diff --git a/.env.development b/.env.development index fdc813c..8bc17b0 100644 --- a/.env.development +++ b/.env.development @@ -31,3 +31,6 @@ VITE_APP_SUB_jeecg-app-1 = '//localhost:8092' # 在线文档编辑版本。可选属性:wps, onlyoffice VITE_GLOB_ONLINE_DOCUMENT_VERSION=wps + +# AutoLogin SSO - 指向 demo 网关 +VITE_AUTOLOGIN_URL=http://localhost:9100/api/sys/autoLogin diff --git a/.env.production b/.env.production index 6f389f4..f29f56f 100644 --- a/.env.production +++ b/.env.production @@ -32,3 +32,6 @@ VITE_GLOB_API_URL_PREFIX= # 在线文档编辑版本。可选属性:wps, onlyoffice VITE_GLOB_ONLINE_DOCUMENT_VERSION=wps + +# AutoLogin SSO - 指向生产网关(地址由运维提供) +VITE_AUTOLOGIN_URL=http://200.100.65.101:9100/api/sys/autoLogin diff --git a/src/api/sys/autologin.ts b/src/api/sys/autologin.ts new file mode 100644 index 0000000..53a33dd --- /dev/null +++ b/src/api/sys/autologin.ts @@ -0,0 +1,16 @@ +import { defHttp } from '/@/utils/http/axios'; + +enum AutoLoginApi { + AutoLogin = '/sys/autoLogin', + IpAutoLogin = '/sys/ipAutoLogin', +} + +/** 自动登录 — 请求网关地址(由 VITE_AUTOLOGIN_URL 控制),form 表单格式 */ +export function autoLoginApi() { + const url = import.meta.env.VITE_AUTOLOGIN_URL || AutoLoginApi.AutoLogin; + return defHttp.post({ + url, + data: 'username=&password=', + headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, + }); +} diff --git a/src/components/semri/deptUserComponent/SzDeptUserModal.vue b/src/components/semri/deptUserComponent/SzDeptUserModal.vue new file mode 100644 index 0000000..d7b0f4e --- /dev/null +++ b/src/components/semri/deptUserComponent/SzDeptUserModal.vue @@ -0,0 +1,158 @@ + + + + + diff --git a/src/components/semri/deptUserComponent/SzDeptUserSelect.vue b/src/components/semri/deptUserComponent/SzDeptUserSelect.vue new file mode 100644 index 0000000..f994eb4 --- /dev/null +++ b/src/components/semri/deptUserComponent/SzDeptUserSelect.vue @@ -0,0 +1,389 @@ + + + + + diff --git a/src/components/semri/deptUserComponent/SzDeptUserSelectedList.vue b/src/components/semri/deptUserComponent/SzDeptUserSelectedList.vue new file mode 100644 index 0000000..a7a0e09 --- /dev/null +++ b/src/components/semri/deptUserComponent/SzDeptUserSelectedList.vue @@ -0,0 +1,55 @@ + + + + + diff --git a/src/components/semri/deptUserComponent/types.ts b/src/components/semri/deptUserComponent/types.ts new file mode 100644 index 0000000..b8d6c32 --- /dev/null +++ b/src/components/semri/deptUserComponent/types.ts @@ -0,0 +1,68 @@ +export interface UserItem { + id: string; + username: string; + realname: string; + orgCodeTxt?: string; + userSecurityLevel?: number; + userSecurityLevel_dictText?: string; + sex_dictText?: string; + sortno?: number; + departId?: string; + departName?: string; +} + +export interface DepartTreeNode { + id: string; + key: string; + value: string; + title: string; + isLeaf?: boolean; + departType?: string | number; + distributable?: number; + disableCheckbox?: boolean; + children?: DepartTreeNode[]; + description?: string; + parentId?: string; + orgCode?: string; +} + +export function deleteIfExist>(array: T[], value: T, key: string): void { + const idx = array.findIndex((item) => item[key] === value[key]); + if (idx >= 0) { + array.splice(idx, 1); + } +} + +export function pushIfNotExist>(array: T[], value: T, key: string): void { + const idx = array.findIndex((item) => item[key] === value[key]); + if (idx < 0) { + array.push(value); + } +} + +export function filterDepartTree>(departTree: T[], searchValue: string): T[] { + let filtered: T[] = []; + departTree.forEach((item) => { + if (item.title && item.title.includes(searchValue)) { + filtered.push(Object.assign({}, item, { children: null, isLeaf: true })); + } + if (item.children) { + const result = filterDepartTree(item.children, searchValue); + if (result.length > 0) { + filtered = filtered.concat(result); + } + } + }); + return filtered; +} + +export function recurTree, R>(tree: T[], callback: (node: T) => R[]): R[] { + let res: R[] = []; + tree.forEach((item) => { + res = res.concat(callback(item)); + if (item.children) { + res = res.concat(recurTree(item.children, callback)); + } + }); + return res; +} diff --git a/src/enums/pageEnum.ts b/src/enums/pageEnum.ts index 58651ac..4443abc 100644 --- a/src/enums/pageEnum.ts +++ b/src/enums/pageEnum.ts @@ -1,6 +1,6 @@ export enum PageEnum { // basic login path - BASE_LOGIN = '/login', + BASE_LOGIN = '/user/login', // basic home path BASE_HOME = '/dashboard/analysis', // error page path @@ -12,5 +12,9 @@ export enum PageEnum { //文件路由 SYS_FILES_PATH = '/file/share', // 邮件中的跳转地址 - TOKEN_LOGIN = '/tokenLogin' + TOKEN_LOGIN = '/tokenLogin', + // 自动登录路径 + AUTOLOGIN_PATH = '/user/autoLogin', + // 登出结果页路径 + LOGOUT_RESULT_PATH = '/user/logoutResult', } diff --git a/src/router/guard/permissionGuard.ts b/src/router/guard/permissionGuard.ts index 89a297f..0abc35b 100644 --- a/src/router/guard/permissionGuard.ts +++ b/src/router/guard/permissionGuard.ts @@ -28,7 +28,7 @@ const ROOT_PATH = RootRoute.path; //update-begin---author:wangshuai ---date:20220629 for:[issues/I5BG1I]vue3不支持auth2登录------------ //update-begin---author:wangshuai ---date:20221111 for: [VUEN-2472]分享免登录------------ -const whitePathList: PageEnum[] = [LOGIN_PATH, OAUTH2_LOGIN_PAGE_PATH,SYS_FILES_PATH, TOKEN_LOGIN ]; +const whitePathList: PageEnum[] = [LOGIN_PATH, OAUTH2_LOGIN_PAGE_PATH,SYS_FILES_PATH, TOKEN_LOGIN, PageEnum.AUTOLOGIN_PATH, PageEnum.LOGOUT_RESULT_PATH ]; //update-end---author:wangshuai ---date:20221111 for: [VUEN-2472]分享免登录------------ //update-end---author:wangshuai ---date:20220629 for:[issues/I5BG1I]vue3不支持auth2登录------------ @@ -57,7 +57,7 @@ export function createPermissionGuard(router: Router) { // Whitelist can be directly entered if (whitePathList.includes(to.path as PageEnum)) { - if (to.path === LOGIN_PATH && token) { + if ((to.path === LOGIN_PATH || to.path === PageEnum.AUTOLOGIN_PATH) && token) { const isSessionTimeout = userStore.getSessionTimeout; //update-begin---author:scott ---date:2023-04-24 for:【QQYUN-4713】登录代码调整逻辑有问题,改造待观察-- @@ -122,7 +122,7 @@ export function createPermissionGuard(router: Router) { //---------【首次登陆并且是企业微信或者钉钉的情况下才会调用】------------------------------------------------ //update-end---author:wangshuai ---date:20230302 for:只有首次登陆并且是企业微信或者钉钉的情况下才会调用------------ // 如果当前是在OAuth2APP环境,就跳转到OAuth2登录页面,否则跳转到登录页面 - path = isOAuth2AppEnv() ? OAUTH2_LOGIN_PAGE_PATH : LOGIN_PATH; + path = isOAuth2AppEnv() ? OAUTH2_LOGIN_PAGE_PATH : PageEnum.AUTOLOGIN_PATH; } //update-end---author:wangshuai ---date:20220629 for:[issues/I5BG1I]vue3 Auth2未实现------------ // redirect login page diff --git a/src/router/routes/index.ts b/src/router/routes/index.ts index 3a1ed5c..152c18c 100644 --- a/src/router/routes/index.ts +++ b/src/router/routes/index.ts @@ -29,7 +29,7 @@ export const RootRoute: AppRouteRecordRaw = { }; export const LoginRoute: AppRouteRecordRaw = { - path: '/login', + path: '/user/login', name: 'Login', //新版后台登录,如果想要使用旧版登录放开即可 // component: () => import('/@/views/sys/login/Login.vue'), @@ -65,6 +65,26 @@ export const TokenLoginRoute: AppRouteRecordRaw = { }, }; // update-begin--author:liaozhiyang---date:20240301---for:【QQYUN-7967】新增、编辑路由访问 +export const AutoLoginRoute: AppRouteRecordRaw = { + path: '/user/autoLogin', + name: 'AutoLogin', + component: () => import('/@/views/sys/login/AutoLogin.vue'), + meta: { + title: '自动登录', + ignoreAuth: true, + }, +}; + +export const LogoutResultRoute: AppRouteRecordRaw = { + path: '/user/logoutResult', + name: 'LogoutResult', + component: () => import('/@/views/sys/login/LogoutResult.vue'), + meta: { + title: '退出登录', + ignoreAuth: true, + }, +}; + export const formUrlDetail = { path: '/online/formUrlDetail/:id/:dataId', name: 'formUrlDetail', @@ -107,4 +127,4 @@ export const formUrlSuccess = { // update-end--author:liaozhiyang---date:20240301---for:【QQYUN-7967】新增、编辑路由访问 // Basic routing without permission -export const basicRoutes = [LoginRoute, RootRoute, ...mainOutRoutes, REDIRECT_ROUTE, PAGE_NOT_FOUND_ROUTE, TokenLoginRoute, Oauth2LoginRoute,formUrlDetail, formUrlAdd, formUrlEdit, formUrlSuccess]; +export const basicRoutes = [LoginRoute, RootRoute, ...mainOutRoutes, REDIRECT_ROUTE, PAGE_NOT_FOUND_ROUTE, TokenLoginRoute, Oauth2LoginRoute, AutoLoginRoute, LogoutResultRoute,formUrlDetail, formUrlAdd, formUrlEdit, formUrlSuccess]; diff --git a/src/store/modules/user.ts b/src/store/modules/user.ts index 099710d..2c97c87 100644 --- a/src/store/modules/user.ts +++ b/src/store/modules/user.ts @@ -8,6 +8,7 @@ import { ROLES_KEY, TOKEN_KEY, USER_INFO_KEY, LOGIN_INFO_KEY, DB_DICT_DATA_KEY, import { getAuthCache, setAuthCache, removeAuthCache } from '/@/utils/auth'; import { GetUserInfoModel, LoginParams, ThirdLoginParams } from '/@/api/sys/model/userModel'; import { doLogout, getUserInfo, loginApi, phoneLoginApi, thirdLogin } from '/@/api/sys/user'; + import { autoLoginApi } from '/@/api/sys/autologin'; import { useI18n } from '/@/hooks/web/useI18n'; import { useMessage } from '/@/hooks/web/useMessage'; import { router } from '/@/router'; @@ -161,6 +162,20 @@ export const useUserStore = defineStore({ return Promise.reject(error); } }, + /** + * 网关自动登录 — 跳过密码,由网关注入身份 + */ + async autoLogin(goHome = true): Promise { + try { + const data = await autoLoginApi(); + const { token, userInfo } = data; + this.setToken(token); + this.setTenant(userInfo.loginTenantId); + return this.afterLoginAction(goHome, data); + } catch (error) { + return Promise.reject(error); + } + }, /** * 扫码登录事件 */ @@ -330,7 +345,7 @@ export const useUserStore = defineStore({ }else{ // update-begin-author:sunjianlei date:20230306 for: 修复登录成功后,没有正确重定向的问题 goLogin && (await router.push({ - path: PageEnum.BASE_LOGIN, + path: PageEnum.LOGOUT_RESULT_PATH, query: { // 传入当前的路由,登录成功后跳转到当前路由 redirect: router.currentRoute.value.fullPath, diff --git a/src/views/bg/bgpartymatter/components/BgPartymatterBPMForm.vue b/src/views/bg/bgpartymatter/components/BgPartymatterBPMForm.vue index ed99695..9629856 100644 --- a/src/views/bg/bgpartymatter/components/BgPartymatterBPMForm.vue +++ b/src/views/bg/bgpartymatter/components/BgPartymatterBPMForm.vue @@ -184,13 +184,10 @@ - - - + @@ -226,7 +223,7 @@ import JDictSelectTag from "../../../../components/Form/src/jeecg/components/JDictSelectTag.vue"; import BgPartymatterBPMFeedbackModal from './BgPartymatterBPMFeedbackModal.vue'; import SUploadFile from '/@/components/semri/fileComponent/SUploadFile.vue'; - import JSelectUser from "../../../../components/Form/src/jeecg/components/JSelectUser.vue"; + import SzDeptUserModal from '/@/components/semri/deptUserComponent/SzDeptUserModal.vue'; const { isDisabledAuth, hasPermission, initBpmFormData} = usePermission(); const props = defineProps({ diff --git a/src/views/bg/xispeak/components/BgXiSpeakBPMForm.vue b/src/views/bg/xispeak/components/BgXiSpeakBPMForm.vue index e23e455..c7ce7f1 100644 --- a/src/views/bg/xispeak/components/BgXiSpeakBPMForm.vue +++ b/src/views/bg/xispeak/components/BgXiSpeakBPMForm.vue @@ -262,6 +262,7 @@ :claim="claim" :showSelnextUser="showSelnextUser" :beforeHandle="saveMainFormBeforeProcessHandle" + :defaultReason="defaultHandleReason" @success="handleProcessSuccess" @claimSuccess="handleClaimSuccess" /> @@ -441,6 +442,59 @@ processTableName: props.formData?.processTableName, })); + // ==================== 默认审批意见 ==================== + const handleReasonTemplateMap: Record string> = { + // TODO: 填写各节点的 taskDefKey + // 部门负责人审批 / 所党委审批 / 督办部门负责人审批 / 纪检负责人审批 + // 'Task_': buildApproveReason, + // 部门经办人反馈完成情况 / 收集流程部门经办人填写 / 反馈流程部门经办人填写反馈 + // 'Task_': buildDeptHandlerFeedbackReason, + // 部门负责人接受任务并分配 + // 'Task_': buildDeptLeaderAssignReason, + // 部门负责人直接反馈 + // 'Task_': buildDeptLeaderDirectFeedbackReason, + // 督办部门经办人确认全部反馈事项 + // 'Task_': buildSuperviseConfirmAllReason, + // 督办经办人核查 / 反馈流程督办经办人核查 + // 'Task_': buildSuperviseCheckReason, + // 纪检经办人监察 + // 'Task_': buildJiJianCheckReason, + }; + + const defaultHandleReason = computed(() => { + const builder = handleReasonTemplateMap[String(processInfo.value.taskDefKey || '')]; + return builder ? builder() : ''; + }); + + function buildApproveReason() { + return '同意。'; + } + + function buildDeptHandlerFeedbackReason() { + return '已完成反馈,请领导审批。'; + } + + function buildDeptLeaderAssignReason() { + const userNameText = subApproveUser.value || ''; + return userNameText ? `请${userNameText}办理。` : ''; + } + + function buildDeptLeaderDirectFeedbackReason() { + return '已完成反馈。'; + } + + function buildSuperviseConfirmAllReason() { + return '已确认全部反馈事项。'; + } + + function buildSuperviseCheckReason() { + return '已核查。'; + } + + function buildJiJianCheckReason() { + return '已监察。'; + } + onMounted(() => { initFormData(); }); diff --git a/src/views/dq/inspectTask/components/DqInspectTaskBPMForm.vue b/src/views/dq/inspectTask/components/DqInspectTaskBPMForm.vue index 4e838b1..38ab75b 100644 --- a/src/views/dq/inspectTask/components/DqInspectTaskBPMForm.vue +++ b/src/views/dq/inspectTask/components/DqInspectTaskBPMForm.vue @@ -29,7 +29,12 @@ - + - +