From 2237aecdf292409d1a3621ea0a0986e5d2e415e3 Mon Sep 17 00:00:00 2001 From: qian Date: Fri, 17 Jan 2025 11:17:40 +0800 Subject: [PATCH 1/5] fix --- 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 5f0ec367e02aa1c2a04d75b31d57725ee4d1fbc2 Mon Sep 17 00:00:00 2001 From: liamzi Date: Fri, 17 Jan 2025 16:21:21 +0800 Subject: [PATCH 2/5] =?UTF-8?q?=E6=A8=A1=E5=9D=97=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E5=88=86=E9=A1=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hooks/supabaseService.js | 2 - src/pages/company/service/index.jsx | 45 +++++-- .../service/itemsManange/classify/index.jsx | 42 +++++-- .../service/itemsManange/sections/index.jsx | 4 +- .../service/itemsManange/sections/project.jsx | 50 ++++++-- .../itemsManange/sections/quotation.jsx | 51 +++++--- .../service/itemsManange/sections/task.jsx | 49 ++++++-- .../service/itemsManange/unit/index.jsx | 38 ++++-- src/pages/resource/menu/index.jsx | 115 +++++++++++------- src/pages/resource/role/index.jsx | 12 +- .../resource/team/components/TeamTable.jsx | 13 +- src/pages/resource/team/index.jsx | 1 + 12 files changed, 307 insertions(+), 115 deletions(-) diff --git a/src/hooks/supabaseService.js b/src/hooks/supabaseService.js index 926ca6c..02f49d0 100644 --- a/src/hooks/supabaseService.js +++ b/src/hooks/supabaseService.js @@ -6,8 +6,6 @@ class SupabaseService { let query = supabase .from(table) .select(options.select || "*", { count: "exact" }); - - // 处理精确匹配条件 if (options.match) { query = query.match(options.match); } diff --git a/src/pages/company/service/index.jsx b/src/pages/company/service/index.jsx index 1a19d55..1e243a8 100644 --- a/src/pages/company/service/index.jsx +++ b/src/pages/company/service/index.jsx @@ -68,11 +68,18 @@ const ServicePage = () => { }, }; + // 添加分页相关状态 + const [pagination, setPagination] = useState({ + current: 1, + pageSize: 10, + total: 0, + }); + // 获取服务模板列表 - const fetchServices = async () => { + const fetchServices = async (page = pagination.current, pageSize = pagination.pageSize) => { try { setLoading(true); - const { data: services } = await supabaseService.select("resources", { + const { data: services, total } = await supabaseService.select("resources", { filter: { type: { eq: "serviceTemplate" }, ...(selectedType @@ -83,9 +90,17 @@ const ServicePage = () => { column: "created_at", ascending: false, }, + page, + pageSize, }); setData(services || []); + setPagination((prev) => ({ + ...prev, + current: page, + pageSize, + total, + })); } catch (error) { console.error("获取服务模板失败:", error); message.error("获取服务模板失败"); @@ -93,12 +108,15 @@ const ServicePage = () => { setLoading(false); } }; + + useEffect(() => { + setPagination((prev) => ({ ...prev, current: 1 })); + fetchServices(1, pagination.pageSize); + }, [selectedType]); + useEffect(() => { fetchUnits(); }, []); - useEffect(() => { - fetchServices(); - }, [selectedType]); const fetchUnits = async () => { setloadingUnits(true); @@ -854,7 +872,7 @@ const ServicePage = () => { { rowExpandable: (record) => record.attributes.sections?.length > 0, }} pagination={{ - pageSize: 10, - showTotal: (total) => `共 ${total} 条`, + ...pagination, + showSizeChanger: true, + showQuickJumper: true, + showTotal: (total) => `共 ${total} 条记录`, + onChange: (page, pageSize) => { + // 页码或页大小改变时触发 + if (pageSize !== pagination.pageSize) { + // 如果是页大小改变,重置到第一页 + fetchServices(1, pageSize); + } else { + fetchServices(page, pageSize); + } + }, }} className="rounded-lg" /> diff --git a/src/pages/company/service/itemsManange/classify/index.jsx b/src/pages/company/service/itemsManange/classify/index.jsx index fed3d4b..07d6b56 100644 --- a/src/pages/company/service/itemsManange/classify/index.jsx +++ b/src/pages/company/service/itemsManange/classify/index.jsx @@ -1,6 +1,6 @@ import React, { useState, useEffect } from 'react'; -import { Table, Button, Form, Input, Space, message, Popconfirm, Drawer, Select, Segmented, Badge } from 'antd'; -import { PlusOutlined, FileTextOutlined, ProjectOutlined, CheckSquareOutlined } from '@ant-design/icons'; +import { Table, Button, Form, Input, Space, message, Popconfirm, Select, Segmented } from 'antd'; +import { PlusOutlined } from '@ant-design/icons'; import { supabaseService } from '@/hooks/supabaseService'; const Classify = ({activeType,typeList}) => { const [data, setData] = useState([]); @@ -8,8 +8,13 @@ const Classify = ({activeType,typeList}) => { const [editingKey, setEditingKey] = useState(''); const [form] = Form.useForm(); const [filterType, setFilterType] = useState('all'); // 'all', 'common', 'current' + const [pagination, setPagination] = useState({ + current: 1, + pageSize: 10, + total: 0, + }); - const fetchCategories = async (type = activeType, filterTypeValue = filterType) => { + const fetchCategories = async (type = activeType, filterTypeValue = filterType, page = pagination.current, pageSize = pagination.pageSize) => { setLoading(true); try { let filterCondition; @@ -25,7 +30,7 @@ const Classify = ({activeType,typeList}) => { filterCondition = { in: `(${type},common)` }; } - const { data: categories } = await supabaseService.select('resources', { + const { data: categories, total } = await supabaseService.select('resources', { filter: { 'type': { eq: 'categories' }, 'attributes->>template_type': filterCondition @@ -33,10 +38,18 @@ const Classify = ({activeType,typeList}) => { order: { column: 'created_at', ascending: false - } + }, + page, + pageSize }); setData(categories || []); + setPagination(prev => ({ + ...prev, + current: page, + pageSize, + total + })); } catch (error) { message.error('获取分类数据失败'); console.error(error); @@ -46,8 +59,9 @@ const Classify = ({activeType,typeList}) => { }; useEffect(() => { - fetchCategories(activeType, filterType); - }, [activeType]); + setPagination(prev => ({ ...prev, current: 1 })); + fetchCategories(activeType, filterType, 1, pagination.pageSize); + }, [activeType, filterType]); // 新增分类 @@ -273,9 +287,17 @@ const Classify = ({activeType,typeList}) => { rowKey="id" loading={loading} pagination={{ - pageSize: 10, - showTotal: (total) => `共 ${total} 条`, - className: "px-4" + ...pagination, + showSizeChanger: true, + showQuickJumper: true, + showTotal: (total) => `共 ${total} 条记录`, + onChange: (page, pageSize) => { + if (pageSize !== pagination.pageSize) { + fetchCategories(activeType, filterType, 1, pageSize); + } else { + fetchCategories(activeType, filterType, page, pageSize); + } + } }} className="rounded-lg" /> diff --git a/src/pages/company/service/itemsManange/sections/index.jsx b/src/pages/company/service/itemsManange/sections/index.jsx index 9ba9f5a..f1a3a8b 100644 --- a/src/pages/company/service/itemsManange/sections/index.jsx +++ b/src/pages/company/service/itemsManange/sections/index.jsx @@ -9,8 +9,10 @@ export default function SectionComponent({ activeType }) { return ; case "task": return ; + case "project": + return default: - return ; + return
暂无数据
} }; return <>{renderFn(activeType)}; diff --git a/src/pages/company/service/itemsManange/sections/project.jsx b/src/pages/company/service/itemsManange/sections/project.jsx index 7133884..658f392 100644 --- a/src/pages/company/service/itemsManange/sections/project.jsx +++ b/src/pages/company/service/itemsManange/sections/project.jsx @@ -24,7 +24,6 @@ import { supabaseService } from '@/hooks/supabaseService'; import { v4 as uuidv4 } from 'uuid'; import { supabase } from "@/config/supabase"; -const { Text } = Typography; const TYPE = 'project'; const ProjectSections = () => { @@ -37,11 +36,15 @@ const ProjectSections = () => { const [formValues, setFormValues] = useState({}); const [uploadModalVisible, setUploadModalVisible] = useState(false); const [currentAddItem, setCurrentAddItem] = useState(null); - - const fetchSections = async () => { + const [pagination, setPagination] = useState({ + current: 1, + pageSize: 10, + total: 0, + }); + const fetchSections = async (page = pagination.current, pageSize = pagination.pageSize) => { setLoading(true); try { - const { data: sections } = await supabaseService.select('resources', { + const { data: sections, total } = await supabaseService.select('resources', { filter: { 'type': { eq: 'sections' }, 'attributes->>template_type': { eq: TYPE } @@ -49,9 +52,18 @@ const ProjectSections = () => { order: { column: 'created_at', ascending: false - } + }, + page, + pageSize }); + setData(sections || []); + setPagination(prev => ({ + ...prev, + current: page, + pageSize, + total + })); } catch (error) { message.error('获取模块数据失败'); console.error(error); @@ -83,9 +95,9 @@ const ProjectSections = () => { }; useEffect(() => { - fetchSections(); + fetchSections(1, pagination.pageSize); fetchUnits(); - }, []); + }, [TYPE]); const handleAdd = () => { const newData = { @@ -151,7 +163,7 @@ const ProjectSections = () => { message.success('保存成功'); setEditingKey(''); - fetchSections(); + fetchSections(pagination.current, pagination.pageSize); } catch (error) { message.error('保存失败'); console.error(error); @@ -162,7 +174,11 @@ const ProjectSections = () => { try { await supabaseService.delete('resources', { id: record.id }); message.success('删除成功'); - fetchSections(); + if (data.length === 1 && pagination.current > 1) { + fetchSections(pagination.current - 1, pagination.pageSize); + } else { + fetchSections(pagination.current, pagination.pageSize); + } } catch (error) { message.error('删除失败'); console.error(error); @@ -528,9 +544,19 @@ const ProjectSections = () => { rowKey="id" loading={loading} pagination={{ - pageSize: 10, - showTotal: (total) => `共 ${total} 条`, - className: "px-4" + ...pagination, + showSizeChanger: true, + showQuickJumper: true, + showTotal: (total) => `共 ${total} 条记录`, + pageSizeOptions: ['10', '20', '50', '100'], + onChange: (page, pageSize) => { + if (pageSize !== pagination.pageSize) { + setPagination(prev => ({ ...prev, pageSize })); + fetchSections(1, pageSize); + } else { + fetchSections(page, pageSize); + } + } }} className="rounded-lg" /> diff --git a/src/pages/company/service/itemsManange/sections/quotation.jsx b/src/pages/company/service/itemsManange/sections/quotation.jsx index 19e4ca4..cf89d16 100644 --- a/src/pages/company/service/itemsManange/sections/quotation.jsx +++ b/src/pages/company/service/itemsManange/sections/quotation.jsx @@ -27,22 +27,34 @@ const SectionsManagement = () => { const [loadingUnits,setLoadingUnits]=useState(false) const [units,setUnit]=useState([]) const [formValues, setFormValues] = useState({}); - const fetchSections = async () => { +const [pagination, setPagination] = useState({ + current: 1, + pageSize: 10, + total: 0, +}); + const fetchSections = async (page = pagination.current, pageSize = pagination.pageSize) => { setLoading(true); try { - - const { data: sections } = await supabaseService.select('resources', { + const { data: sections, total } = await supabaseService.select('resources', { filter: { 'type': { eq: 'sections' }, - 'attributes->>template_type': {eq:TYPE} + 'attributes->>template_type': { eq: TYPE } }, order: { column: 'created_at', ascending: false - } + }, + page, + pageSize }); - + setData(sections || []); + setPagination(prev => ({ + ...prev, + current: page, + pageSize, + total + })); } catch (error) { message.error('获取模块数据失败'); console.error(error); @@ -72,8 +84,7 @@ const [formValues, setFormValues] = useState({}); } }; useEffect(() => { - fetchSections(); - + fetchSections(1, pagination.pageSize); }, [TYPE]); const handleAdd = () => { @@ -115,7 +126,7 @@ const [formValues, setFormValues] = useState({}); attributes: { name: values.name, template_type: TYPE, - items: items.filter(item => item.name), // 只保存有名称的项目 + items: items.filter(item => item.name), }, schema_version: 1 }); @@ -135,7 +146,7 @@ const [formValues, setFormValues] = useState({}); message.success('保存成功'); setEditingKey(''); - fetchSections(); + fetchSections(pagination.current, pagination.pageSize); } catch (error) { message.error('保存失败'); console.error(error); @@ -146,7 +157,11 @@ const [formValues, setFormValues] = useState({}); try { await supabaseService.delete('resources', { id: record.id }); message.success('删除成功'); - fetchSections(); + if (data.length === 1 && pagination.current > 1) { + fetchSections(pagination.current - 1, pagination.pageSize); + } else { + fetchSections(pagination.current, pagination.pageSize); + } } catch (error) { message.error('删除失败'); console.error(error); @@ -450,9 +465,17 @@ const [formValues, setFormValues] = useState({}); rowKey="id" loading={loading} pagination={{ - pageSize: 10, - showTotal: (total) => `共 ${total} 条`, - className: "px-4" + ...pagination, + showSizeChanger: true, + showQuickJumper: true, + showTotal: (total) => `共 ${total} 条记录`, + onChange: (page, pageSize) => { + if (pageSize !== pagination.pageSize) { + fetchSections(1, pageSize); + } else { + fetchSections(page, pageSize); + } + } }} className="rounded-lg" /> diff --git a/src/pages/company/service/itemsManange/sections/task.jsx b/src/pages/company/service/itemsManange/sections/task.jsx index 4d2387f..af4565c 100644 --- a/src/pages/company/service/itemsManange/sections/task.jsx +++ b/src/pages/company/service/itemsManange/sections/task.jsx @@ -18,7 +18,6 @@ import { supabaseService } from '@/hooks/supabaseService'; import { v4 as uuidv4 } from 'uuid'; import dayjs from 'dayjs'; -const { Text } = Typography; const TYPE = 'task'; const TaskSections = () => { @@ -29,11 +28,16 @@ const TaskSections = () => { const [loadingUnits, setLoadingUnits] = useState(false); const [units, setUnit] = useState([]); const [formValues, setFormValues] = useState({}); + const [pagination, setPagination] = useState({ + current: 1, + pageSize: 10, + total: 0, + }); - const fetchSections = async () => { + const fetchSections = async (page = pagination.current, pageSize = pagination.pageSize) => { setLoading(true); try { - const { data: sections } = await supabaseService.select('resources', { + const { data: sections, total } = await supabaseService.select('resources', { filter: { 'type': { eq: 'sections' }, 'attributes->>template_type': { eq: TYPE } @@ -41,9 +45,18 @@ const TaskSections = () => { order: { column: 'created_at', ascending: false - } + }, + page, + pageSize }); + setData(sections || []); + setPagination(prev => ({ + ...prev, + current: page, + pageSize, + total + })); } catch (error) { message.error('获取模块数据失败'); console.error(error); @@ -75,9 +88,9 @@ const TaskSections = () => { }; useEffect(() => { - fetchSections(); + fetchSections(1, pagination.pageSize); fetchUnits(); - }, []); + }, [TYPE]); const handleAdd = () => { const newData = { @@ -144,7 +157,7 @@ const TaskSections = () => { message.success('保存成功'); setEditingKey(''); - fetchSections(); + fetchSections(pagination.current, pagination.pageSize); } catch (error) { message.error('保存失败'); console.error(error); @@ -155,7 +168,11 @@ const TaskSections = () => { try { await supabaseService.delete('resources', { id: record.id }); message.success('删除成功'); - fetchSections(); + if (data.length === 1 && pagination.current > 1) { + fetchSections(pagination.current - 1, pagination.pageSize); + } else { + fetchSections(pagination.current, pagination.pageSize); + } } catch (error) { message.error('删除失败'); console.error(error); @@ -440,9 +457,19 @@ const TaskSections = () => { rowKey="id" loading={loading} pagination={{ - pageSize: 10, - showTotal: (total) => `共 ${total} 条`, - className: "px-4" + ...pagination, + showSizeChanger: true, + showQuickJumper: true, + showTotal: (total) => `共 ${total} 条记录`, + pageSizeOptions: ['10', '20', '50', '100'], + onChange: (page, pageSize) => { + if (pageSize !== pagination.pageSize) { + setPagination(prev => ({ ...prev, pageSize })); + fetchSections(1, pageSize); + } else { + fetchSections(page, pageSize); + } + } }} className="rounded-lg" /> diff --git a/src/pages/company/service/itemsManange/unit/index.jsx b/src/pages/company/service/itemsManange/unit/index.jsx index fd3e3fc..d6d6bf3 100644 --- a/src/pages/company/service/itemsManange/unit/index.jsx +++ b/src/pages/company/service/itemsManange/unit/index.jsx @@ -9,8 +9,13 @@ const UnitManagement = ({ activeType, typeList }) => { const [editingKey, setEditingKey] = useState(''); const [form] = Form.useForm(); const [filterType, setFilterType] = useState('all'); + const [pagination, setPagination] = useState({ + current: 1, + pageSize: 10, + total: 0, + }); - const fetchUnits = async (type = activeType, filterTypeValue = filterType) => { + const fetchUnits = async (type = activeType, filterTypeValue = filterType, page = pagination.current, pageSize = pagination.pageSize) => { setLoading(true); try { let filterCondition; @@ -26,7 +31,7 @@ const UnitManagement = ({ activeType, typeList }) => { filterCondition = { in: `(${type},common)` }; } - const { data: units } = await supabaseService.select('resources', { + const { data: units, total } = await supabaseService.select('resources', { filter: { 'type': { eq: 'units' }, 'attributes->>template_type': filterCondition @@ -34,10 +39,18 @@ const UnitManagement = ({ activeType, typeList }) => { order: { column: 'created_at', ascending: false - } + }, + page, + pageSize }); setData(units || []); + setPagination(prev => ({ + ...prev, + current: page, + pageSize, + total + })); } catch (error) { message.error('获取单位数据失败'); console.error(error); @@ -47,8 +60,9 @@ const UnitManagement = ({ activeType, typeList }) => { }; useEffect(() => { - fetchUnits(activeType, filterType); - }, [activeType]); + setPagination(prev => ({ ...prev, current: 1 })); + fetchUnits(activeType, filterType, 1, pagination.pageSize); + }, [activeType, filterType]); const handleAdd = () => { const newData = { @@ -269,9 +283,17 @@ const UnitManagement = ({ activeType, typeList }) => { rowKey="id" loading={loading} pagination={{ - pageSize: 10, - showTotal: (total) => `共 ${total} 条`, - className: "px-4" + ...pagination, + showSizeChanger: true, + showQuickJumper: true, + showTotal: (total) => `共 ${total} 条记录`, + onChange: (page, pageSize) => { + if (pageSize !== pagination.pageSize) { + fetchUnits(activeType, filterType, 1, pageSize); + } else { + fetchUnits(activeType, filterType, page, pageSize); + } + } }} className="rounded-lg" /> diff --git a/src/pages/resource/menu/index.jsx b/src/pages/resource/menu/index.jsx index ff8dd60..2441769 100644 --- a/src/pages/resource/menu/index.jsx +++ b/src/pages/resource/menu/index.jsx @@ -13,7 +13,7 @@ import { TreeSelect } from 'antd'; import { getAllRouteOptions, allRoutes } from '@/routes/routes'; -import { supabase } from '@/config/supabase'; +import { supabaseService } from '@/hooks/supabaseService'; import { PlusOutlined, EditOutlined, DeleteOutlined } from '@ant-design/icons'; const { Title } = Typography; @@ -25,7 +25,12 @@ export default function MenuManagement() { const [menuList, setMenuList] = useState([]); const [form] = Form.useForm(); const [roles, setRoles] = useState([]); - + const [pagination, setPagination] = useState({ + current: 1, + pageSize: 10, + total: 0, + }); + // 获取所有路由选项 const routeOptions = getAllRouteOptions(); @@ -80,19 +85,31 @@ export default function MenuManagement() { ]; // 获取菜单数据 - const fetchMenuList = async () => { + const fetchMenuList = async (page = pagination.current, pageSize = pagination.pageSize) => { + setLoading(true); try { - setLoading(true); - const { data, error } = await supabase - .from('resources') - .select('*') - .eq('type', TYPE) - .order('created_at', { ascending: false }); - - if (error) throw error; - setMenuList(data); + const { data: menus, total } = await supabaseService.select('resources', { + filter: { + 'type': { eq: TYPE } + }, + order: { + column: 'created_at', + ascending: false + }, + page, + pageSize + }); + + setMenuList(menus || []); + setPagination(prev => ({ + ...prev, + current: page, + pageSize, + total + })); } catch (error) { - message.error('获取数据失败:' + error.message); + message.error('获取菜单数据失败'); + console.error(error); } finally { setLoading(false); } @@ -101,12 +118,12 @@ export default function MenuManagement() { // 获取角色列表 const fetchRoles = async () => { try { - const { data, error } = await supabase - .from('roles') - .select('*') - .order('name'); - - if (error) throw error; + const { data } = await supabaseService.select('roles', { + order: { + column: 'name', + ascending: true + } + }); setRoles(data || []); } catch (error) { message.error('获取角色数据失败'); @@ -127,27 +144,20 @@ export default function MenuManagement() { } }; - let result; if (form.getFieldValue('id')) { - result = await supabase - .from('resources') - .update(menuData) - .eq('id', form.getFieldValue('id')) - .select(); + await supabaseService.update('resources', + { id: form.getFieldValue('id') }, + menuData + ); } else { - result = await supabase - .from('resources') - .insert([menuData]) - .select(); + await supabaseService.insert('resources', menuData); } - if (result.error) throw result.error; - message.success('保存成功'); setIsModalVisible(false); - fetchMenuList(); + fetchMenuList(pagination.current, pagination.pageSize); } catch (error) { - message.error('保存失败:' + error.message); + message.error('保存失败:' + (error.message || '未知错误')); } finally { setLoading(false); } @@ -168,19 +178,17 @@ export default function MenuManagement() { const handleDelete = async (id) => { try { setLoading(true); - const {data, error } = await supabase - .from('resources') - .delete() - .eq('id', id); - if (error) throw error; - if(data.length>0){ - message.success('删除成功'); - fetchMenuList(); - }else{ - message.error('删除失败'); + await supabaseService.delete('resources', { id }); + message.success('删除成功'); + + // 如果当前页只有一条数据且不是第一页,删除后自动跳转到上一页 + if (menuList.length === 1 && pagination.current > 1) { + fetchMenuList(pagination.current - 1, pagination.pageSize); + } else { + fetchMenuList(pagination.current, pagination.pageSize); } } catch (error) { - message.error('删除失败:' + error.message); + message.error('删除失败:' + (error.message || '未知错误')); } finally { setLoading(false); } @@ -196,7 +204,7 @@ export default function MenuManagement() { }; useEffect(() => { - fetchMenuList(); + fetchMenuList(1, pagination.pageSize); fetchRoles(); }, []); @@ -221,6 +229,23 @@ export default function MenuManagement() { columns={columns} dataSource={menuList} loading={loading} + pagination={{ + ...pagination, + showSizeChanger: true, + showQuickJumper: true, + showTotal: (total) => `共 ${total} 条记录`, + pageSizeOptions: ['10', '20', '50', '100'], + onChange: (page, pageSize) => { + if (pageSize !== pagination.pageSize) { + // 如果是改变每页条数,重置到第一页 + setPagination(prev => ({ ...prev, pageSize })); + fetchMenuList(1, pageSize); + } else { + // 如果是改变页码,获取对应页数据 + fetchMenuList(page, pageSize); + } + } + }} rowKey="id" /> diff --git a/src/pages/resource/role/index.jsx b/src/pages/resource/role/index.jsx index e3342f2..1a4870f 100644 --- a/src/pages/resource/role/index.jsx +++ b/src/pages/resource/role/index.jsx @@ -52,7 +52,6 @@ export default function PermissionManagement() { resources:resource_id(*) `, { count: 'exact' }); - // 添加排序 if (params.field && params.order) { const ascending = params.order === 'ascend'; query = query.order(params.field, { ascending }); @@ -544,7 +543,16 @@ export default function PermissionManagement() { dataSource={permissions} rowKey="id" loading={loading} - pagination={pagination} + pagination={{ + ...pagination, + showSizeChanger: true, + showQuickJumper: true, + showTotal: (total) => `共 ${total} 条记录`, + pageSizeOptions: ['10', '20', '50', '100'], + onChange: (page, pageSize) => { + setPagination(prev => ({ ...prev,page, pageSize })); + } + }} onChange={handleTableChange} className='w-full' /> diff --git a/src/pages/resource/team/components/TeamTable.jsx b/src/pages/resource/team/components/TeamTable.jsx index 8718b85..bc9f3cf 100644 --- a/src/pages/resource/team/components/TeamTable.jsx +++ b/src/pages/resource/team/components/TeamTable.jsx @@ -3,7 +3,7 @@ import { Table, Form, Button, Space, Popconfirm, Tag, message } from 'antd'; import { EditOutlined, DeleteOutlined, SaveOutlined, CloseOutlined } from '@ant-design/icons'; import { EditableCell } from './EditableCell'; import { ExpandedMemberships } from './ExpandedMemberships'; -export const TeamTable = ({ tableLoading,pagination,dataSource, onTableChange,onDelete ,onUpdate}) => { +export const TeamTable = ({ tableLoading,pagination,dataSource,setPagination, onTableChange,onDelete ,onUpdate}) => { const [form] = Form.useForm(); const [editingKey, setEditingKey] = useState(''); const [loading, setLoading] = useState(false); @@ -182,7 +182,6 @@ export const TeamTable = ({ tableLoading,pagination,dataSource, onTableChange,on
`共 ${total} 条记录`, + pageSizeOptions: ['10', '20', '50', '100'], + onChange: (page, pageSize) => { + setPagination(prev => ({ ...prev,page, pageSize })); + } + }} expandable={{ expandedRowRender: (record) => ( { Date: Fri, 17 Jan 2025 17:18:53 +0800 Subject: [PATCH 3/5] fix --- src/contexts/AuthContext.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/contexts/AuthContext.jsx b/src/contexts/AuthContext.jsx index 3589d9c..2160134 100644 --- a/src/contexts/AuthContext.jsx +++ b/src/contexts/AuthContext.jsx @@ -182,7 +182,7 @@ export const AuthProvider = ({ children }) => { } }; const fetchMenuList = async (role) => { - console.log(role,'role'); + if(!role||!user?.id) return; try { const { data, error } = await supabase .from('resources') From c229f2dbc458f7543a0d3df4e0f316d76d0837cb Mon Sep 17 00:00:00 2001 From: liamzi Date: Fri, 17 Jan 2025 17:39:14 +0800 Subject: [PATCH 4/5] fix --- src/components/auth/ProtectedRoute.jsx | 13 +++++++++ src/contexts/AuthContext.jsx | 40 +++++++++++++++----------- 2 files changed, 37 insertions(+), 16 deletions(-) diff --git a/src/components/auth/ProtectedRoute.jsx b/src/components/auth/ProtectedRoute.jsx index 41ab006..9a96c28 100644 --- a/src/components/auth/ProtectedRoute.jsx +++ b/src/components/auth/ProtectedRoute.jsx @@ -3,13 +3,26 @@ import { Navigate, useLocation } from "react-router-dom"; import { useAuth } from "@/contexts/AuthContext"; const PUBLIC_PATHS = ['login', '404','home']; + export const ProtectedRoute = ({ children }) => { const { user } = useAuth(); const location = useLocation(); const currentPath = location.pathname.replace(/^\//, ''); + + // 如果是公共路径,直接显示 if (PUBLIC_PATHS.includes(currentPath) || currentPath === '*') { return children; } + + // 如果用户未登录,重定向到登录页面,并携带当前路径 + if (!user?.id) { + return ; + } + + // 如果用户已登录,检查权限 if (user?.id) { const hasPermission = user.menukeys?.some(key => { return currentPath === key || currentPath.startsWith(`${key}/`); diff --git a/src/contexts/AuthContext.jsx b/src/contexts/AuthContext.jsx index 2160134..9924aa0 100644 --- a/src/contexts/AuthContext.jsx +++ b/src/contexts/AuthContext.jsx @@ -8,14 +8,13 @@ import { v4 as uuidv4 } from "uuid"; const AuthContext = createContext({}); export const AuthProvider = ({ children }) => { - const [searchParams, setSearchParams] = useSearchParams(); + const [searchParams] = useSearchParams(); const navigate = useNavigate(); const location = useLocation(); const [user, setUser] = useState({}); const [loading, setLoading] = useState(true); useEffect(() => { - //处理google登录 const hash = window.location.hash.substring(1); const hashParams = new URLSearchParams(hash); const accessToken = hashParams.get("access_token"); @@ -62,12 +61,7 @@ export const AuthProvider = ({ children }) => { } }, [user]); - // useEffect(() => { - // const redirectTo = searchParams.get("redirectTo"); - // if (redirectTo) { - // navigate(redirectTo); - // } - // }, [location.pathname]); + //检查时候在管理模块团队中,没有就自动加入 const checkInTeam = async (user) => { @@ -121,7 +115,21 @@ export const AuthProvider = ({ children }) => { message.error(error.message || "登录失败,请稍后重试"); return; } - setUser(data.user); + + const role = await checkInTeam(data.user); + const menukey = await fetchMenuList(role); + setUser({ ...data.user, adminRole: role, menukeys: menukey }); + + // 获取重定向路径 + const redirectTo = searchParams.get("redirectTo"); + if (redirectTo) { + // 如果有重定向路径,则导航到该路径 + navigate(decodeURIComponent(redirectTo), { replace: true }); + } else { + // 如果没有重定向路径,则导航到首页 + navigate("/home", { replace: true }); + } + return data; } catch (error) { message.error(error.message || "登录失败,请稍后重试"); @@ -134,13 +142,12 @@ export const AuthProvider = ({ children }) => { const signInWithGoogle = async () => { try { setLoading(true); - const redirectTo = searchParams.get("redirectTo"); + const redirectTo = searchParams.get("redirectTo") || "/home"; + const { data, error } = await supabase.auth.signInWithOAuth({ provider: "google", options: { - redirectTo: `${window.location.origin}/login?redirectTo=${ - redirectTo ?? "" - }`, + redirectTo: `${window.location.origin}/login?redirectTo=${encodeURIComponent(redirectTo)}`, }, }); @@ -182,13 +189,13 @@ export const AuthProvider = ({ children }) => { } }; const fetchMenuList = async (role) => { - if(!role||!user?.id) return; + if(!role) return; try { const { data, error } = await supabase .from('resources') .select('*') .eq('type', 'menuKey') - .eq('attributes->>roleName', role) // 添加这行来筛选 OWNER 角色 + .eq('attributes->>roleName', role) .single(); if (error) throw error; if(data?.attributes?.menuKeys){ @@ -214,7 +221,8 @@ export const AuthProvider = ({ children }) => { } setUser({}); message.success("已成功登出"); - navigate(`/login?redirectTo=${location.pathname}`, { replace: true }); + // 保存当前完整路径作为重定向 URL + navigate(`/login?redirectTo=${encodeURIComponent(location.pathname + location.search)}`, { replace: true }); } catch (error) { message.error(error.message || "登出失败,请稍后重试"); } finally { From 0e71c0e8b2e97073baf6fa4b8b535df3dca75960 Mon Sep 17 00:00:00 2001 From: liamzi Date: Fri, 17 Jan 2025 17:47:21 +0800 Subject: [PATCH 5/5] pdf --- src/contexts/AuthContext.jsx | 2 +- src/pages/company/quotation/view/index.jsx | 100 +++++++++++---------- 2 files changed, 54 insertions(+), 48 deletions(-) diff --git a/src/contexts/AuthContext.jsx b/src/contexts/AuthContext.jsx index 9924aa0..07073f0 100644 --- a/src/contexts/AuthContext.jsx +++ b/src/contexts/AuthContext.jsx @@ -199,7 +199,7 @@ export const AuthProvider = ({ children }) => { .single(); if (error) throw error; if(data?.attributes?.menuKeys){ - return data.attributes.menuKeys; + return data.attributes.menuKeys; }else{ return []; } diff --git a/src/pages/company/quotation/view/index.jsx b/src/pages/company/quotation/view/index.jsx index 4adfeda..f04d0bb 100644 --- a/src/pages/company/quotation/view/index.jsx +++ b/src/pages/company/quotation/view/index.jsx @@ -7,7 +7,7 @@ import html2canvas from 'html2canvas'; import jsPDF from 'jspdf'; const { Title, Text } = Typography; -import { EXCHANGE_RATE,defaultSymbol } from '@/utils/exchange_rate'; +import { EXCHANGE_RATE, defaultSymbol } from '@/utils/exchange_rate'; const QuotationPreview = () => { const { id } = useParams(); @@ -114,17 +114,6 @@ const QuotationPreview = () => { } }; - // 导出按钮组件 - const ExportPDFButton = () => ( - - ); - if (loading) { return (
@@ -139,52 +128,69 @@ const QuotationPreview = () => { const currencySymbol = EXCHANGE_RATE[attributes.currency]?.symbol || defaultSymbol; return ( -
+
+
- - 报价单预览 + + 报价单预览 - +
- } - > -
+
+ +
- {attributes.quataName} - 创建日期:{new Date(quotation.created_at).toLocaleDateString()} + {attributes.quataName} + + 创建日期:{new Date(quotation.created_at).toLocaleDateString()} +
-
- 基本信息 -
+
+ 基本信息 +
- 客户: - + 客户: + {attributes.customers?.map(customer => ( - {customer.name} + + {customer.name} + ))}
- 货币类型: - {attributes.currency} + 货币类型: + {attributes.currency}
{attributes.sections?.map((section, sIndex) => ( -
-
+
+
-

{section.sectionName}

+

{section.sectionName}

-
-
- +
+
+ @@ -194,9 +200,9 @@ const QuotationPreview = () => { - + {section.items.map((item, iIndex) => ( - + @@ -216,9 +222,9 @@ const QuotationPreview = () => { ))} {/* 金额汇总 */} -
-
-
+
+
+
税前总计: {currencySymbol}{attributes.beforeTaxAmount?.toLocaleString()} @@ -238,9 +244,9 @@ const QuotationPreview = () => {
)} -
- 最终金额: - +
+ 最终金额: + {currencySymbol}{(attributes.discount || attributes.afterTaxAmount)?.toLocaleString()}
@@ -251,9 +257,9 @@ const QuotationPreview = () => { {/* 补充说明 */} {attributes.description && (
- 补充说明 -
- {attributes.description} + 补充说明 +
+ {attributes.description}
)}
项目明细 描述/备注小计
{item.name} {item.description} {item.unit}