From c18118d604926e462ff9ae5cfebe8bae044b462a Mon Sep 17 00:00:00 2001 From: xuqssq Date: Tue, 14 Jan 2025 22:34:51 +0800 Subject: [PATCH 1/9] dep --- src/index.css | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/index.css b/src/index.css index b28b04f..e69de29 100644 --- a/src/index.css +++ b/src/index.css @@ -1,3 +0,0 @@ - - - From 1eb2e0dd57f2ea27bc702d6a96fd29a9a5c55f83 Mon Sep 17 00:00:00 2001 From: qian Date: Wed, 15 Jan 2025 10:10:30 +0800 Subject: [PATCH 2/9] dep --- src/index.css | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/index.css b/src/index.css index e69de29..139597f 100644 --- a/src/index.css +++ b/src/index.css @@ -0,0 +1,2 @@ + + From 3d7b8d705dae24d8739debed163065b1cb451e29 Mon Sep 17 00:00:00 2001 From: liamzi Date: Wed, 15 Jan 2025 11:08:08 +0800 Subject: [PATCH 3/9] =?UTF-8?q?=E4=BE=A7=E8=BE=B9=E6=A0=8F=E9=80=89?= =?UTF-8?q?=E4=B8=AD=E6=95=88=E6=9E=9C=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Layout/Sidebar.jsx | 10 ++++++---- src/components/auth/ProtectedRoute.jsx | 7 +++---- src/pages/home/index.jsx | 11 +++++++++++ src/routes/AppRoutes.jsx | 7 +++---- src/routes/routes.js | 8 +++++++- src/utils/menuUtils.jsx | 2 +- 6 files changed, 31 insertions(+), 14 deletions(-) create mode 100644 src/pages/home/index.jsx diff --git a/src/components/Layout/Sidebar.jsx b/src/components/Layout/Sidebar.jsx index 807cfa8..d606931 100644 --- a/src/components/Layout/Sidebar.jsx +++ b/src/components/Layout/Sidebar.jsx @@ -18,9 +18,7 @@ const Sidebar = ({ collapsed }) => { if (!user?.id||user.menukeys?.length===0) return []; return getMenuItems(user?.menukeys || []); }, [user]); -useEffect(()=>{ - console.log(menuClient,'menuClient'); -},[menuClient]) + const defaultOpenKeys = useMemo(() => { const pathSegments = location.pathname.split("/").filter(Boolean); return pathSegments.reduce((acc, _, index) => { @@ -30,6 +28,10 @@ useEffect(()=>{ }, []); }, [location.pathname]); + const selectedKey = useMemo(() => { + return location.pathname; + }, [location.pathname]); + const handleMenuClick = ({ key }) => { navigate(key); }; @@ -48,7 +50,7 @@ useEffect(()=>{ { const { user } = useAuth(); const location = useLocation(); @@ -15,13 +15,12 @@ export const ProtectedRoute = ({ children }) => { return currentPath === key || currentPath.startsWith(`${key}/`); }); - if (!hasPermission ) { - return ; + if (!hasPermission) { + return ; } return children; } - // 如果用户未登录,重定向到登录页 return ; }; diff --git a/src/pages/home/index.jsx b/src/pages/home/index.jsx new file mode 100644 index 0000000..2c46511 --- /dev/null +++ b/src/pages/home/index.jsx @@ -0,0 +1,11 @@ +import React from 'react'; + +const Home = () => { + return ( +
+ 首页 +
+ ); +}; + +export default Home; \ No newline at end of file diff --git a/src/routes/AppRoutes.jsx b/src/routes/AppRoutes.jsx index 287dc18..4f53cb1 100644 --- a/src/routes/AppRoutes.jsx +++ b/src/routes/AppRoutes.jsx @@ -68,8 +68,8 @@ const AppRoutes = () => { + user?.id ? ( + ) : ( ) @@ -84,10 +84,9 @@ const AppRoutes = () => { } > - {/* 默认重定向到服务管理页面 */} } + element={} /> {renderRoutes(allRoutes)} } /> diff --git a/src/routes/routes.js b/src/routes/routes.js index 23cb9c8..93a01af 100644 --- a/src/routes/routes.js +++ b/src/routes/routes.js @@ -1,7 +1,13 @@ import { lazy } from "react"; -// 所有可用的路由配置 export const allRoutes = [ + { + path: "/home", + component: lazy(() => import("@/pages/home")), + name: "首页", + hidden: true, + key: "home", + }, { path: "dashboard", component: lazy(() => import("@/pages/Dashboard")), diff --git a/src/utils/menuUtils.jsx b/src/utils/menuUtils.jsx index 19771bc..9119a75 100644 --- a/src/utils/menuUtils.jsx +++ b/src/utils/menuUtils.jsx @@ -39,7 +39,7 @@ const generateMenuItems = (routes, menuKeys = [], parentPath = "") => { const icon = route.icon && ; const menuItem = { - key: route.key, // 使用 key 而不是 fullPath + key: fullPath, icon, label: route.name, }; From 48733f3b7c9453f7abaae6cfce3f108c824b0ce7 Mon Sep 17 00:00:00 2001 From: liamzi Date: Wed, 15 Jan 2025 11:21:49 +0800 Subject: [PATCH 4/9] feat --- src/pages/company/quotation/view/index.jsx | 97 ++++++++++++---------- src/routes/routes.js | 18 +++- 2 files changed, 70 insertions(+), 45 deletions(-) diff --git a/src/pages/company/quotation/view/index.jsx b/src/pages/company/quotation/view/index.jsx index 333b4bf..4adfeda 100644 --- a/src/pages/company/quotation/view/index.jsx +++ b/src/pages/company/quotation/view/index.jsx @@ -42,61 +42,70 @@ const QuotationPreview = () => { // PDF导出函数 const exportPDF = async () => { try { - // 显示加载中 message.loading('正在生成PDF...', 0); - - // 获取要导出的DOM元素 const element = document.getElementById('quotation-content'); - // 使用html2canvas将DOM转换为canvas - const canvas = await html2canvas(element, { - scale: 2, // 提高清晰度 - useCORS: true, // 允许加载跨域图片 - logging: false, // 关闭日志 - backgroundColor: '#ffffff' // 设置背景色 + // A4 尺寸(单位:pt,1mm ≈ 2.83pt) + const a4Width = 595.28; + const a4Height = 841.89; + const margin = 40; // 页边距(pt) + + // 初始化 PDF + const pdf = new jsPDF({ + unit: 'pt', + format: 'a4', }); - // 获取canvas的宽高 - const imgWidth = 210; // A4纸的宽度(mm) - const pageHeight = 297; // A4纸的高度(mm) - const imgHeight = canvas.height * imgWidth / canvas.width; - const pdfWidth = imgWidth; - const pdfHeight = imgHeight; - - // 将canvas转为图片 - const imgData = canvas.toDataURL('image/jpeg', 1.0); - - // 初始化jsPDF - const pdf = new jsPDF('p', 'mm', 'a4'); + // 获取内容的总高度 + let remainingContent = element.cloneNode(true); + document.body.appendChild(remainingContent); + remainingContent.style.width = `${a4Width - 2 * margin}pt`; + const totalHeight = remainingContent.offsetHeight; - // 计算分页 - let position = 0; - let currentPage = 1; - - while (position < pdfHeight) { - // 添加图片到PDF - pdf.addImage( - imgData, - 'JPEG', - 0, // x坐标 - position === 0 ? 0 : -position, // y坐标 - pdfWidth, // 图片宽度 - pdfHeight // 图片高度 - ); - - position += pageHeight; - - // 如果还有内容,添加新页面 - if (position < pdfHeight) { + // 计算需要的页数 + const contentHeight = a4Height - 2 * margin; + const pageCount = Math.ceil(totalHeight / contentHeight); + + // 逐页处理内容 + for (let i = 0; i < pageCount; i++) { + if (i > 0) { pdf.addPage(); - currentPage++; } + + // 创建当前页的容器 + const pageDiv = document.createElement('div'); + pageDiv.style.width = `${a4Width - 2 * margin}pt`; + pageDiv.style.height = `${contentHeight}pt`; + pageDiv.style.position = 'absolute'; + pageDiv.style.top = '0'; + pageDiv.style.left = '0'; + pageDiv.style.overflow = 'hidden'; + + // 克隆原始内容 + const contentClone = element.cloneNode(true); + contentClone.style.transform = `translateY(-${i * contentHeight}pt)`; + pageDiv.appendChild(contentClone); + document.body.appendChild(pageDiv); + + // 转换为图片并添加到 PDF + const canvas = await html2canvas(pageDiv, { + scale: 2, + useCORS: true, + logging: false, + backgroundColor: '#ffffff', + }); + + const imgData = canvas.toDataURL('image/jpeg', 1.0); + pdf.addImage(imgData, 'JPEG', margin, margin, a4Width - 2 * margin, contentHeight); + + // 清理临时元素 + document.body.removeChild(pageDiv); } - // 保存PDF + // 清理克隆的元素 + document.body.removeChild(remainingContent); + pdf.save(`${quotation.attributes.quataName || '报价单'}.pdf`); - - // 关闭加载提示 message.destroy(); message.success('PDF导出成功!'); } catch (error) { diff --git a/src/routes/routes.js b/src/routes/routes.js index 93a01af..ae7f2c2 100644 --- a/src/routes/routes.js +++ b/src/routes/routes.js @@ -81,6 +81,15 @@ export const allRoutes = [ hidden: true, key: "company/quotaInfo", }, + { + path: "quotaInfo/preview/:id?", + hidden: true, + component: lazy(() => import("@/pages/company/quotation/view")), + name: "报价单预览", + icon: "file", + key: "company/quotaInfo/preview", + }, + { path: "project", component: lazy(() => import("@/pages/company/project")), @@ -140,7 +149,14 @@ export const allRoutes = [ icon: "appstore", hidden: true, key: "company/projectView", - } + }, + { + path: "templateItemManage", + component: lazy(() => import("@/pages/company/service/itemsManange")), + name: "资源类型", + icon: "container", + key: "company/templateItem", + }, ] } ]; From c24c26c39b0e70cd91515c424cd570438915b9b1 Mon Sep 17 00:00:00 2001 From: qian Date: Wed, 15 Jan 2025 11:24:11 +0800 Subject: [PATCH 5/9] dep --- src/index.css | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/index.css b/src/index.css index 139597f..e69de29 100644 --- a/src/index.css +++ b/src/index.css @@ -1,2 +0,0 @@ - - From a4743e5bb3883eef646a835bed0aa6292d9f34ba Mon Sep 17 00:00:00 2001 From: liamzi Date: Wed, 15 Jan 2025 11:25:49 +0800 Subject: [PATCH 6/9] fix --- src/components/Layout/Sidebar.jsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/Layout/Sidebar.jsx b/src/components/Layout/Sidebar.jsx index d606931..4d4543b 100644 --- a/src/components/Layout/Sidebar.jsx +++ b/src/components/Layout/Sidebar.jsx @@ -54,6 +54,7 @@ const Sidebar = ({ collapsed }) => { defaultOpenKeys={defaultOpenKeys} items={menuClient} onClick={handleMenuClick} + style={{ overflow: 'auto' }} /> ); From 81008d0159d022097139dc79e54102f8fdcc48fa Mon Sep 17 00:00:00 2001 From: liamzi Date: Wed, 15 Jan 2025 15:31:08 +0800 Subject: [PATCH 7/9] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=97=A0=E6=9D=83?= =?UTF-8?q?=E9=99=90=E6=8F=90=E9=86=92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hooks/resource/useResource.js | 6 +--- src/hooks/supabaseService.js | 29 ++++++++++++------- src/pages/company/project/detail/index.jsx | 3 +- src/pages/company/quotation/detail/index.jsx | 5 +++- .../detail/components/ProjectTemplate.jsx | 4 +-- .../detail/components/QuotationTemplate.jsx | 10 ++----- .../detail/components/TaskTemplate.jsx | 3 +- src/pages/company/service/detail/index.jsx | 2 -- src/pages/company/service/index.jsx | 6 ++-- src/pages/company/supplier/detail/index.jsx | 11 ++++--- src/pages/company/task/index.jsx | 10 +++---- src/pages/resource/role/index.jsx | 21 +++++++++----- src/routes/routes.js | 8 +++++ 13 files changed, 68 insertions(+), 50 deletions(-) diff --git a/src/hooks/resource/useResource.js b/src/hooks/resource/useResource.js index f131734..d1fb8b1 100644 --- a/src/hooks/resource/useResource.js +++ b/src/hooks/resource/useResource.js @@ -24,8 +24,6 @@ export const useResources = (initialPagination, initialSorter, type) => { setCurrentPagination(newPagination); setCurrentSorter(newSorter); - console.log(params.searchQuery,'params.searchQuery'); - const { data, total: newTotal } = await resourceService.getResources({ page: newPagination.current, pageSize: newPagination.pageSize, @@ -77,8 +75,6 @@ export const useResources = (initialPagination, initialSorter, type) => { const deleteResource = async (id) => { try { const data= await resourceService.deleteResource(id, type); - console.log(data,data.length,'data'); - if(data?.length>0){ const newCurrent = resources.length === 1 && currentPagination.current > 1 @@ -87,7 +83,7 @@ export const useResources = (initialPagination, initialSorter, type) => { await fetchResources({ current: newCurrent }); message.success("删除成功"); }else{ - throw new Error("no level"); + throw new Error("暂无权限"); } } catch (error) { throw error; diff --git a/src/hooks/supabaseService.js b/src/hooks/supabaseService.js index 4b0790a..926ca6c 100644 --- a/src/hooks/supabaseService.js +++ b/src/hooks/supabaseService.js @@ -1,5 +1,5 @@ import { supabase } from "@/config/supabase"; - +import { message } from "antd"; class SupabaseService { async select(table, options = {}) { try { @@ -60,12 +60,22 @@ class SupabaseService { .from(table) .insert(data) .select(); + if (error) { + if (error.code === '42501' || error.status === 403) { + throw new Error('暂无权限:您没有执行此操作的权限'); - if (error) throw error; + } + throw new Error(error.message || '数据库操作失败'); + } + if (result?.length === 0) { + throw new Error('暂无权限:您没有执行此操作的权限'); + } return result; } catch (error) { - console.error(`Error inserting into ${table}:`, error.message); - throw error; + // 确保错误始终是 Error 对象 + const errorMessage = error instanceof Error ? error.message : String(error); + console.error(`Insert error for table ${table}:`, errorMessage); + throw new Error(errorMessage); } } @@ -83,22 +93,21 @@ class SupabaseService { } const { data, error } = await query.select(); - + if(data.length===0) throw '暂无权限' ; if (error) throw error; return data; } catch (error) { - console.error(`Error updating ${table}:`, error.message); - throw error; + throw new Error('更新失败'); } } // 通用 DELETE 请求 async delete(table, match) { try { - const { error } = await supabase.from(table).delete().match(match); - + const { data,error } = await supabase.from(table).delete().match(match).select(); + if(data.length===0) throw '暂无权限'; if (error) throw error; - return true; + return data; } catch (error) { console.error(`Error deleting from ${table}:`, error.message); throw error; diff --git a/src/pages/company/project/detail/index.jsx b/src/pages/company/project/detail/index.jsx index fd8382a..294c4ff 100644 --- a/src/pages/company/project/detail/index.jsx +++ b/src/pages/company/project/detail/index.jsx @@ -228,8 +228,7 @@ export default function ProjectDetail() { .select(); } - if (result.error) throw result.error; - + if (result.error||result.data.length===0) throw 'error'; message.success("保存成功"); navigate("/company/project"); } catch (error) { diff --git a/src/pages/company/quotation/detail/index.jsx b/src/pages/company/quotation/detail/index.jsx index 63809ab..97c6061 100644 --- a/src/pages/company/quotation/detail/index.jsx +++ b/src/pages/company/quotation/detail/index.jsx @@ -268,7 +268,10 @@ const QuotationForm = () => { } if (result.error) throw result.error; - + if(result.length===0){ + message.error('暂无权限'); + return; + }; message.success("保存成功"); navigate("/company/quotation"); } catch (error) { diff --git a/src/pages/company/service/detail/components/ProjectTemplate.jsx b/src/pages/company/service/detail/components/ProjectTemplate.jsx index 31a9f8c..89ed9ad 100644 --- a/src/pages/company/service/detail/components/ProjectTemplate.jsx +++ b/src/pages/company/service/detail/components/ProjectTemplate.jsx @@ -8,9 +8,9 @@ const ProjectTemplate = ({ form, id, isView }) => { layout="vertical" disabled={isView} > - {/* 专案模板特有的字段和组件 */} + - {/* 项目阶段、时间线等内容 */} + ); diff --git a/src/pages/company/service/detail/components/QuotationTemplate.jsx b/src/pages/company/service/detail/components/QuotationTemplate.jsx index 52f48ce..aaa8f44 100644 --- a/src/pages/company/service/detail/components/QuotationTemplate.jsx +++ b/src/pages/company/service/detail/components/QuotationTemplate.jsx @@ -103,21 +103,17 @@ const QuotationTemplate = ({ id, isView, onCancel,isEdit }) => { }; if (id) { - // 更新 - await supabaseService.update('resources', - { id }, - serviceData - ); + await supabaseService.update('resources', { id }, serviceData); } else { - // 新增 await supabaseService.insert('resources', serviceData); } message.success("保存成功"); onCancel(); } catch (error) { + const errorMsg = error instanceof Error ? error.message : '保存失败'; console.error("保存失败:", error); - message.error("保存失败"); + message.error(errorMsg); } finally { setLoading(false); } diff --git a/src/pages/company/service/detail/components/TaskTemplate.jsx b/src/pages/company/service/detail/components/TaskTemplate.jsx index 72e384c..b9104b4 100644 --- a/src/pages/company/service/detail/components/TaskTemplate.jsx +++ b/src/pages/company/service/detail/components/TaskTemplate.jsx @@ -104,15 +104,14 @@ const TaskTemplate = ({ id, isView, onCancel,isEdit }) => { serviceData ); } else { - // 新增 await supabaseService.insert('resources', serviceData); } message.success("保存成功"); onCancel(); } catch (error) { + message.error('保存失败'); console.error("保存失败:", error); - message.error("保存失败"); } finally { setLoading(false); } diff --git a/src/pages/company/service/detail/index.jsx b/src/pages/company/service/detail/index.jsx index 81d37ed..ff2092a 100644 --- a/src/pages/company/service/detail/index.jsx +++ b/src/pages/company/service/detail/index.jsx @@ -7,7 +7,6 @@ import TaskTemplate from './components/TaskTemplate'; const { Title } = Typography; -// 模板类型配置 const TEMPLATE_CONFIG = { quotation: { title: '报价单模板', @@ -36,7 +35,6 @@ const ServiceForm = () => { if (!currentTemplate) { return
无效的模板类型
; } - return (
{ setData(services || []); } catch (error) { console.error("获取服务模板失败:", error); - message.error("获取服���模板失败"); + message.error("获取服务模板失败"); } finally { setLoading(false); } @@ -127,7 +127,7 @@ const ServicePage = () => { fetchServices(); } catch (error) { console.error("删除失败:", error); - message.error("删除失败"); + message.error(error); } }; @@ -173,7 +173,7 @@ const ServicePage = () => { } } catch (error) { console.error("保存失败:", error); - message.error("保存失败"); + message.error(error); } }; diff --git a/src/pages/company/supplier/detail/index.jsx b/src/pages/company/supplier/detail/index.jsx index 18adcb3..78a46ec 100644 --- a/src/pages/company/supplier/detail/index.jsx +++ b/src/pages/company/supplier/detail/index.jsx @@ -1,5 +1,5 @@ import React, { useState, useEffect } from 'react'; -import { Form, Input, Select, Button, Space, Card, Typography } from 'antd'; +import { Form, Input, Select, Button, Space, Card, Typography, message } from 'antd'; import { ArrowLeftOutlined, SaveOutlined } from '@ant-design/icons'; import { supabase } from '@/config/supabase'; import { useNavigate, useParams, useSearchParams } from 'react-router-dom'; @@ -22,9 +22,8 @@ const SupplierForm = () => { .select('*') .eq('id', id) .single(); - if (error) throw error; - + if (id) { // 设置表单初始值 form.setFieldsValue({ @@ -74,10 +73,14 @@ const SupplierForm = () => { .insert([supplierData]) .select(); } - + if(result.data.length===0){ + message.error('暂无权限'); + return; + }; if (result.error) throw result.error; navigate('/company/supplier'); } catch (error) { + message.error('暂无权限'); console.error('保存失败:', error); } }; diff --git a/src/pages/company/task/index.jsx b/src/pages/company/task/index.jsx index fb89a1b..96a6112 100644 --- a/src/pages/company/task/index.jsx +++ b/src/pages/company/task/index.jsx @@ -251,9 +251,7 @@ const TaskPage = () => { setLoading(true); const newAttributes = JSON.parse(JSON.stringify(record.attributes)); - // 修改任务名称,添加"副本"标识 newAttributes.taskName = `${newAttributes.taskName} (副本)`; - const { data, error } = await supabase .from("resources") .insert([ @@ -261,10 +259,12 @@ const TaskPage = () => { type: "task", attributes: newAttributes, }, - ]); - + ]).select() + if(!data||data?.length===0){ + message.error('暂无权限'); + return; + }; if (error) throw error; - message.success("复制成功"); fetchTasks(); // 刷新列表 } catch (error) { diff --git a/src/pages/resource/role/index.jsx b/src/pages/resource/role/index.jsx index 88b1a36..d738048 100644 --- a/src/pages/resource/role/index.jsx +++ b/src/pages/resource/role/index.jsx @@ -1,5 +1,5 @@ import React, { useState, useEffect } from 'react'; -import { Card, App, Table, Button, Modal, Form, Select, message, Input, Divider } from 'antd'; +import { Card, App, Table, Button, Modal, Form, Select, message, Input, Divider, Popconfirm } from 'antd'; import { PlusOutlined, DeleteOutlined, EditOutlined } from '@ant-design/icons'; import { supabase } from '@/config/supabase'; @@ -377,12 +377,19 @@ export default function PermissionManagement() { setModalVisible(true); }} /> -
), }, diff --git a/src/routes/routes.js b/src/routes/routes.js index ae7f2c2..9e59c97 100644 --- a/src/routes/routes.js +++ b/src/routes/routes.js @@ -119,6 +119,14 @@ export const allRoutes = [ icon: "appstore", key: "company/serviceTemplate", }, + { + path: "serviceTemplateInfo/:id?", + hidden: true, + component: lazy(() => import("@/pages/company/service/detail")), + name: "服务模版详情", + icon: "container", + key: "company/serviceTemplateInfo", + }, { path: "supplier", component: lazy(() => import("@/pages/company/supplier")), From 7775333603e755f5cb1deed21ed37c8cc952a831 Mon Sep 17 00:00:00 2001 From: xuqssq Date: Wed, 15 Jan 2025 23:05:11 +0800 Subject: [PATCH 8/9] dep --- src/index.css | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/index.css b/src/index.css index e69de29..139597f 100644 --- a/src/index.css +++ b/src/index.css @@ -0,0 +1,2 @@ + + From 8dccf8e554eefcfa832eca45be35be4dddad3cb8 Mon Sep 17 00:00:00 2001 From: liamzi Date: Thu, 16 Jan 2025 18:41:30 +0800 Subject: [PATCH 9/9] =?UTF-8?q?=E9=BB=91=E6=9A=97=E6=A8=A1=E5=BC=8Ffix?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/ChatAi/index.jsx | 4 +- src/components/Layout/Sidebar.jsx | 3 +- src/components/SectionList/index.jsx | 56 +++++++-------- src/components/TaskList/index.jsx | 4 +- src/components/difyChatAi/index.jsx | 6 +- src/index.css | 2 - src/pages/company/customer/index.jsx | 2 +- src/pages/company/project/detail/index.jsx | 2 +- src/pages/company/project/index.jsx | 2 +- src/pages/company/quotation/detail/index.jsx | 2 +- src/pages/company/quotation/index.jsx | 38 +++++----- src/pages/company/service/detail/index.jsx | 2 +- src/pages/company/service/index.jsx | 10 +-- .../service/itemsManange/classify/index.jsx | 2 +- .../service/itemsManange/unit/index.jsx | 2 +- src/pages/company/supplier/index.jsx | 2 +- src/pages/company/task/detail/index.jsx | 2 +- src/pages/company/task/index.jsx | 6 +- src/pages/marketing/campaign/index.jsx | 8 --- .../marketing/campaign/performance/index.jsx | 34 --------- src/pages/marketing/campaign/plan/index.jsx | 48 ------------- .../project/components/ProjectForm.jsx | 45 ------------ .../marketing/campaign/project/index.jsx | 71 ------------------- src/pages/marketing/communication/index.jsx | 8 --- .../marketing/communication/journey/index.jsx | 40 ----------- .../marketing/communication/list/index.jsx | 48 ------------- .../marketing/communication/preview/index.jsx | 42 ----------- src/pages/marketing/index.jsx | 8 --- src/pages/marketing/template/index.jsx | 43 ----------- .../resource/resourceTask/edit/index.jsx | 2 +- src/pages/resource/resourceTask/index.jsx | 2 +- src/pages/resource/role/index.jsx | 13 ++-- .../team/components/MembershipTable.jsx | 2 +- .../resource/team/components/TeamTable.jsx | 3 +- src/pages/resource/team/index.jsx | 2 +- src/styles/main.scss | 54 ++++++++------ 36 files changed, 115 insertions(+), 505 deletions(-) delete mode 100644 src/pages/marketing/campaign/index.jsx delete mode 100644 src/pages/marketing/campaign/performance/index.jsx delete mode 100644 src/pages/marketing/campaign/plan/index.jsx delete mode 100644 src/pages/marketing/campaign/project/components/ProjectForm.jsx delete mode 100644 src/pages/marketing/campaign/project/index.jsx delete mode 100644 src/pages/marketing/communication/index.jsx delete mode 100644 src/pages/marketing/communication/journey/index.jsx delete mode 100644 src/pages/marketing/communication/list/index.jsx delete mode 100644 src/pages/marketing/communication/preview/index.jsx delete mode 100644 src/pages/marketing/index.jsx delete mode 100644 src/pages/marketing/template/index.jsx diff --git a/src/components/ChatAi/index.jsx b/src/components/ChatAi/index.jsx index 4587fd0..1e764d9 100644 --- a/src/components/ChatAi/index.jsx +++ b/src/components/ChatAi/index.jsx @@ -202,13 +202,13 @@ export default function ChatAIDrawer({ open, onClose, onExport }) { placeholder="请输入您的问题..." onChange={handleInputChange} disabled={isLoading} - className="flex-1 rounded-lg border-gray-300 hover:border-blue-400 focus:border-blue-600 focus:shadow-blue-100" + className="flex-1 rounded-md " /> diff --git a/src/components/Layout/Sidebar.jsx b/src/components/Layout/Sidebar.jsx index 4d4543b..2d009a1 100644 --- a/src/components/Layout/Sidebar.jsx +++ b/src/components/Layout/Sidebar.jsx @@ -44,7 +44,7 @@ const Sidebar = ({ collapsed }) => { theme={isDarkMode ? "dark" : "light"} width={256} collapsedWidth={80} - className={`app-sidebar ${collapsed ? "collapsed" : ""}`} + className={`app-sidebar ${collapsed ? "collapsed" : ""} overflow-auto`} > { defaultOpenKeys={defaultOpenKeys} items={menuClient} onClick={handleMenuClick} - style={{ overflow: 'auto' }} /> ); diff --git a/src/components/SectionList/index.jsx b/src/components/SectionList/index.jsx index 97411f4..588dea5 100644 --- a/src/components/SectionList/index.jsx +++ b/src/components/SectionList/index.jsx @@ -187,50 +187,44 @@ const SectionList = ({ {availableSections.map((section) => (
handleUseTemplate(section, add)} >
-

+

{section.attributes.name}

-
+
{section.attributes.items?.length || 0} 个项目
-
- {(section.attributes.items || []) - .slice(0, 3) - .map((item, index) => ( -
- - {item.name} - - - {formatExchangeRate(currentCurrency, item.price)} - -
- ))} +
+ {(section.attributes.items || []).slice(0, 3).map((item, index) => ( +
+ + {item.name} + + + {formatExchangeRate(currentCurrency, item.price)} + +
+ ))} {(section.attributes.items || []).length > 3 && ( -
+
还有 {section.attributes.items.length - 3} 个项目...
)}
-
- 总金额 - +
+ 总金额 + {formatExchangeRate( currentCurrency, (section.attributes.items || []).reduce( - (sum, item) => - sum + (item.price * (item.quantity || 1) || 0), + (sum, item) => sum + (item.price * (item.quantity || 1) || 0), 0 ) )} @@ -241,12 +235,12 @@ const SectionList = ({ ))}
-
+
@@ -256,7 +250,7 @@ const SectionList = ({
-

+

暂无可用模板

-

+

您可以选择创建一个自定义模块开始使用

diff --git a/src/components/TaskList/index.jsx b/src/components/TaskList/index.jsx index d7e7122..e5bafcd 100644 --- a/src/components/TaskList/index.jsx +++ b/src/components/TaskList/index.jsx @@ -199,7 +199,7 @@ const SectionList = ({ form, isView, formValues, type }) => { {availableSections.map((section) => (
handleUseTemplate(section, add)} >
@@ -241,7 +241,7 @@ const SectionList = ({ form, isView, formValues, type }) => { ))}
-
+
diff --git a/src/index.css b/src/index.css index 139597f..e69de29 100644 --- a/src/index.css +++ b/src/index.css @@ -1,2 +0,0 @@ - - diff --git a/src/pages/company/customer/index.jsx b/src/pages/company/customer/index.jsx index 2df9258..008ef48 100644 --- a/src/pages/company/customer/index.jsx +++ b/src/pages/company/customer/index.jsx @@ -158,7 +158,7 @@ const CustomerPage = () => { columns={columns} dataSource={customers} rowKey="id" - scroll={{ x: true }} + scroll={{ x: true}} loading={loading} onChange={handleTableChange} pagination={{ diff --git a/src/pages/company/project/detail/index.jsx b/src/pages/company/project/detail/index.jsx index 294c4ff..61254ca 100644 --- a/src/pages/company/project/detail/index.jsx +++ b/src/pages/company/project/detail/index.jsx @@ -256,7 +256,7 @@ export default function ProjectDetail() { }, [id, templateId]); return ( -
+
{ columns={columns} dataSource={projects} rowKey="id" - scroll={{ x: true }} + scroll={{ x: true}} loading={loadingProjects} onChange={handleTableChange} pagination={{ diff --git a/src/pages/company/quotation/detail/index.jsx b/src/pages/company/quotation/detail/index.jsx index 97c6061..9c70388 100644 --- a/src/pages/company/quotation/detail/index.jsx +++ b/src/pages/company/quotation/detail/index.jsx @@ -362,7 +362,7 @@ const QuotationForm = () => { }; return ( -
+
{ columns={columns} dataSource={quotations} rowKey="id" - scroll={{ x: true }} + scroll={{ x: true}} loading={loadingQuotations} onChange={handleTableChange} pagination={{ @@ -405,7 +405,7 @@ useEffect(()=>{ , @@ -414,28 +414,28 @@ useEffect(()=>{ type="primary" disabled={!selectedTemplateId} onClick={handleConfirm} - className="gap-2 px-6 rounded-full bg-blue-600 hover:bg-blue-700" + className="gap-2 px-6 rounded-full " > 使用选中模板 , ]} width={900} - className="template-modal" + className="template-modal " > {loading ? ( -
+
) : templates.length === 0 ? ( - + 暂无可用模板} /> ) : ( -
+
{getTemplatesByCategory().map((group, groupIndex) => (
-

+

{group.name} - + ({group.templates.length})

@@ -450,18 +450,18 @@ useEffect(()=>{ relative p-6 rounded-xl cursor-pointer transition-all duration-200 ${ selectedTemplateId === template.id - ? "ring-2 ring-blue-500 bg-blue-50/40" - : "hover:shadow-lg border border-gray-200 hover:border-blue-200" + ? "ring-2 ring-blue-500 dark:ring-blue-400 bg-blue-50/40 dark:bg-blue-900/30" + : "hover:shadow-lg border border-gray-200 dark:border-gray-700 hover:border-blue-200 dark:hover:border-blue-700" } - transform hover:-translate-y-1 + transform hover:-translate-y-1 dark:bg-gray-800 `} >
-

+

{template.attributes.templateName}

-

+

{template.attributes.description || "暂无描述"}

@@ -475,16 +475,16 @@ useEffect(()=>{ rounded-lg p-3 text-sm border ${ selectedTemplateId === template.id - ? "bg-white border-blue-200" - : "bg-gray-50 border-gray-100" + ? "bg-white dark:bg-gray-700 border-blue-200 dark:border-blue-600" + : "bg-gray-50 dark:bg-gray-800 border-gray-100 dark:border-gray-700" } `} >
- + {section.sectionName} - + {section.items.length}项
@@ -494,7 +494,7 @@ useEffect(()=>{ {selectedTemplateId === template.id && (
-
+
{ return
无效的模板类型
; } return ( -
+
{ title: "名称", dataIndex: "name", key: "name", - width: "15%", render: (text, item, index) => { const isEditing = editingKey === `${record.id}-${section.key}-${index}`; @@ -286,7 +285,6 @@ const ServicePage = () => { title: "单位", dataIndex: "unit", key: "unit", - width: "10%", render: (text, item, index) => { const isEditing = editingKey === `${record.id}-${section.key}-${index}`; @@ -320,7 +318,6 @@ const ServicePage = () => { title: "单价", dataIndex: "price", key: "price", - width: "10%", render: (text, item, index) => { const isEditing = editingKey === `${record.id}-${section.key}-${index}`; @@ -343,7 +340,6 @@ const ServicePage = () => { title: "数量", dataIndex: "quantity", key: "quantity", - width: "10%", render: (text, item, index) => { const isEditing = editingKey === `${record.id}-${section.key}-${index}`; @@ -677,7 +673,7 @@ const ServicePage = () => {
{ title: "模板名称", dataIndex: ["attributes", "templateName"], key: "templateName", - className: "min-w-[200px]", }, { title: "模板类型", @@ -766,6 +761,7 @@ const ServicePage = () => { title: "创建时间", dataIndex: "created_at", key: "created_at", + width: 220, render: (text) => new Date(text).toLocaleString(), sorter: (a, b) => new Date(a.created_at) - new Date(b.created_at), }, @@ -858,7 +854,7 @@ const ServicePage = () => {
{
{
{ } >
+
{ } - className="h-full w-full overflow-auto dark:bg-gray-800 dark:border-gray-700" + className="h-full w-full overflow-auto " extra={
- - ); -}; - -export default CampaignPlan; \ No newline at end of file diff --git a/src/pages/marketing/campaign/project/components/ProjectForm.jsx b/src/pages/marketing/campaign/project/components/ProjectForm.jsx deleted file mode 100644 index d38e869..0000000 --- a/src/pages/marketing/campaign/project/components/ProjectForm.jsx +++ /dev/null @@ -1,45 +0,0 @@ -import React from 'react'; -import { Form, Input, DatePicker, Select } from 'antd'; -import { STATUS } from '@/constants/status'; - -export const ProjectForm = ({ form }) => ( - - - - - - - - {Object.values(STATUS).map(status => ( - - {status} - - ))} - - - -); \ No newline at end of file diff --git a/src/pages/marketing/campaign/project/index.jsx b/src/pages/marketing/campaign/project/index.jsx deleted file mode 100644 index b95f772..0000000 --- a/src/pages/marketing/campaign/project/index.jsx +++ /dev/null @@ -1,71 +0,0 @@ -import React, { useState } from 'react'; -import { Card, Modal, Form } from 'antd'; -import { PageHeader } from '@/components/common/PageHeader'; -import { BaseTable } from '@/components/common/BaseTable'; -import { ProjectForm } from './components/ProjectForm'; -import { useProjectData } from './hooks/useProjectData'; -import { getStatusColumn, getDateColumn } from '@/utils/tableColumns'; - -const CampaignProject = () => { - const [form] = Form.useForm(); - const [visible, setVisible] = useState(false); - const { loading, data, pagination, loadData } = useProjectData(); - - const columns = [ - { - title: '专案名称', - dataIndex: 'name', - key: 'name', - }, - { - title: '负责人', - dataIndex: 'manager', - key: 'manager', - }, - getDateColumn('开始日期', 'startDate'), - getStatusColumn(), - ]; - - const handleAdd = () => { - setVisible(true); - }; - - const handleSubmit = async () => { - try { - const values = await form.validateFields(); - console.log('Success:', values); - setVisible(false); - form.resetFields(); - loadData(); - } catch (error) { - console.error('Failed:', error); - } - }; - - return ( - - - - setVisible(false)} - > - - - - ); -}; - -export default CampaignProject; \ No newline at end of file diff --git a/src/pages/marketing/communication/index.jsx b/src/pages/marketing/communication/index.jsx deleted file mode 100644 index fb3699d..0000000 --- a/src/pages/marketing/communication/index.jsx +++ /dev/null @@ -1,8 +0,0 @@ -import React from 'react'; -import { Outlet } from 'react-router-dom'; - -const Communication = () => { - return ; -}; - -export default Communication; \ No newline at end of file diff --git a/src/pages/marketing/communication/journey/index.jsx b/src/pages/marketing/communication/journey/index.jsx deleted file mode 100644 index 864d35a..0000000 --- a/src/pages/marketing/communication/journey/index.jsx +++ /dev/null @@ -1,40 +0,0 @@ -import React from 'react'; -import { Card, Timeline, Button } from 'antd'; -import { ClockCircleOutlined } from '@ant-design/icons'; - -const CommunicationJourney = () => { - return ( - 导出记录 - } - > - , - children: '客户查看邮件 2023-10-25 11:00:00', - }, - { - color: 'red', - children: '系统提醒跟进 2023-10-25 14:00:00', - }, - { - children: '完成跟进 2023-10-25 16:00:00', - }, - ]} - /> - - ); -}; - -export default CommunicationJourney; \ No newline at end of file diff --git a/src/pages/marketing/communication/list/index.jsx b/src/pages/marketing/communication/list/index.jsx deleted file mode 100644 index 589990a..0000000 --- a/src/pages/marketing/communication/list/index.jsx +++ /dev/null @@ -1,48 +0,0 @@ -import React from 'react'; -import { Card, Table, Button, Input } from 'antd'; -import { PlusOutlined } from '@ant-design/icons'; - -const { Search } = Input; - -const CommunicationList = () => { - const columns = [ - { - title: '名单名称', - dataIndex: 'name', - key: 'name', - }, - { - title: '联系人数量', - dataIndex: 'contactCount', - key: 'contactCount', - }, - { - title: '创建日期', - dataIndex: 'createdAt', - key: 'createdAt', - }, - { - title: '更新日期', - dataIndex: 'updatedAt', - key: 'updatedAt', - }, - ]; - - return ( - }> - 新增名单 - - } - > -
- -
-
- - ); -}; - -export default CommunicationList; \ No newline at end of file diff --git a/src/pages/marketing/communication/preview/index.jsx b/src/pages/marketing/communication/preview/index.jsx deleted file mode 100644 index 6c97dfa..0000000 --- a/src/pages/marketing/communication/preview/index.jsx +++ /dev/null @@ -1,42 +0,0 @@ -import React from 'react'; -import { Card, Tabs, Button } from 'antd'; -import { SendOutlined } from '@ant-design/icons'; - -const CommunicationPreview = () => { - const items = [ - { - key: '1', - label: '邮件预览', - children: ( -
-

邮件主题

-
邮件内容预览区域
-
- ), - }, - { - key: '2', - label: '短信预览', - children: ( -
-
短信内容预览区域
-
- ), - }, - ]; - - return ( - }> - 发送测试 - - } - > - - - ); -}; - -export default CommunicationPreview; \ No newline at end of file diff --git a/src/pages/marketing/index.jsx b/src/pages/marketing/index.jsx deleted file mode 100644 index af40925..0000000 --- a/src/pages/marketing/index.jsx +++ /dev/null @@ -1,8 +0,0 @@ -import React from 'react'; -import { Outlet } from 'react-router-dom'; - -const MarketingCenter = () => { - return ; -}; - -export default MarketingCenter; \ No newline at end of file diff --git a/src/pages/marketing/template/index.jsx b/src/pages/marketing/template/index.jsx deleted file mode 100644 index 3eec094..0000000 --- a/src/pages/marketing/template/index.jsx +++ /dev/null @@ -1,43 +0,0 @@ -import React from 'react'; -import { Card, Table, Button } from 'antd'; -import { PlusOutlined } from '@ant-design/icons'; - -const TemplatePage = () => { - const columns = [ - { - title: '模版名称', - dataIndex: 'name', - key: 'name', - }, - { - title: '类型', - dataIndex: 'type', - key: 'type', - }, - { - title: '创建日期', - dataIndex: 'createdAt', - key: 'createdAt', - }, - { - title: '状态', - dataIndex: 'status', - key: 'status', - }, - ]; - - return ( - }> - 新增模版 - - } - > -
- - ); -}; - -export default TemplatePage; \ No newline at end of file diff --git a/src/pages/resource/resourceTask/edit/index.jsx b/src/pages/resource/resourceTask/edit/index.jsx index d31a20e..6d964f8 100644 --- a/src/pages/resource/resourceTask/edit/index.jsx +++ b/src/pages/resource/resourceTask/edit/index.jsx @@ -261,7 +261,7 @@ const ResourceTaskForm = () => { bordered={false} >
{ } >
(
handleDelete(record.id)} >
), @@ -522,7 +523,7 @@ export default function PermissionManagement() { return ( - + { setModalType('add'); @@ -538,12 +539,14 @@ export default function PermissionManagement() { />
{
{ const editable = isEditing(record); return editable ? ( @@ -180,7 +181,7 @@ export const TeamTable = ({ tableLoading,pagination,dataSource, onTableChange,on return (
{ return ( - +