.env.development
@@ -11,7 +11,7 @@ VITE_APP_CONTEXT_PATH = '/' # 监控地址 VITE_APP_MONITRO_ADMIN = 'http://localhost:9090/admin/applications' VITE_APP_MONITOR_ADMIN = 'http://localhost:9090/admin/applications' # SnailJob 控制台地址 VITE_APP_SNAILJOB_ADMIN = 'http://localhost:8800/snail-job' .env.production
@@ -8,7 +8,7 @@ VITE_APP_CONTEXT_PATH = '/' # 监控地址 VITE_APP_MONITRO_ADMIN = '/admin/applications' VITE_APP_MONITOR_ADMIN = '/admin/applications' # SnailJob 控制台地址 VITE_APP_SNAILJOB_ADMIN = '/snail-job' package.json
@@ -1,6 +1,6 @@ { "name": "ruoyi-vue-plus", "version": "5.2.0-BETA", "version": "5.2.0", "description": "RuoYi-Vue-Plus多租户管理系统", "author": "LionLi", "license": "MIT", @@ -30,7 +30,7 @@ "diagram-js": "12.3.0", "didi": "9.0.2", "echarts": "5.5.0", "element-plus": "2.7.2", "element-plus": "2.7.5", "file-saver": "2.0.5", "fuse.js": "7.0.0", "highlight.js": "11.9.0", src/api/system/social/auth.ts
@@ -1,10 +1,14 @@ import request from '@/utils/request'; // 绑定账号 export function authBinding(source: string) { export function authBinding(source: string, tenantId: string) { return request({ url: '/auth/binding/' + source, method: 'get' method: 'get', params: { tenantId: tenantId, domain: window.location.host } }); } src/api/system/user/types.ts
@@ -26,6 +26,7 @@ */ export interface UserVO extends BaseEntity { userId: string | number; tenantId: string; deptId: number; userName: string; nickName: string; src/api/workflow/processInstance/index.ts
@@ -53,7 +53,7 @@ * @param businessKey 业务id * @returns */ export const getHistoryRecord = (businessKey: string) => { export const getHistoryRecord = (businessKey: string | number) => { return request({ url: `/workflow/processInstance/getHistoryRecord/${businessKey}`, method: 'get' src/bpmn/panel/TaskPanel.vue
@@ -281,12 +281,11 @@ const roleSelectRef = ref<InstanceType<typeof RoleSelect>>(); const dueDateRef = ref<InstanceType<typeof DueDate>>(); const isMultiple = ref(true); const openUserSelect = () => { userSelectRef.value.open(); }; const openSingleUserSelect = () => { if (formData.value.assignee.includes('$')) { if (formData.value.assignee?.includes('$')) { formData.value.assignee = ''; } singleUserSelectRef.value.open(); src/components/Process/approvalRecord.vue
@@ -67,7 +67,7 @@ const bpmnViewRef = ref<BpmnView>(); //初始化查询审批记录 const init = async (businessKey: string) => { const init = async (businessKey: string | number) => { visible.value = true; loading.value = true; tabActiveName.value = 'bpmn'; src/components/Process/multiInstanceUser.vue
@@ -1,22 +1,28 @@ <template> <el-dialog v-model="visible" draggable :title="title" :width="width" :height="height" append-to-body :close-on-click-modal="false"> <div class="p-2" v-if="multiInstance === 'add'"> <el-dialog v-model="visible" draggable :title="title" :width="width" :height="height" append-to-body :close-on-click-modal="false"> <div v-if="multiInstance === 'add'" class="p-2"> <el-row :gutter="20"> <!-- 部门树 --> <el-col :lg="4" :xs="24" style=""> <el-card shadow="hover"> <el-input v-model="deptName" placeholder="请输入部门名称" prefix-icon="Search" clearable /> <el-tree class="mt-2" ref="deptTreeRef" node-key="id" :data="deptOptions" :props="{ label: 'label', children: 'children' }" :expand-on-click-node="false" :filter-node-method="filterNode" highlight-current default-expand-all @node-click="handleNodeClick"></el-tree> <el-tree ref="deptTreeRef" class="mt-2" node-key="id" :data="deptOptions" :props="{ label: 'label', children: 'children' }" :expand-on-click-node="false" :filter-node-method="filterNode" highlight-current default-expand-all @node-click="handleNodeClick" ></el-tree> </el-card> </el-col> <el-col :lg="20" :xs="24"> <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave"> <div class="search" v-show="showSearch"> <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave"> <div v-show="showSearch" class="search"> <el-form ref="queryFormRef" :model="queryParams" :inline="true"> <el-form-item label="用户名称" prop="userName"> <el-input v-model="queryParams.userName" placeholder="请输入用户名称" clearable @keyup.enter="handleQuery" /> @@ -25,8 +31,8 @@ <el-input v-model="queryParams.phonenumber" placeholder="请输入手机号码" clearable @keyup.enter="handleQuery" /> </el-form-item> <el-form-item> <el-button type="primary" @click="handleQuery" icon="Search">搜索</el-button> <el-button @click="resetQuery" icon="Refresh">重置</el-button> <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button> <el-button icon="Refresh" @click="resetQuery">重置</el-button> </el-form-item> </el-form> </div> @@ -35,17 +41,16 @@ <el-card shadow="hover"> <template #header> <el-row :gutter="10"> <right-toolbar v-model:showSearch="showSearch" @queryTable="handleQuery" :search="true"></right-toolbar> <right-toolbar v-model:showSearch="showSearch" :search="true" @query-table="handleQuery"></right-toolbar> </el-row> </template> <el-table v-loading="loading" :data="userList" ref="multipleTableRef" row-key="userId" @selection-change="handleSelectionChange"> <el-table ref="multipleTableRef" v-loading="loading" :data="userList" row-key="userId" @selection-change="handleSelectionChange"> <el-table-column type="selection" width="50" align="center" /> <el-table-column label="用户编号" align="center" key="userId" prop="userId" /> <el-table-column label="用户名称" align="center" key="userName" prop="userName" :show-overflow-tooltip="true" /> <el-table-column label="用户昵称" align="center" key="nickName" prop="nickName" :show-overflow-tooltip="true" /> <el-table-column label="手机号码" align="center" key="phonenumber" prop="phonenumber" width="120" /> <el-table-column key="userId" label="用户编号" align="center" prop="userId" /> <el-table-column key="userName" label="用户名称" align="center" prop="userName" :show-overflow-tooltip="true" /> <el-table-column key="nickName" label="用户昵称" align="center" prop="nickName" :show-overflow-tooltip="true" /> <el-table-column key="phonenumber" label="手机号码" align="center" prop="phonenumber" width="120" /> <el-table-column label="创建时间" align="center" prop="createTime" width="160"> <template #default="scope"> <span>{{ scope.row.createTime }}</span> @@ -53,18 +58,23 @@ </el-table-column> </el-table> <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="handleQuery" /> <pagination v-show="total > 0" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" :total="total" @pagination="handleQuery" /> </el-card> <el-card shadow="hover"> <el-tag v-for="(user, index) in chooseUserList" :key="user.userId" style="margin:2px" closable @close="handleCloseTag(user, index)">{{ user.userName }} <el-tag v-for="(user, index) in chooseUserList" :key="user.userId" style="margin: 2px" closable @close="handleCloseTag(user, index)" >{{ user.userName }} </el-tag> </el-card> </el-col> </el-row> </div> <div class="p-2" v-if="multiInstance === 'delete'"> <div v-if="multiInstance === 'delete'" class="p-2"> <el-table v-loading="loading" :data="taskList" @selection-change="handleTaskSelection"> <el-table-column type="selection" width="55" /> <el-table-column prop="name" label="任务名称" /> @@ -285,7 +295,7 @@ //删除tag const handleCloseTag = (user: UserVO, index: any) => { if (multipleTableRef.value.selection && multipleTableRef.value.selection.length > 0) { multipleTableRef.value.selection.forEach((u: UserVO, i: Number) => { multipleTableRef.value.selection.forEach((u: UserVO, i: number) => { if (user.userId === u.userId) { multipleTableRef.value.selection.splice(i, 1); } src/layout/components/SocialCallback/index.vue
@@ -17,7 +17,9 @@ const code = route.query.code as string; const state = route.query.state as string; const source = route.query.source as string; const tenantId = localStorage.getItem('tenantId') ? (localStorage.getItem('tenantId') as string) : '000000'; const stateJson = JSON.parse(atob(state)); const tenantId = stateJson.tenantId as string ? stateJson.tenantId as string : '000000'; const domain = stateJson.domain as string; const processResponse = async (res: any) => { if (res.code !== 200) { @@ -60,12 +62,21 @@ }; const init = async () => { // 如果域名不相等 则重定向处理 let host = window.location.host; if (domain !== host) { let urlFull = new URL(window.location.href); urlFull.host = domain; window.location.href = urlFull.toString(); return; } const data: LoginData = { socialCode: code, socialState: state, tenantId: tenantId, source: source, clientId: 'e5cd7e4891bf95d1d19206ce24a7b32e', clientId: import.meta.env.VITE_APP_CLIENT_ID, grantType: 'social' }; src/store/modules/user.ts
@@ -10,6 +10,7 @@ const name = ref(''); const nickname = ref(''); const userId = ref<string | number>(''); const tenantId = ref<string>(''); const avatar = ref(''); const roles = ref<Array<string>>([]); // 用户角色编码集合 → 判断路由权限 const permissions = ref<Array<string>>([]); // 用户权限编码集合 → 判断按钮权限 @@ -49,6 +50,7 @@ nickname.value = user.nickName; avatar.value = profile; userId.value = user.userId; tenantId.value = user.tenantId; return Promise.resolve(); } return Promise.reject(err); @@ -69,6 +71,7 @@ return { userId, tenantId, token, nickname, avatar, src/types/env.d.ts
@@ -11,9 +11,8 @@ VITE_APP_BASE_API: string; VITE_APP_BASE_URL: string; VITE_APP_CONTEXT_PATH: string; VITE_APP_MONITRO_ADMIN: string; VITE_APP_POWERJOB_ADMIN: string; VITE_APP_EASYRETRY_ADMIN: string; VITE_APP_MONITOR_ADMIN: string; VITE_APP_SNAILJOB_ADMIN: string; VITE_APP_ENV: string; VITE_APP_ENCRYPT: string; VITE_APP_RSA_PUBLIC_KEY: string; src/views/index.vue
@@ -33,7 +33,7 @@ * 部署方式 Docker 容器编排 一键部署业务集群<br /> * 国际化 SpringMessage Spring标准国际化方案<br /> </p> <p><b>当前版本:</b> <span>v5.2.0-BETA</span></p> <p><b>当前版本:</b> <span>v5.2.0</span></p> <p> <el-tag type="danger">¥免费开源</el-tag> </p> @@ -77,7 +77,7 @@ * 分布式监控 Prometheus、Grafana 全方位性能监控<br /> * 其余与 Vue 版本一致<br /> </p> <p><b>当前版本:</b> <span>v2.2.0-BETA</span></p> <p><b>当前版本:</b> <span>v2.2.0</span></p> <p> <el-tag type="danger">¥免费开源</el-tag> </p> src/views/login.vue
@@ -186,20 +186,12 @@ } }; //检测租户选择框的变化 watch( () => loginForm.value.tenantId, () => { localStorage.setItem('tenantId', String(loginForm.value.tenantId)); } ); /** * 第三方登录 * @param type */ const doSocialLogin = (type: string) => { authBinding(type).then((res: any) => { authBinding(type, loginForm.value.tenantId).then((res: any) => { if (res.code === HttpStatus.SUCCESS) { // 获取授权地址跳转 window.location.href = res.data; src/views/monitor/admin/index.vue
@@ -5,5 +5,5 @@ </template> <script setup lang="ts"> const url = ref(import.meta.env.VITE_APP_MONITRO_ADMIN); const url = ref(import.meta.env.VITE_APP_MONITOR_ADMIN); </script> src/views/system/user/profile/thirdParty.vue
@@ -58,6 +58,7 @@ <script lang="ts" setup> import { authUnlock, authBinding } from '@/api/system/social/auth'; import { propTypes } from '@/utils/propTypes'; import useUserStore from "@/store/modules/user"; const { proxy } = getCurrentInstance() as ComponentInternalInstance; @@ -83,7 +84,7 @@ }; const authUrl = (source: string) => { authBinding(source).then((res: any) => { authBinding(source, useUserStore().tenantId).then((res: any) => { if (res.code === 200) { window.location.href = res.data; } else { src/views/workflow/leave/leaveEdit.vue
@@ -3,34 +3,10 @@ <el-card shadow="never"> <div style="display: flex; justify-content: space-between"> <div> <el-button v-if=" routeParams.type === 'add' || (routeParams.type === 'update' && form.status && (form.status === 'draft' || form.status === 'cancel' || form.status === 'back')) " :loading="buttonLoading" type="info" @click="submitForm('draft')" >暂存</el-button > <el-button v-if=" routeParams.type === 'add' || (routeParams.type === 'update' && form.status && (form.status === 'draft' || form.status === 'cancel' || form.status === 'back')) " :loading="buttonLoading" type="primary" @click="submitForm('submit')" >提 交</el-button > <el-button v-if="routeParams.type === 'approval' && form.status && form.status === 'waiting'" :loading="buttonLoading" type="primary" @click="approvalVerifyOpen" >审批</el-button > <el-button v-if="form.status !== 'draft'" type="primary" @click="handleApprovalRecord">流程进度</el-button> <el-button v-if="submitButtonShow" :loading="buttonLoading" type="info" @click="submitForm('draft')">暂存</el-button> <el-button v-if="submitButtonShow" :loading="buttonLoading" type="primary" @click="submitForm('submit')">提 交</el-button> <el-button v-if="approvalButtonShow" :loading="buttonLoading" type="primary" @click="approvalVerifyOpen">审批</el-button> <el-button v-if="form && form.id && form.status !== 'draft'" type="primary" @click="handleApprovalRecord">流程进度</el-button> </div> <div> <el-button style="float: right" @click="goBack()">返回</el-button> @@ -154,7 +130,7 @@ const startDate = new Date(leaveTime.value[0]).getTime(); const endDate = new Date(leaveTime.value[1]).getTime(); const diffInMilliseconds = endDate - startDate; form.value.leaveDays = Math.floor(diffInMilliseconds / (1000 * 60 * 60 * 24)); form.value.leaveDays = Math.floor(diffInMilliseconds / (1000 * 60 * 60 * 24)) + 1; }; /** 获取详情 */ const getInfo = () => { @@ -246,6 +222,21 @@ const approvalVerifyOpen = async () => { submitVerifyRef.value.openDialog(routeParams.value.taskId); }; //校验提交按钮是否显示 const submitButtonShow = computed(() => { return ( routeParams.value.type === 'add' || (routeParams.value.type === 'update' && form.value.status && (form.value.status === 'draft' || form.value.status === 'cancel' || form.value.status === 'back')) ); }); //校验审批按钮是否显示 const approvalButtonShow = computed(() => { return routeParams.value.type === 'approval' && form.value.status && form.value.status === 'waiting'; }); onMounted(() => { nextTick(async () => { routeParams.value = proxy.$route.query; tsconfig.json
@@ -19,9 +19,6 @@ "paths": { "@/*": ["src/*"] }, "compilerOptions": { "types": ["element-plus/global"] }, "types": ["vite/client"], "skipLibCheck": true, "removeComments": true,