diff --git a/config/config.UAT.ts b/config/config.UAT.ts index a022290..6e23f3e 100644 --- a/config/config.UAT.ts +++ b/config/config.UAT.ts @@ -12,7 +12,7 @@ export default defineConfig({ //密码加密参数 REACT_APP_PASSWORD_CIPHERMODE:'1', - REACT_APP_PASSWORD_PUBLICKEY:'0428D625CEEB71CE823BD7D78DFEE7B122F2DA5C4D21E32253AD684D0FE21810394A799639C0CDFBFEB535A1DFD6A366A637E582CE0B1466A5FE7858841135DE6B', + REACT_APP_PASSWORD_PUBLICKEY:'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCvLBkALIYR/x9Rv5TiXQGWAXTzraN/He80r9gQovSQ5oTP8qllL9+Oc1LdTijPFRsddHWg37umvFliwhmukU1NT+o2loGcKpyMHFkc/UPNjQLvd+YFR4nYhgP8l+dmRNOtQWawOt5dbksRKTghMjA+FKT2+itMsawSs1+Ic+zoIwIDAQAB', //当前环境 START_ENV:'UAT', diff --git a/config/config.dev.ts b/config/config.dev.ts index d7f0893..06c4372 100644 --- a/config/config.dev.ts +++ b/config/config.dev.ts @@ -12,7 +12,7 @@ export default defineConfig({ //密码加密参数 REACT_APP_PASSWORD_CIPHERMODE: '1', - REACT_APP_PASSWORD_PUBLICKEY: '0428D625CEEB71CE823BD7D78DFEE7B122F2DA5C4D21E32253AD684D0FE21810394A799639C0CDFBFEB535A1DFD6A366A637E582CE0B1466A5FE7858841135DE6B', + REACT_APP_PASSWORD_PUBLICKEY: 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCvLBkALIYR/x9Rv5TiXQGWAXTzraN/He80r9gQovSQ5oTP8qllL9+Oc1LdTijPFRsddHWg37umvFliwhmukU1NT+o2loGcKpyMHFkc/UPNjQLvd+YFR4nYhgP8l+dmRNOtQWawOt5dbksRKTghMjA+FKT2+itMsawSs1+Ic+zoIwIDAQAB', //当前环境 START_ENV: 'DEV', diff --git a/config/config.prod.ts b/config/config.prod.ts index 61ff507..5fbd4a6 100644 --- a/config/config.prod.ts +++ b/config/config.prod.ts @@ -12,7 +12,7 @@ export default defineConfig({ //密码加密参数 REACT_APP_PASSWORD_CIPHERMODE:'1', - REACT_APP_PASSWORD_PUBLICKEY:'04819CF427F9150FEEBD91E8D2346F203FC47312D212022A967D8372EA30B9581CCEEFCE2670BDDAF2E8DA1620EA73948126078ED9FF9773AA3A94EE6C80035A18', + REACT_APP_PASSWORD_PUBLICKEY:'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCvLBkALIYR/x9Rv5TiXQGWAXTzraN/He80r9gQovSQ5oTP8qllL9+Oc1LdTijPFRsddHWg37umvFliwhmukU1NT+o2loGcKpyMHFkc/UPNjQLvd+YFR4nYhgP8l+dmRNOtQWawOt5dbksRKTghMjA+FKT2+itMsawSs1+Ic+zoIwIDAQAB', //当前环境 START_ENV:'PROD', diff --git a/config/config.sim.ts b/config/config.sim.ts index 43156ec..ebda6bf 100644 --- a/config/config.sim.ts +++ b/config/config.sim.ts @@ -12,7 +12,7 @@ export default defineConfig({ //密码加密参数 REACT_APP_PASSWORD_CIPHERMODE: '1', - REACT_APP_PASSWORD_PUBLICKEY: '0428D625CEEB71CE823BD7D78DFEE7B122F2DA5C4D21E32253AD684D0FE21810394A799639C0CDFBFEB535A1DFD6A366A637E582CE0B1466A5FE7858841135DE6B', + REACT_APP_PASSWORD_PUBLICKEY: 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCvLBkALIYR/x9Rv5TiXQGWAXTzraN/He80r9gQovSQ5oTP8qllL9+Oc1LdTijPFRsddHWg37umvFliwhmukU1NT+o2loGcKpyMHFkc/UPNjQLvd+YFR4nYhgP8l+dmRNOtQWawOt5dbksRKTghMjA+FKT2+itMsawSs1+Ic+zoIwIDAQAB', //当前环境 START_ENV: 'sim', diff --git a/config/proxy.ts b/config/proxy.ts index 83636d7..ab6d58e 100644 --- a/config/proxy.ts +++ b/config/proxy.ts @@ -7,9 +7,9 @@ export default { // }, '/api/*': { // target: 'http://10.242.37.148:18022',//连接天宫的ng - target: 'http://localhost:3000',//连接天宫的ng + target: 'http://10.60.161.52:18030/',//连接天宫的ng changeOrigin: true, - pathRewrite: { '^': '' }, + pathRewrite: { '^/api': '' }, }, }, UAT: { @@ -38,11 +38,11 @@ export default { changeOrigin: true, pathRewrite: { '/api/biz-service-ebtp-process': '' }, }, - '/api/sys-manager-ebtp-project': { - target: 'http://localhost:18030', - changeOrigin: true, - pathRewrite: { '/api/sys-manager-ebtp-project': '' }, - }, + // '/api/sys-manager-ebtp-project': { + // target: 'http://localhost:18030', + // changeOrigin: true, + // pathRewrite: { '/api/sys-manager-ebtp-project': '' }, + // }, '/api/biz-service-ebtp-rsms': { target: 'http://localhost:18014', changeOrigin: true, diff --git a/config/router_transfer.ts b/config/router_transfer.ts index 81d12df..b6adc34 100644 --- a/config/router_transfer.ts +++ b/config/router_transfer.ts @@ -1,5 +1,9 @@ const { LOGIN_PATH } = process.env; export default [ + { + path: '/internal-login', + component: './Login/internal', + }, // {//内部人员便捷登陆页 // path: '/loginFake', // component: './Login/index', diff --git a/package.json b/package.json index 9fc119f..76d72f3 100644 --- a/package.json +++ b/package.json @@ -75,6 +75,7 @@ "dva": "2.4.1", "echarts": "^5.2.2", "echarts-for-react": "^3.0.2", + "jsencrypt": "^3.3.2", "lodash": "4.17.21", "moment": "^2.29.4", "omit.js": "2.0.2", diff --git a/src/components/CaptchaInput/index.less b/src/components/CaptchaInput/index.less new file mode 100644 index 0000000..fa599b1 --- /dev/null +++ b/src/components/CaptchaInput/index.less @@ -0,0 +1,48 @@ +.captchaContainer { + width: 100%; + + :global { + .ant-input-affix-wrapper { + padding-right: 4px; + } + } + + .captchaWrapper { + display: flex; + justify-content: end; + align-items: center; + gap: 8px; + height: 40px; + width: 120px; + } + + .captchaImage { + height: 40px; + width: 100%; + cursor: pointer; + border-radius: 4px; + border: 1px solid #d9d9d9; + object-fit: contain; + background: #fff; + + &:hover { + border-color: #40a9ff; + box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2); + } + } + + .refreshIcon { + font-size: 16px; + color: #1890ff; + cursor: pointer; + transition: all 0.3s; + padding: 4px; + + &:hover { + color: #40a9ff; + transform: rotate(180deg); + background: rgba(24, 144, 255, 0.1); + border-radius: 4px; + } + } +} \ No newline at end of file diff --git a/src/components/CaptchaInput/index.tsx b/src/components/CaptchaInput/index.tsx new file mode 100644 index 0000000..02752ca --- /dev/null +++ b/src/components/CaptchaInput/index.tsx @@ -0,0 +1,72 @@ +import React, { useState, useEffect, forwardRef, useImperativeHandle } from 'react'; +import { Input, Spin } from 'antd'; +import { SafetyOutlined } from '@ant-design/icons'; +import styles from './index.less'; +import { getCaptcha } from '@/services/login'; + +interface CaptchaInputProps { + value?: { + captcha: string; + captchaToken: string; + }; + onChange?: (value: { captcha: string; captchaToken: string }) => void; + placeholder?: string; +} + +export interface CaptchaInputRef { + refresh: () => void; +} + +const CaptchaInput = forwardRef((props: CaptchaInputProps, ref) => { + const { value, onChange, placeholder = '请输入验证码' } = props; + const [imgUrl, setImgUrl] = useState(''); + const [captchaToken, setCaptchaToken] = useState(''); + const [loading, setLoading] = useState(false); + + // 获取验证码 + const fetchCaptcha = async () => { + setLoading(true); + try { + const res = await getCaptcha(); + if (res?.success) { + setImgUrl('data:image/png;base64,' + res.data.base64Image); + setCaptchaToken(res.data.code); + } + } catch (error) { + console.error('获取验证码失败:', error); + } finally { + setLoading(false); + } + }; + + // 组件挂载时获取验证码 + useEffect(() => { + fetchCaptcha(); + }, []); + + useImperativeHandle(ref, () => ({ + refresh: fetchCaptcha, + })); + + return ( +
+ onChange?.({ captcha: e.target.value, captchaToken: captchaToken })} + placeholder={placeholder} + maxLength={4} + prefix={} + suffix={ +
+ {loading ? : 验证码} +
+ } + /> +
+ ); +}); + +CaptchaInput.displayName = 'CaptchaInput'; + +export default CaptchaInput; \ No newline at end of file diff --git a/src/components/GlobalHeader/services.ts b/src/components/GlobalHeader/services.ts index 750f8a5..a6ba67f 100644 --- a/src/components/GlobalHeader/services.ts +++ b/src/components/GlobalHeader/services.ts @@ -22,3 +22,9 @@ export async function getLogout() { // 退出登录,注销 // params }); } + +export async function logout() { + return request('/api/v1/login/logout', { + method: 'post', + }); +} \ No newline at end of file diff --git a/src/pages/LoadingPage/index.tsx b/src/pages/LoadingPage/index.tsx index deee6f5..b1aa6c7 100644 --- a/src/pages/LoadingPage/index.tsx +++ b/src/pages/LoadingPage/index.tsx @@ -76,7 +76,7 @@ const Loading: React.FC<{}> = () => { // } else { setUserData(userData, userData.authorityList[0].roleCode, userData.authorityList[0]); // } - await setDict();//存字典 + // await setDict();//存字典 setTimeout(() => { history.push({ pathname: `/${url}`, @@ -89,185 +89,185 @@ const Loading: React.FC<{}> = () => { //获取用户信息 async function getUserData(token: string, url: string, extra: any, status: number) { -const res = { - "userId": "ex-linjp29", - "lastName": null, - "firstName": null, - "fullName": "林剑萍", - "emailAddress": null, - "loginName": "ex-linjp29", - "mobilePhone": null, - "officePhone": null, - "sex": null, - "employeeCategory": null, - "userType": "1", - "dateOfBirth": null, - "age": null, - "employeeNumber": "1743164896", - "nationalityId": null, - "nationality": null, - "nationalIdentifier": null, - "supervisorId": null, - "organizationId": "101058278", - "organizationName": "湖北信通通信有限公司", - "orgCategory": null, - "deptId": "101058278", - "deptName": "湖北信通通信有限公司", - "roleIds": null, - "bussiGroupId": null, - "positionId": null, - "currentRoleCode": "undefined", - "province": null, - "authorityList": [ - { - "roleId": "000009", - "roleName": "代理机构业务经理", - "roleCode": "ebtp-agency-project-manager", - "roleScope": "EBTP", - "authorities": [ - "ebtp-agency-project-manager", - null, - "ebtp-agency-project-manager", - "ebtp-agency-project-manager,ebtp-expert,ebtp-supplier,ebtp-agency-admin", - "ebtp-agency-project-manager", - "ebtp-agency-project-manager,ebtp-expert,ebtp-supplier,ebtp-agency-admin", - "ebtp-agency-project-manager", - "ebtp-agency-project-manager", - null, - "ebtp-agency-project-manager", - null, - "ebtp-agency-project-manager", - "ebtp-agency-project-manager", - null, - "ebtp-agency-project-manager,ebtp-expert,ebtp-agency-admin", - null, - null, - "ebtp-agency-admin", - null, - null, - null, - null, - null, - null, - null, - "ebtp-agency-project-manager", - "ebtp-agency-project-manager,ebtp-purchase", - "ebtp-agency-project-manager,ebtp-purchase", - "ebtp-agency-project-manager,ebtp-purchase", - "ebtp-agency-project-manager,ebtp-purchase", - "ebtp-agency-project-manager,ebtp-purchase", - null, - null, - null, - null, - null, - "ebtp-agency-project-manager,ebtp-expert,ebtp-supplier", - "ebtp-agency-project-manager,ebtp-supplier", - "ebtp-agency-project-manager", - "ebtp-agency-project-manager", - null - ] - }, - { - "roleId": "000006", - "roleName": "供应商", - "roleCode": "ebtp-supplier", - "roleScope": "EBTP", - "authorities": [ - "system:user:test", - "ebtp-agency-project-manager,ebtp-expert,ebtp-supplier,ebtp-agency-admin", - "system:user:test", - "ebtp-agency-project-manager", - "ebtp-agency-project-manager,ebtp-expert,ebtp-supplier,ebtp-agency-admin", - "ebtp-supplier", - "ebtp-supplier", - "system:user:test", - "system:user:test", - "ebtp-agency-project-manager,ebtp-expert,ebtp-agency-admin", - "ebtp-supplier", - "system:user:test", - "ebtp-supplier", - "system:user:test", - "ebtp-supplier", - "ebtp-supplier", - "ebtp-supplier", - "ebtp-supplier", - "ebtp-supplier", - "ebtp-supplier", - "ebtp-supplier", - null, - null, - null, - "ebtp-agency-project-manager,ebtp-expert,ebtp-supplier", - "ebtp-agency-project-manager,ebtp-supplier", - "ebtp-supplier", - "system:user:test", - "system:user:test", - "system:user:test", - "ebtp-agency-project-manager", - "system:user:test" - ] - } - ] -} - if (res?.authorityList == null || res?.authorityList?.length == 0) { - if (url == 'ExamineAndApprove/Announcement' || - url == 'ExamineAndApprove/ChangeTheAnnouncement' || - url == 'ExamineAndApprove/Publicity' || - url == 'ExamineAndApprove/InvitationLetter' || - url == 'ExamineAndApprove/ExternalReference' || - url == 'ExamineAndApprove/FailureAnnouncement') { - let newAuthority: any[] = [] - newAuthority.push({ - authorities: [null, "system:user:test", "system:user:test", "system:user:test", "system:user:test", null, null], - roleCode: "ebtp-unicom-default", - roleId: "20004", - roleName: "联通普通用户", - roleScope: "EBTP" - }) - res.authorityList = [...newAuthority]; - await redirect(res, url, extra); +// const res = { +// "userId": "ex-linjp29", +// "lastName": null, +// "firstName": null, +// "fullName": "林剑萍", +// "emailAddress": null, +// "loginName": "ex-linjp29", +// "mobilePhone": null, +// "officePhone": null, +// "sex": null, +// "employeeCategory": null, +// "userType": "1", +// "dateOfBirth": null, +// "age": null, +// "employeeNumber": "1743164896", +// "nationalityId": null, +// "nationality": null, +// "nationalIdentifier": null, +// "supervisorId": null, +// "organizationId": "101058278", +// "organizationName": "湖北信通通信有限公司", +// "orgCategory": null, +// "deptId": "101058278", +// "deptName": "湖北信通通信有限公司", +// "roleIds": null, +// "bussiGroupId": null, +// "positionId": null, +// "currentRoleCode": "undefined", +// "province": null, +// "authorityList": [ +// { +// "roleId": "000009", +// "roleName": "代理机构业务经理", +// "roleCode": "ebtp-agency-project-manager", +// "roleScope": "EBTP", +// "authorities": [ +// "ebtp-agency-project-manager", +// null, +// "ebtp-agency-project-manager", +// "ebtp-agency-project-manager,ebtp-expert,ebtp-supplier,ebtp-agency-admin", +// "ebtp-agency-project-manager", +// "ebtp-agency-project-manager,ebtp-expert,ebtp-supplier,ebtp-agency-admin", +// "ebtp-agency-project-manager", +// "ebtp-agency-project-manager", +// null, +// "ebtp-agency-project-manager", +// null, +// "ebtp-agency-project-manager", +// "ebtp-agency-project-manager", +// null, +// "ebtp-agency-project-manager,ebtp-expert,ebtp-agency-admin", +// null, +// null, +// "ebtp-agency-admin", +// null, +// null, +// null, +// null, +// null, +// null, +// null, +// "ebtp-agency-project-manager", +// "ebtp-agency-project-manager,ebtp-purchase", +// "ebtp-agency-project-manager,ebtp-purchase", +// "ebtp-agency-project-manager,ebtp-purchase", +// "ebtp-agency-project-manager,ebtp-purchase", +// "ebtp-agency-project-manager,ebtp-purchase", +// null, +// null, +// null, +// null, +// null, +// "ebtp-agency-project-manager,ebtp-expert,ebtp-supplier", +// "ebtp-agency-project-manager,ebtp-supplier", +// "ebtp-agency-project-manager", +// "ebtp-agency-project-manager", +// null +// ] +// }, +// { +// "roleId": "000006", +// "roleName": "供应商", +// "roleCode": "ebtp-supplier", +// "roleScope": "EBTP", +// "authorities": [ +// "system:user:test", +// "ebtp-agency-project-manager,ebtp-expert,ebtp-supplier,ebtp-agency-admin", +// "system:user:test", +// "ebtp-agency-project-manager", +// "ebtp-agency-project-manager,ebtp-expert,ebtp-supplier,ebtp-agency-admin", +// "ebtp-supplier", +// "ebtp-supplier", +// "system:user:test", +// "system:user:test", +// "ebtp-agency-project-manager,ebtp-expert,ebtp-agency-admin", +// "ebtp-supplier", +// "system:user:test", +// "ebtp-supplier", +// "system:user:test", +// "ebtp-supplier", +// "ebtp-supplier", +// "ebtp-supplier", +// "ebtp-supplier", +// "ebtp-supplier", +// "ebtp-supplier", +// "ebtp-supplier", +// null, +// null, +// null, +// "ebtp-agency-project-manager,ebtp-expert,ebtp-supplier", +// "ebtp-agency-project-manager,ebtp-supplier", +// "ebtp-supplier", +// "system:user:test", +// "system:user:test", +// "system:user:test", +// "ebtp-agency-project-manager", +// "system:user:test" +// ] +// } +// ] +// } +// if (res?.authorityList == null || res?.authorityList?.length == 0) { +// if (url == 'ExamineAndApprove/Announcement' || +// url == 'ExamineAndApprove/ChangeTheAnnouncement' || +// url == 'ExamineAndApprove/Publicity' || +// url == 'ExamineAndApprove/InvitationLetter' || +// url == 'ExamineAndApprove/ExternalReference' || +// url == 'ExamineAndApprove/FailureAnnouncement') { +// let newAuthority: any[] = [] +// newAuthority.push({ +// authorities: [null, "system:user:test", "system:user:test", "system:user:test", "system:user:test", null, null], +// roleCode: "ebtp-unicom-default", +// roleId: "20004", +// roleName: "联通普通用户", +// roleScope: "EBTP" +// }) +// res.authorityList = [...newAuthority]; +// await redirect(res, url, extra); +// } +// }else { +// await redirect(res, url, extra); +// } + fgetUserMsg(token).then(async res => { + if (res) { + if (res?.userType == null) { + error('401'); + } else { + if (res?.authorityList == null || res?.authorityList?.length == 0) { + if (url == 'ExamineAndApprove/Announcement' || + url == 'ExamineAndApprove/ChangeTheAnnouncement' || + url == 'ExamineAndApprove/Publicity' || + url == 'ExamineAndApprove/InvitationLetter' || + url == 'ExamineAndApprove/ExternalReference' || + url == 'ExamineAndApprove/FailureAnnouncement') { + const newAuthority: any[] = [] + newAuthority.push({ + authorities: [null, "system:user:test", "system:user:test", "system:user:test", "system:user:test", null, null], + roleCode: "ebtp-cosco-default", + roleId: "20004", + roleName: "普通用户", + roleScope: "EBTP" + }) + res.authorityList = [...newAuthority]; + await redirect(res, url, extra); + } else { + if (status == 0) { + await refreshUserData(res?.userType, token, url, extra); + } else { + error('401'); + } + } + } else { + await redirect(res, url, extra); + } + } + } else { + message.error("登录信息有误,请重新登录") } - }else { - await redirect(res, url, extra); - } - // await fgetUserMsg(token).then(async res => { - // if (res) { - // if (res?.userType == null) { - // error('401'); - // } else { - // if (res?.authorityList == null || res?.authorityList?.length == 0) { - // if (url == 'ExamineAndApprove/Announcement' || - // url == 'ExamineAndApprove/ChangeTheAnnouncement' || - // url == 'ExamineAndApprove/Publicity' || - // url == 'ExamineAndApprove/InvitationLetter' || - // url == 'ExamineAndApprove/ExternalReference' || - // url == 'ExamineAndApprove/FailureAnnouncement') { - // let newAuthority: any[] = [] - // newAuthority.push({ - // authorities: [null, "system:user:test", "system:user:test", "system:user:test", "system:user:test", null, null], - // roleCode: "ebtp-unicom-default", - // roleId: "20004", - // roleName: "联通普通用户", - // roleScope: "EBTP" - // }) - // res.authorityList = [...newAuthority]; - // await redirect(res, url, extra); - // } else { - // if (status == 0) { - // await refreshUserData(res?.userType, token, url, extra); - // } else { - // error('401'); - // } - // } - // } else { - // await redirect(res, url, extra); - // } - // } - // } else { - // message.error("登录信息有误,请重新登录") - // } - // }) + }) } //通过code取token async function getToken(code: string, data: any) { diff --git a/src/pages/LoadingPage/service.ts b/src/pages/LoadingPage/service.ts index 1a8ec45..dc5401e 100644 --- a/src/pages/LoadingPage/service.ts +++ b/src/pages/LoadingPage/service.ts @@ -6,7 +6,7 @@ import request from '@/utils/request'; * @returns */ export async function fgetUserMsg(params: any) { - return request('/api/sys-manager-ebtp-project/v1/userinfo/get', { + return request('/api/v1/userinfo/get', { method: 'GET', headers: { 'Authorization': params }, data: params, diff --git a/src/pages/Login/internal.less b/src/pages/Login/internal.less new file mode 100644 index 0000000..5ba938b --- /dev/null +++ b/src/pages/Login/internal.less @@ -0,0 +1,100 @@ +.loginContainer { + display: flex; + justify-content: center; + align-items: center; + min-height: 100vh; + background-color: #f5f7fa; + padding: 20px; +} + +.loginCard { + width: 100%; + max-width: 480px; + box-shadow: 0 4px 24px rgba(0, 0, 0, 0.1); + border-radius: 8px; + + :global { + .ant-card-body { + padding: 40px 48px; + } + } +} + +.loginTabs { + :global { + // 自定义标签页样式 + .ant-tabs-tab { + font-size: 16px; + padding: 12px 24px; + margin: 0 8px !important; + + &:hover { + color: #1890ff; + } + } + + .ant-tabs-tab-active { + background-color: #1890ff; + color: #fff !important; + border-radius: 4px; + + .ant-tabs-tab-btn { + color: #fff !important; + } + } + + // 移除底部边框 + .ant-tabs-nav::before { + border: none; + } + + .ant-tabs-ink-bar { + display: none; + } + + // 表单样式 + .ant-form-item { + margin-bottom: 24px; + } + + // 登录按钮样式 + .ant-btn-primary { + height: 48px; + font-size: 16px; + border-radius: 4px; + + &:hover { + background-color: #40a9ff; + border-color: #40a9ff; + } + } + + // 输入框样式 + .ant-input-affix-wrapper { + border-radius: 4px; + + &:hover { + border-color: #40a9ff; + } + + &:focus, + &-focused { + border-color: #1890ff; + box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2); + } + } + + .ant-input { + border-radius: 4px; + + &:hover { + border-color: #40a9ff; + } + + &:focus { + border-color: #1890ff; + box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2); + } + } + } +} \ No newline at end of file diff --git a/src/pages/Login/internal.tsx b/src/pages/Login/internal.tsx new file mode 100644 index 0000000..1411700 --- /dev/null +++ b/src/pages/Login/internal.tsx @@ -0,0 +1,151 @@ +import React, { useEffect, useRef, useState } from 'react'; +import { Form, Input, Button, Checkbox, Card, Typography } from 'antd'; +import { UserOutlined, LockOutlined, EyeInvisibleOutlined, EyeTwoTone } from '@ant-design/icons'; +import { history } from 'umi'; +import cookie from 'react-cookies'; +import CaptchaInput from '@/components/CaptchaInput'; +import styles from './internal.less'; +import { internalUserLogin } from '@/services/login'; + +const { Title, Link } = Typography; + +interface LoginFormValues { + username: string; + password: string; + captcha: { + captcha: string; + captchaToken: string; + }; + remember: boolean; +} + +const InternalLogin: React.FC = () => { + const [form] = Form.useForm(); + const [loading, setLoading] = useState(false); + const captchaRef = useRef(null); + + const onFinish = async (values: LoginFormValues) => { + const params = { + account: values.username, + password: values.password, + captcha: values.captcha, + remember: values.remember, + } + try { + setLoading(true); + const res = await internalUserLogin(params); + if (res?.code === 200) { + sessionStorage.setItem('Authorization', res?.data?.token || ''); + history.push('/redirect'); + } else { + captchaRef.current?.refresh(); + form.setFieldsValue({ + captcha: { + captcha: '', + captchaToken: '', + }, + }); + } + } catch (error) { + console.error('登录失败:', error); + } finally { + setLoading(false); + } + }; + + + // 组件挂载时,检查是否有记住的用户名 + useEffect(() => { + const savedUser = localStorage.getItem('remember_user'); + if (savedUser) { + const user = JSON.parse(savedUser); + form.setFieldsValue({ + username: user.username, + password: user.password, + remember: true, + }); + } + }, [form]); + + useEffect(() => { + cookie.remove('mall3_token'); + sessionStorage.clear(); + }, []); + + const renderLoginForm = () => ( +
+ + } + placeholder={'请输入用户名'} + /> + + + + } + placeholder="请输入密码" + iconRender={(visible) => (visible ? : )} + /> + + + + + + + +
+ + 记住密码 + + 忘记密码? +
+
+ + + + + +
+ 还没有账号? + 立即注册 +
+
+ ); + + return ( +
+ + + 电子招投标平台 + + + {renderLoginForm()} + +
+ ); +}; + +export default InternalLogin; \ No newline at end of file diff --git a/src/pages/Project/ProjectManage/ProjectManager/ProjectDocumentation/components/ProjectDocumentation.tsx b/src/pages/Project/ProjectManage/ProjectManager/ProjectDocumentation/components/ProjectDocumentation.tsx index ad9105b..98ce7ee 100644 --- a/src/pages/Project/ProjectManage/ProjectManager/ProjectDocumentation/components/ProjectDocumentation.tsx +++ b/src/pages/Project/ProjectManage/ProjectManager/ProjectDocumentation/components/ProjectDocumentation.tsx @@ -47,7 +47,7 @@ const ProjectDocumentation: React.FC = () => { title: '采购方式', dataIndex: 'bidMethodDict', valueType: 'select', - valueEnum: proTableValueEnumOther(dictData[procurementModeEntrust], proTypeCode), + valueEnum: proTableValueEnumOther(dictData?.[procurementModeEntrust], proTypeCode), search: proTypeCode.length > 1 ? void 0 : false, }, title: { diff --git a/src/pages/Tender/supplier/InvitationLetter/components/InvitationLetter.tsx b/src/pages/Tender/supplier/InvitationLetter/components/InvitationLetter.tsx index e99c566..437da6d 100644 --- a/src/pages/Tender/supplier/InvitationLetter/components/InvitationLetter.tsx +++ b/src/pages/Tender/supplier/InvitationLetter/components/InvitationLetter.tsx @@ -206,7 +206,7 @@ const LookingForBusinessOpportunitiesList: React.FC = () => { dataIndex: 'bidMethodDict', search: proTypeCode?.length > 1 ? void 0 : false, width: '8%', - valueEnum: proTableValueEnumOther(dictData[procurementModeEntrust], proTypeCode) + valueEnum: proTableValueEnumOther(dictData?.[procurementModeEntrust], proTypeCode) }, { title: '项目名称', diff --git a/src/services/login.ts b/src/services/login.ts index 075bca8..4632326 100644 --- a/src/services/login.ts +++ b/src/services/login.ts @@ -1,5 +1,6 @@ import request from '@/utils/request'; import { getEncrypt } from '@/utils/session'; +import { encryptData } from '@/utils/encrypt'; export interface LoginParamsType { userName: string; @@ -13,6 +14,14 @@ export interface FaceLoginParamsType { multipartFiles: Blob; } +export interface InternalUserLoginParamsType { + account: string; + password: string; + captcha: { + captcha: string; + captchaToken: string; + }; +} const sm2 = require('sm-crypto').sm2; const encrypt = getEncrypt(); @@ -61,7 +70,7 @@ export async function ZjfakeAccountLogin(params: LoginParamsType) { // 专家人脸登录 export async function ZjfakeFaceLogin(params: FaceLoginParamsType) { - var formData = new FormData(); + const formData = new FormData(); formData.append('idNo', params.userName); formData.append('multipartFiles', params.multipartFiles, 'upload_face.jpeg'); return request('/api/sys-manager-ebtp-project/outer/v1/ebtp/face/faceCompare', { @@ -133,3 +142,31 @@ export async function logoutTokenApi() { // params: params }); } + +/** + * 获取图形验证码 + * @returns Promise<{ success: boolean; data: { base64Image: string, code: string } }> + */ +export async function getCaptcha() { + return request('/api/v1/login/getCaptcha', { + method: 'GET', + }); +} + +/** + * 内部用户登录 + */ +export async function internalUserLogin(params: InternalUserLoginParamsType) { + // 加密密码 + const encryptedPassword = encryptData(params.password); + const data = { + account: params.account, + password: encryptedPassword, + identifying: params.captcha.captcha, + encryptValue: params.captcha.captchaToken, + } + return request('/api/v1/login/accountLogin', { + method: 'POST', + data, + }); +} \ No newline at end of file diff --git a/src/utils/encrypt.ts b/src/utils/encrypt.ts new file mode 100644 index 0000000..ae499a0 --- /dev/null +++ b/src/utils/encrypt.ts @@ -0,0 +1,9 @@ +import JSEncrypt from 'jsencrypt'; + +const encrypt = new JSEncrypt(); + +encrypt.setPublicKey(REACT_APP_PASSWORD_PUBLICKEY); + +export function encryptData(data: string) { + return encrypt.encrypt(data) || ''; +} diff --git a/src/utils/request.ts b/src/utils/request.ts index af6b1c6..db5c5b9 100644 --- a/src/utils/request.ts +++ b/src/utils/request.ts @@ -94,6 +94,7 @@ request.interceptors.request.use(async (url, options) => { headers = { Authorization: getUserToken() == null ? null : getUserToken(), currentRoleCode: getSessionRoleData()?.roleCode, + Mall3Check: 'mall3_token', ...options.headers, }; } diff --git a/src/utils/session.ts b/src/utils/session.ts index 004c04b..a4737c4 100644 --- a/src/utils/session.ts +++ b/src/utils/session.ts @@ -257,7 +257,7 @@ export async function jurySaveInfo(record: any) { * 获取国密加密算法需要的属性 */ export function getEncrypt() { - let encrypt = { + const encrypt = { cipherMode: REACT_APP_PASSWORD_CIPHERMODE, publicKey: REACT_APP_PASSWORD_PUBLICKEY }