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 c29039c..8c56ee2 100644 --- a/src/components/Layout/Sidebar.jsx +++ b/src/components/Layout/Sidebar.jsx @@ -44,6 +44,10 @@ const Sidebar = ({ collapsed }) => { }, []); }, [location.pathname]); + const selectedKey = useMemo(() => { + return location.pathname; + }, [location.pathname]); + const handleMenuClick = ({ key }) => { navigate(key); }; @@ -56,13 +60,17 @@ const Sidebar = ({ collapsed }) => { theme={isDarkMode ? "dark" : "light"} width={256} collapsedWidth={80} - className={`app-sidebar ${collapsed ? "collapsed" : ""}`} + className={`app-sidebar ${collapsed ? "collapsed" : ""} overflow-auto`} > >>>>>> 8dccf8e554eefcfa832eca45be35be4dddad3cb8 defaultOpenKeys={defaultOpenKeys} items={menuClient} onClick={handleMenuClick} 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/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/index.css b/src/index.css index b28b04f..e69de29 100644 --- a/src/index.css +++ b/src/index.css @@ -1,3 +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 fd8382a..61254ca 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) { @@ -257,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 63809ab..9c70388 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) { @@ -359,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 && (
-
+
{ // 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/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..df4cfb1 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,9 +35,8 @@ 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); } }; @@ -263,7 +263,6 @@ const ServicePage = () => { 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 = () => {
{
{
{ .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/supplier/index.jsx b/src/pages/company/supplier/index.jsx index fd82331..78bb501 100644 --- a/src/pages/company/supplier/index.jsx +++ b/src/pages/company/supplier/index.jsx @@ -144,7 +144,7 @@ const SupplierPage = () => { } >
+
{ 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) { @@ -344,7 +344,7 @@ const TaskPage = () => { } - 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)} + > + +
), }, @@ -515,7 +523,7 @@ export default function PermissionManagement() { return ( - + { setModalType('add'); @@ -531,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 ( - + { + user?.id ? ( + ) : ( ) @@ -84,10 +84,9 @@ const AppRoutes = () => { } > - {/* 默认重定向到服务管理页面 */} } + element={} /> {renderRoutes(allRoutes)} } /> diff --git a/src/routes/routes.js b/src/routes/routes.js index 0dbf67a..23f66d3 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")), @@ -76,13 +82,23 @@ export const allRoutes = [ key: "company/quotaInfo", }, { +<<<<<<< HEAD path: "quotaInfo/preview/:id?", // 添加可选的 id 参数 +======= + path: "quotaInfo/preview/:id?", +>>>>>>> 8dccf8e554eefcfa832eca45be35be4dddad3cb8 hidden: true, component: lazy(() => import("@/pages/company/quotation/view")), name: "报价单预览", icon: "file", +<<<<<<< HEAD key:'company/quotaInfo/preview' }, +======= + key: "company/quotaInfo/preview", + }, + +>>>>>>> 8dccf8e554eefcfa832eca45be35be4dddad3cb8 { path: "project", component: lazy(() => import("@/pages/company/project")), @@ -119,7 +135,10 @@ export const allRoutes = [ name: "服务模版详情", icon: "container", key: "company/serviceTemplateInfo", +<<<<<<< HEAD +======= +>>>>>>> 8dccf8e554eefcfa832eca45be35be4dddad3cb8 }, { path: "supplier", @@ -157,7 +176,11 @@ export const allRoutes = [ component: lazy(() => import("@/pages/company/service/itemsManange")), name: "资源类型", icon: "container", +<<<<<<< HEAD key:'company/templateItemManage' +======= + key: "company/templateItem", +>>>>>>> 8dccf8e554eefcfa832eca45be35be4dddad3cb8 }, ] } diff --git a/src/styles/main.scss b/src/styles/main.scss index 4a175dc..f0e13e7 100644 --- a/src/styles/main.scss +++ b/src/styles/main.scss @@ -5,6 +5,7 @@ :root { + // Light mode colors --primary-color: #1677ff; --primary-gradient: linear-gradient(45deg, #1677ff, #36cff0); --success-color: #52c41a; @@ -12,6 +13,25 @@ --error-color: #ff4d4f; --font-family: 'Poppins', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, 'Noto Sans', sans-serif; + + // Google-style scrollbar colors (Light mode) + --scrollbar-thumb: rgba(0, 0, 0, .2); + --scrollbar-thumb-hover: rgba(0, 0, 0, .4); + --scrollbar-track: transparent; +} + +:root.dark { + // Dark mode colors + --primary-color: #4f9eff; // 更亮的蓝色适配暗色模式 + --primary-gradient: linear-gradient(45deg, #4f9eff, #60deff); + --success-color: #6ede3b; + --warning-color: #ffc53d; + --error-color: #ff7875; + + // Google-style scrollbar colors (Dark mode) + --scrollbar-thumb: rgba(255, 255, 255, .2); + --scrollbar-thumb-hover: rgba(255, 255, 255, .4); + --scrollbar-track: transparent; } body { @@ -152,42 +172,36 @@ body { } } -/* 滚动条基础样式 */ +/* 自定义滚动条样式 */ ::-webkit-scrollbar { width: 8px; - /* 垂直滚动条宽度 */ height: 8px; - /* 水平滚动条高度 */ } -/* 亮色模式滚动条样式 */ ::-webkit-scrollbar-track { - @apply bg-gray-100; - /* 轨道背景色 */ + background: var(--scrollbar-track); } ::-webkit-scrollbar-thumb { - @apply bg-gray-300 rounded-full hover:bg-gray-400 transition-colors; - /* 滑块样式 */ + background-color: var(--scrollbar-thumb); + border-radius: 4px; + transition: background-color 0.2s ease; } -/* 暗色模式滚动条样式 */ -.dark { - ::-webkit-scrollbar-track { - @apply bg-gray-800; - /* 暗色模式轨道背景 */ - } - - ::-webkit-scrollbar-thumb { - @apply bg-gray-600 hover:bg-gray-500; - /* 暗色模式滑块样式 */ - } +::-webkit-scrollbar-thumb:hover { + background-color: var(--scrollbar-thumb-hover); } /* Firefox 滚动条样式 */ * { scrollbar-width: thin; - scrollbar-color: theme('colors.gray.300') theme('colors.gray.100'); + scrollbar-color: var(--scrollbar-thumb) var(--scrollbar-track); +} + +@media (prefers-color-scheme: dark) { + * { + scrollbar-color: rgba(255, 255, 255, 0.2) transparent; + } } .dark * { 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, };