From 26722d643d0b4bcee91ba65970cb74189bfd579b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AD=99=E6=99=AF=E5=AD=A6?= <5412262+sun_jing_xue@user.noreply.gitee.com> Date: Tue, 5 Aug 2025 11:24:32 +0800 Subject: [PATCH] =?UTF-8?q?=E8=8F=9C=E5=8D=95=E4=B8=8E=20=E5=AE=A1?= =?UTF-8?q?=E6=A0=B8=E6=8C=89=E9=92=AE=EF=BC=8C=E7=99=BB=E5=BD=95=E6=96=B0?= =?UTF-8?q?=E7=94=A8=E6=88=B7=E4=BF=AE=E6=94=B9=E5=AF=86=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../component/BaseInfoFormModal.tsx | 12 +++- .../CompanyInfo/component/BaseInfoTab.tsx | 15 +++- src/components/CompanyInfo/services.ts | 5 +- src/layouts/BasicLayout.tsx | 50 +++++++++++-- src/pages/index/index.tsx | 47 ------------ src/pages/index/servers.ts | 13 ---- .../login/components/ChangePasswordModal.tsx | 72 +++++++++++++++++++ src/pages/login/login.tsx | 46 +++++++++++- .../admission/SupplierCategoryEntry/index.tsx | 13 +++- .../SupplierCategoryEntry/services.ts | 3 + .../admission/admissionManagement/index.tsx | 15 +++- .../admission/admissionManagement/services.ts | 2 +- .../SupplierChangeReviewManage/index.tsx | 21 ++++-- .../SupplierChangeReviewManage/services.ts | 2 +- .../supplierExit/supplierExitAudit/index.tsx | 18 ++++- .../supplierExitAudit/services.ts | 2 +- src/servers/api/login.ts | 15 +++- 17 files changed, 260 insertions(+), 91 deletions(-) create mode 100644 src/pages/login/components/ChangePasswordModal.tsx diff --git a/src/components/CompanyInfo/component/BaseInfoFormModal.tsx b/src/components/CompanyInfo/component/BaseInfoFormModal.tsx index 6d34045..b6b456e 100644 --- a/src/components/CompanyInfo/component/BaseInfoFormModal.tsx +++ b/src/components/CompanyInfo/component/BaseInfoFormModal.tsx @@ -74,7 +74,9 @@ interface coscoSupplierSurveyAttachments { //变更要求 interface changeComparisonDataProps { name?: string; + nameEn?: string; range?: string; + supplierType?: string; } const BaseInfoFormModal: React.FC = ({ visible, @@ -114,7 +116,9 @@ const BaseInfoFormModal: React.FC = ({ }); setChangeComparisonData({ name: initialValues.name, - range: initialValues.range + range: initialValues.range, + supplierType: initialValues.supplierType, + nameEn: initialValues.nameEn, }) setViewData({ ...changeData, @@ -261,11 +265,15 @@ const BaseInfoFormModal: React.FC = ({ )} {() => { + console.log(changeComparisonData,';changeComparisonData'); + // 每次Form数据变化都会重新render const currentName = form.getFieldValue(['coscoSupplierBase', 'name']); + const currentNameEn = form.getFieldValue(['coscoSupplierBase', 'nameEn']); const currentRange = form.getFieldValue(['coscoSupplierBase', 'range']); const shouldShowPanel = - (changeComparisonData?.name !== undefined && currentName !== changeComparisonData.name) || + (changeComparisonData?.name !== undefined && (currentName !== changeComparisonData.name && changeComparisonData.supplierType === 'dvs' )) || + (changeComparisonData?.name !== undefined && (currentNameEn !== changeComparisonData.nameEn && changeComparisonData.supplierType === 'ovs' )) || (changeComparisonData?.range !== undefined && currentRange !== changeComparisonData.range); if (!shouldShowPanel) return null; diff --git a/src/components/CompanyInfo/component/BaseInfoTab.tsx b/src/components/CompanyInfo/component/BaseInfoTab.tsx index a2e1248..7f0b5b9 100644 --- a/src/components/CompanyInfo/component/BaseInfoTab.tsx +++ b/src/components/CompanyInfo/component/BaseInfoTab.tsx @@ -1,6 +1,6 @@ import React, { useEffect, useState } from 'react'; -import { Descriptions, Button } from 'antd'; -import { coscoSupplierBase } from '../services'; +import { Descriptions, Button, message } from 'antd'; +import { coscoSupplierBase, getSupplierIdCount } from '../services'; import { useIntl } from 'umi'; import BaseInfoFormModal from './BaseInfoFormModal' @@ -68,7 +68,16 @@ const BaseInfoTab: React.FC = (props) => { //增改查 const [formVisible, setFormVisible] = useState(false); const handleAdd = () => { - setFormVisible(true); + + getSupplierIdCount(record).then((res) => { + if(res === 0) { + setFormVisible(true); + } else { + message.warning('已存在变更信息审核') + } + + }) + }; const handleFormSubmit = () => { setFormVisible(false); diff --git a/src/components/CompanyInfo/services.ts b/src/components/CompanyInfo/services.ts index 5c67a03..c116b0f 100644 --- a/src/components/CompanyInfo/services.ts +++ b/src/components/CompanyInfo/services.ts @@ -283,6 +283,9 @@ export const categoryTree = () => request.get('/cosco/category/categoryTree'); - +/** + * 验证是否有变更 + */ +export const getSupplierIdCount = (id: string) => request.get(`/coscoSupplierChangeApply/getSupplierIdCount/${id}`); diff --git a/src/layouts/BasicLayout.tsx b/src/layouts/BasicLayout.tsx index 33862cc..364c104 100644 --- a/src/layouts/BasicLayout.tsx +++ b/src/layouts/BasicLayout.tsx @@ -4,7 +4,7 @@ import ProLayout, { PageContainer } from '@ant-design/pro-layout'; import { Link, useLocation, useIntl } from 'umi'; import { connect } from 'dva'; import defaultSettings from '../../config/defaultSettings'; -import routes from '../../config/router.config'; +import routes from '../../config/router.config'; import { ConfigProvider, Breadcrumb } from 'antd'; import HeaderComponent from './Header'; import IconFont from '@/components/IconFont/IconFont'; @@ -19,14 +19,14 @@ const MenuRender = (item: any, isSubMenu: boolean) => { - {intl.formatMessage({ id: `${item.name}` || '' })} + {intl.formatMessage({ id: `menu.${item.name}` || '' })} ) : ( - {intl.formatMessage({ id: `${item.name}` || '' })} + {intl.formatMessage({ id: `menu.${item.name}` || '' })} )} @@ -77,8 +77,8 @@ function convertMenuData(menus: any[]): any[] { const icon = item.icon || undefined; // 递归 children->routes let routes; - if (item.children && item.children.length > 0) { - routes = convertMenuData(item.children); + if (item.routes && item.routes.length > 0) { + routes = convertMenuData(item.routes); } // 国际化优先找 menu.name,否则直接显示 name return { @@ -90,6 +90,43 @@ function convertMenuData(menus: any[]): any[] { }); } +// 新增递归过滤函数 +function filterMenusByLocalConfig(localMenus: any[], remoteMenus: any[]): any[] { + if (!Array.isArray(localMenus) || !Array.isArray(remoteMenus)) return []; + // remoteMenus 可能有 children 字段,也可能有 routes 字段 + const remoteMap = new Map(); + remoteMenus.forEach(r => { + if (r.path) remoteMap.set(r.path, r); + }); + + // filter 和 map 后的结果直接 return + localMenus + .filter(local => local.path && remoteMap.has(local.path)) + .map(local => { + const remote = remoteMap.get(local.path); + // 兼容 children 或 routes 字段 + const localChildren = local.children || local.routes; + const remoteChildren = remote.children || remote.routes; + let newChildren: any[] = []; + if ( + localChildren && localChildren.length > 0 && + remoteChildren && remoteChildren.length > 0 + ) { + newChildren = filterMenusByLocalConfig(localChildren, remoteChildren); + } + // 保留原有结构,只替换 children 或 routes + let node = { ...local }; + if (local.children) { + node.children = newChildren; + } else if (local.routes) { + node.routes = newChildren; + } + return node; + }); + + return localMenus +} + const BasicLayout: React.FC = (props) => { const { children, tab, dispatch } = props; @@ -118,7 +155,8 @@ const BasicLayout: React.FC = (props) => { const menuStr = sessionStorage.getItem('menuList'); if (menuStr) { const menus = JSON.parse(menuStr); - setMenuRoutes(convertMenuData(menus)); + const filteredMenus = filterMenusByLocalConfig(routes, menus); + setMenuRoutes(convertMenuData(filteredMenus)); } }, []); diff --git a/src/pages/index/index.tsx b/src/pages/index/index.tsx index d8abae8..05c5821 100644 --- a/src/pages/index/index.tsx +++ b/src/pages/index/index.tsx @@ -1,10 +1,8 @@ import React, { useEffect, useState } from 'react'; import { Card, Row, Col, Spin, message } from 'antd'; import { Column, Pie, Bar } from '@ant-design/charts'; -import ChangePasswordModal from './components/ChangePasswordModal'; import { - changePasswordOnFirstLogin, getYearcountNum, getAccessTypeCountNum, getSupplierTypeCountNum, @@ -22,38 +20,6 @@ const HomeDashboard: React.FC = () => { const [supplierAuditData, setSupplierAuditData] = useState([]); const [loading, setLoading] = useState(false); - // ======= 新增部分:弹窗控制 ======= - const [showChangePwd, setShowChangePwd] = useState(false); - useEffect(() => { - // 检查 firstLogin - const userStr = sessionStorage.getItem('currentUser'); - if (userStr) { - try { - const userObj = JSON.parse(userStr); - if (userObj?.supplierUser?.firstLogin === 0) { - setShowChangePwd(true); - } - } catch (e) { } - } - }, []); - // 修改密码确认回调 - const handleChangePwd = async (values: { userId: string; newPassword: string; confirmPassword: string; }) => { - try { - await changePasswordOnFirstLogin({ ...values }); - message.success('密码修改成功,请重新登录'); - // 更新缓存 firstLogin=1 - const userStr = sessionStorage.getItem('currentUser'); - if (userStr) { - const userObj = JSON.parse(userStr); - if (userObj?.supplierUser) userObj.supplierUser.firstLogin = 1; - sessionStorage.setItem('currentUser', JSON.stringify(userObj)); - } - setShowChangePwd(false); - - } catch (e: any) { - message.error(e?.message || '修改密码失败'); - } - }; useEffect(() => { setLoading(true); @@ -193,19 +159,6 @@ const HomeDashboard: React.FC = () => { return ( <> - { - setShowChangePwd(false) - const userStr = sessionStorage.getItem('currentUser'); - if (userStr) { - const userObj = JSON.parse(userStr); - if (userObj?.supplierUser) userObj.supplierUser.firstLogin = 1; - sessionStorage.setItem('currentUser', JSON.stringify(userObj)); - } - }} - /> {/* 第一行:3图 */} diff --git a/src/pages/index/servers.ts b/src/pages/index/servers.ts index f85a889..eefdd11 100644 --- a/src/pages/index/servers.ts +++ b/src/pages/index/servers.ts @@ -1,18 +1,5 @@ import request from '@/utils/request'; -/** - * - * @param params - * @returns - * - */ -interface PasswordOnFirstLogin { - userId:string; - newPassword:string; - confirmPassword:string; -} -export const changePasswordOnFirstLogin = (data:PasswordOnFirstLogin) => request.post(`/v1/login/supplier/changePasswordOnFirstLogin`, { data}); - /** * * @param params diff --git a/src/pages/login/components/ChangePasswordModal.tsx b/src/pages/login/components/ChangePasswordModal.tsx new file mode 100644 index 0000000..8e3550f --- /dev/null +++ b/src/pages/login/components/ChangePasswordModal.tsx @@ -0,0 +1,72 @@ +import React, { useEffect } from 'react'; +import { Modal, Form, Input, Button } from 'antd'; +// props: visible, onOk, onCancel +const ChangePasswordModal: React.FC<{ + visible: boolean; + onOk: (values: { userId: string; newPassword: string; confirmPassword: string }) => Promise; +}> = ({ visible, onOk }) => { + const [form] = Form.useForm(); + + const handleOk = async () => { + try { + const values = await form.validateFields(); + await onOk({ ...values }); + form.resetFields(); + } catch (err) {} + }; + + return ( + +
+ + + + + + + ({ + validator(_, value) { + if (!value || getFieldValue('newPassword') === value) return Promise.resolve(); + return Promise.reject('两次输入密码不一致'); + }, + }), + ]} + > + + +
+
+ +
+
+ ); +}; + +export default ChangePasswordModal; diff --git a/src/pages/login/login.tsx b/src/pages/login/login.tsx index 59f36ff..ef08489 100644 --- a/src/pages/login/login.tsx +++ b/src/pages/login/login.tsx @@ -3,7 +3,8 @@ import { Form, Input, Button, Checkbox, Tabs, message } from 'antd'; import { UserOutlined, LockOutlined, EyeInvisibleOutlined, EyeTwoTone } from '@ant-design/icons'; import { history, useIntl } from 'umi'; import './login.less'; -import { getCaptcha, supplierLogin, expertLogin, accountLogin, getUserinfo, refreshDictCache, findMenuList } from '@/servers/api/login'; +import { getCaptcha, supplierLogin, expertLogin, accountLogin, getUserinfo, refreshDictCache, findMenuList, changePasswordOnFirstLogin } from '@/servers/api/login'; +import ChangePasswordModal from './components/ChangePasswordModal'; import { encryptWithRsa } from '@/utils/encryptWithRsa' @@ -14,6 +15,10 @@ const LoginPage: React.FC = () => { const [form] = Form.useForm(); const [loading, setLoading] = useState(false); const [captchaImg, setCaptchaImg] = useState(''); + const [userId, setUserId] = useState(''); + // ======= 修改密码弹窗控制 ======= + const [showChangePwd, setShowChangePwd] = useState(false); + // const [captchaKey, setCaptchaKey] = useState(''); //切换后 走不同接口 const loginApiMap: { [key: string]: (params: any) => Promise } = { @@ -51,6 +56,26 @@ const LoginPage: React.FC = () => { // }); // } }, [form]); + + // 修改密码确认回调 + const handleChangePwd = async (values: { userId: string; newPassword: string; confirmPassword: string; }) => { + try { + await changePasswordOnFirstLogin({ + userId: userId, + newPassword: encryptWithRsa(values.newPassword, false), + confirmPassword: encryptWithRsa(values.confirmPassword, false) + }).then((res) => { + if(res.data) { + setShowChangePwd(false); + message.success('修改成功,请重新登录'); + } else { + message.success('修改密码失败'); + } + }) + } catch (e: any) { + message.error(e?.message || '修改密码失败'); + } + }; const onFinish = async (values: any) => { setLoading(true); try { @@ -92,11 +117,19 @@ const LoginPage: React.FC = () => { sessionStorage.setItem('currentUser', JSON.stringify(loginRes.data)); await getUserinfo().then(async (res) => { const roleIdList = res.authorityList.map((item: any) => item.roleId); + console.log(res); + + setUserId(res.userId) sessionStorage.setItem('Userinfo', JSON.stringify(res)); const menuList: any = await findMenuList({ roleIdList }); sessionStorage.setItem('menuList', JSON.stringify(menuList.data)); - message.success('登录成功'); - history.push('/index'); + //新用户需要修改一次密码 + if (loginRes.data?.supplierUser?.firstLogin === 1) { + setShowChangePwd(true); + } else { + message.success('登录成功'); + history.push('/index'); + } }); } else { message.error(loginRes.message || '登录失败'); @@ -157,6 +190,12 @@ const LoginPage: React.FC = () => { } return ( + <> + +
{/*
@@ -245,6 +284,7 @@ const LoginPage: React.FC = () => {
+ ); }; diff --git a/src/pages/supplier/admission/SupplierCategoryEntry/index.tsx b/src/pages/supplier/admission/SupplierCategoryEntry/index.tsx index 5a06481..2067d12 100644 --- a/src/pages/supplier/admission/SupplierCategoryEntry/index.tsx +++ b/src/pages/supplier/admission/SupplierCategoryEntry/index.tsx @@ -10,7 +10,7 @@ import CategorySelector from '@/components/CategorySelector'; import AdmissionTypeSelect from '@/components/CommonSelect/AdmissionTypeSelect'; import AccessDepartmentSelect from "@/components/AccessDepartmentSelect" //接口 -import { getPage, startApprove } from './services' +import { getPage, startApprove, supplierChangeApprove } from './services' import { getDictList } from '@/servers/api/dicts' //统一列表分页 import tableProps from '@/utils/tableProps' @@ -120,6 +120,15 @@ const SupplierCategoryEntry: React.FC = () => { 发起审批 )} + {record.approveStatus === '0' && ( + + )} ), }, @@ -131,7 +140,7 @@ const SupplierCategoryEntry: React.FC = () => {
- + diff --git a/src/pages/supplier/admission/SupplierCategoryEntry/services.ts b/src/pages/supplier/admission/SupplierCategoryEntry/services.ts index 0759cc8..21c29fe 100644 --- a/src/pages/supplier/admission/SupplierCategoryEntry/services.ts +++ b/src/pages/supplier/admission/SupplierCategoryEntry/services.ts @@ -62,3 +62,6 @@ export const add = (data: addInterface) => request.post('/coscoAccessWorkCategor * 品类选择查询树 */ export const categoryTree = () => request.get('/cosco/category/categoryTree'); + + +export const supplierChangeApprove = (data: { id:string; approveStatus:string }) => request.post('/synchronous/receiveCategoryApprove', { data }); \ No newline at end of file diff --git a/src/pages/supplier/admission/admissionManagement/index.tsx b/src/pages/supplier/admission/admissionManagement/index.tsx index af2bbae..0b57aa3 100644 --- a/src/pages/supplier/admission/admissionManagement/index.tsx +++ b/src/pages/supplier/admission/admissionManagement/index.tsx @@ -13,7 +13,7 @@ import AdmissionTypeSelect from '@/components/CommonSelect/AdmissionTypeSelect'; import AccessStatusSelect from '@/components/CommonSelect/AccessStatusSelect'; import AccessDepartmentSelect from "@/components/AccessDepartmentSelect" //接口 -import { getPage, startApprove } from './services' +import { getPage, startApprove, supplierChangeApprove } from './services' //统一列表分页 import tableProps from '@/utils/tableProps' @@ -112,7 +112,7 @@ const AccessManagement: React.FC = () => { }, { title: '操作', - width: 200, + width: 220, fixed: 'right', render: (_: any, record: any) => ( @@ -127,6 +127,15 @@ const AccessManagement: React.FC = () => { openModal('result', record)}>评审结果 )} + {record.approveStatus === '0' && ( + + )} ), @@ -173,7 +182,7 @@ const AccessManagement: React.FC = () => { dataSource={data} columns={columns} loading={loading} - pagination={{...tableProps.pagination, total: pagination.total }} + pagination={{ ...tableProps.pagination, total: pagination.total }} onChange={(pagination) => { const values = form.getFieldsValue(); getList(values, pagination.current!, pagination.pageSize!) diff --git a/src/pages/supplier/admission/admissionManagement/services.ts b/src/pages/supplier/admission/admissionManagement/services.ts index f067d20..a9d1dd3 100644 --- a/src/pages/supplier/admission/admissionManagement/services.ts +++ b/src/pages/supplier/admission/admissionManagement/services.ts @@ -123,4 +123,4 @@ export const startApprove = (params: startApproveData) => request.get(`/coscoAcc */ export const reviewInfoData = (params: startApproveData) => request.get(`/coscoAccessWork/reviewInfoData`, { params }); - +export const supplierChangeApprove = (data: { id:string; approveStatus:string }) => request.post('/synchronous/receiveApprove', { data }); \ No newline at end of file diff --git a/src/pages/supplier/informationManagement/SupplierChangeReviewManage/index.tsx b/src/pages/supplier/informationManagement/SupplierChangeReviewManage/index.tsx index 327540b..dcc8f23 100644 --- a/src/pages/supplier/informationManagement/SupplierChangeReviewManage/index.tsx +++ b/src/pages/supplier/informationManagement/SupplierChangeReviewManage/index.tsx @@ -5,7 +5,7 @@ import { SearchOutlined, DeleteOutlined } from '@ant-design/icons'; import DetailView from './components/DetailView'; import RegionTypeSelect from '@/components/CommonSelect/RegionTypeSelect' //接口 -import { getPage } from './services'; +import { getPage, supplierChangeApprove } from './services'; import type { ColumnsType } from 'antd/es/table'; //字典 import { getDictList } from '@/servers/api/dicts' @@ -189,9 +189,22 @@ const SupplierChangeReviewManage: React.FC = ({ dispatch }) => { width: 160, fixed: 'right', render: (_: any, record: any) => ( - + <> + + {/* 测试使用,需删除 */} + { record.approveStatus === '0' && ( + + )} + + ), }, ]; diff --git a/src/pages/supplier/informationManagement/SupplierChangeReviewManage/services.ts b/src/pages/supplier/informationManagement/SupplierChangeReviewManage/services.ts index 8cc37b8..81de15b 100644 --- a/src/pages/supplier/informationManagement/SupplierChangeReviewManage/services.ts +++ b/src/pages/supplier/informationManagement/SupplierChangeReviewManage/services.ts @@ -21,4 +21,4 @@ export const supplierChangeApplyById = (id: string) => request.get(`/coscoSuppli - +export const supplierChangeApprove = (data: { id:string; approveStatus:string }) => request.post('/synchronous/supplierChangeApprove', { data }); diff --git a/src/pages/supplier/supplierExit/supplierExitAudit/index.tsx b/src/pages/supplier/supplierExit/supplierExitAudit/index.tsx index 9dcc0d2..476269a 100644 --- a/src/pages/supplier/supplierExit/supplierExitAudit/index.tsx +++ b/src/pages/supplier/supplierExit/supplierExitAudit/index.tsx @@ -8,7 +8,7 @@ import ViewBlacklistModal from './components/ViewBlacklistModal'; import AccessDepartmentSelect from "@/components/AccessDepartmentSelect" //接口 import { getDictList } from '@/servers/api/dicts' -import { getPage } from './services' +import { getPage, supplierChangeApprove } from './services' //统一列表分页 import tableProps from '@/utils/tableProps' import moment from 'moment'; @@ -102,10 +102,11 @@ const supplierExitAudit: React.FC = () => { title: "操作", key: "option", align: "center", - width: 100, + width: 140, fixed: 'right', render: (record: any) => ( - + { setSelectedRecordId(record.id); setViewVisible(true); @@ -113,6 +114,17 @@ const supplierExitAudit: React.FC = () => { > 查看 + {record.approveStatus === '0' && ( + + )} + + ), }, ]; diff --git a/src/pages/supplier/supplierExit/supplierExitAudit/services.ts b/src/pages/supplier/supplierExit/supplierExitAudit/services.ts index 35993f6..4b517c1 100644 --- a/src/pages/supplier/supplierExit/supplierExitAudit/services.ts +++ b/src/pages/supplier/supplierExit/supplierExitAudit/services.ts @@ -84,4 +84,4 @@ export const coscoSupplierexit = (id: string) => request.get(`/coscoSupplierexit - +export const supplierChangeApprove = (data: { id:string; approveStatus:string }) => request.post('/synchronous/supplierCategoryTcApprove', { data }); diff --git a/src/servers/api/login.ts b/src/servers/api/login.ts index 5ee8b85..fea95bc 100644 --- a/src/servers/api/login.ts +++ b/src/servers/api/login.ts @@ -104,4 +104,17 @@ export async function reset(data: resetData) { method: 'POST', data }); -} \ No newline at end of file +} + +/** + * + * @param params + * @returns + * + */ +interface PasswordOnFirstLogin { + userId:string; + newPassword:string; + confirmPassword:string; +} +export const changePasswordOnFirstLogin = (data:PasswordOnFirstLogin) => request.post(`/v1/login/supplier/changePasswordOnFirstLogin`, { data}); \ No newline at end of file