This commit is contained in:
123 2025-06-01 20:29:32 +08:00
commit 2aad354c3f
84 changed files with 996 additions and 569 deletions

View File

@ -315,6 +315,9 @@
"watchThrottled": true, "watchThrottled": true,
"watchTriggerable": true, "watchTriggerable": true,
"watchWithFilter": true, "watchWithFilter": true,
"whenever": true "whenever": true,
"Slot": true,
"Slots": true,
"createRef": true
} }
} }

View File

@ -2,16 +2,23 @@
- 本仓库为前端技术栈 [Vue3](https://v3.cn.vuejs.org) + [TS](https://www.typescriptlang.org/) + [Element Plus](https://element-plus.org/zh-CN) + [Vite](https://cn.vitejs.dev) 版本。 - 本仓库为前端技术栈 [Vue3](https://v3.cn.vuejs.org) + [TS](https://www.typescriptlang.org/) + [Element Plus](https://element-plus.org/zh-CN) + [Vite](https://cn.vitejs.dev) 版本。
- 成员项目: 基于 vben5(ant-design-vue) 的前端项目 [ruoyi-plus-vben5](https://gitee.com/dapppp/ruoyi-plus-vben5) - 成员项目: 基于 vben5(ant-design-vue) 的前端项目 [ruoyi-plus-vben5](https://gitee.com/dapppp/ruoyi-plus-vben5)
- 配套后端代码仓库地址 - 成员项目: 基于soybean 的前端项目 [ruoyi-plus-soybean](https://gitee.com/xlsea/ruoyi-plus-soybean)
- [RuoYi-Vue-Plus 5.X(注意版本号)](https://gitee.com/dromara/RuoYi-Vue-Plus)
- [RuoYi-Cloud-Plus 2.X(注意版本号)](https://gitee.com/dromara/RuoYi-Cloud-Plus) ## 配套后端代码仓库地址
| 介绍 | 项目名 | 项目地址 |
|------------|:-----------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 🔥 分布式集群框架 | RuoYi-Vue-Plus | - [Gitee](https://gitee.com/dromara/RuoYi-Vue-Plus)<br> - [GitHub](https://github.com/dromara/RuoYi-Vue-Plus)<br> - [GitCode](https://gitcode.com/dromara/RuoYi-Vue-Plus) |
| 🔥 微服务框架 | RuoYi-Cloud-Plus | - [Gitee](https://gitee.com/dromara/RuoYi-Cloud-Plus)<br>- [GitHub](https://github.com/dromara/RuoYi-Cloud-Plus)<br> - [GitCode](https://gitcode.com/dromara/RuoYi-Cloud-Plus) |
## 分支说明
- ts分支(稳定发布主分支 生产可用)
- dev分支(开发分支 开发过程中使用)
## 前端运行 ## 前端运行
```bash ```bash
# 克隆项目
git clone https://gitee.com/JavaLionLi/plus-ui.git
# 安装依赖 # 安装依赖
npm install --registry=https://registry.npmmirror.com npm install --registry=https://registry.npmmirror.com

View File

@ -1,7 +1,7 @@
{ {
"$schema": "https://json.schemastore.org/package", "$schema": "https://json.schemastore.org/package",
"name": "lx-vue-plus", "name": "ruoyi-vue-plus",
"version": "5.3.1-2.3.0", "version": "5.4.0-2.4.0",
"description": "龙翔管理系统", "description": "龙翔管理系统",
"author": "LionLi", "author": "LionLi",
"license": "MIT", "license": "MIT",
@ -23,31 +23,31 @@
"@element-plus/icons-vue": "2.3.1", "@element-plus/icons-vue": "2.3.1",
"@highlightjs/vue-plugin": "2.1.0", "@highlightjs/vue-plugin": "2.1.0",
"@vueup/vue-quill": "1.2.0", "@vueup/vue-quill": "1.2.0",
"@vueuse/core": "12.7.0", "@vueuse/core": "13.1.0",
"animate.css": "4.1.1", "animate.css": "4.1.1",
"await-to-js": "3.0.0", "await-to-js": "3.0.0",
"axios": "1.7.8", "axios": "1.8.4",
"crypto-js": "4.2.0", "crypto-js": "4.2.0",
"echarts": "5.5.0", "echarts": "5.6.0",
"element-plus": "2.8.8", "element-plus": "2.9.8",
"file-saver": "2.0.5", "file-saver": "2.0.5",
"highlight.js": "11.9.0", "highlight.js": "11.9.0",
"image-conversion": "2.1.1", "image-conversion": "2.1.1",
"js-cookie": "3.0.5", "js-cookie": "3.0.5",
"jsencrypt": "3.3.2", "jsencrypt": "3.3.2",
"nprogress": "0.2.0", "nprogress": "0.2.0",
"pinia": "2.2.6", "pinia": "3.0.2",
"screenfull": "6.0.2", "screenfull": "6.0.2",
"vue": "3.5.13", "vue": "3.5.13",
"vue-cropper": "1.1.1", "vue-cropper": "1.1.1",
"vue-i18n": "10.0.5", "vue-i18n": "11.1.3",
"vue-json-pretty": "2.4.0", "vue-json-pretty": "2.4.0",
"vue-router": "4.4.5", "vue-router": "4.5.0",
"vue-types": "5.1.3", "vue-types": "6.0.0",
"vxe-table": "4.5.22" "vxe-table": "4.13.7"
}, },
"devDependencies": { "devDependencies": {
"@iconify/json": "2.2.276", "@iconify/json": "^2.2.276",
"@types/crypto-js": "4.2.2", "@types/crypto-js": "4.2.2",
"@types/file-saver": "2.0.7", "@types/file-saver": "2.0.7",
"@types/js-cookie": "3.0.6", "@types/js-cookie": "3.0.6",
@ -56,8 +56,8 @@
"@unocss/preset-attributify": "66.0.0", "@unocss/preset-attributify": "66.0.0",
"@unocss/preset-icons": "66.0.0", "@unocss/preset-icons": "66.0.0",
"@unocss/preset-uno": "66.0.0", "@unocss/preset-uno": "66.0.0",
"@vitejs/plugin-vue": "5.2.1", "@vitejs/plugin-vue": "5.2.3",
"@vue/compiler-sfc": "3.4.23", "@vue/compiler-sfc": "3.5.13",
"@vue/eslint-config-prettier": "10.2.0", "@vue/eslint-config-prettier": "10.2.0",
"@vue/eslint-config-typescript": "14.4.0", "@vue/eslint-config-typescript": "14.4.0",
"autoprefixer": "10.4.20", "autoprefixer": "10.4.20",
@ -66,19 +66,22 @@
"eslint-plugin-vue": "9.32.0", "eslint-plugin-vue": "9.32.0",
"globals": "16.0.0", "globals": "16.0.0",
"prettier": "3.5.2", "prettier": "3.5.2",
"sass": "1.84.0", "sass": "1.87.0",
"typescript": "~5.7.3", "typescript": "~5.8.3",
"unocss": "66.0.0", "unocss": "66.0.0",
"unplugin-auto-import": "0.17.5", "unplugin-auto-import": "19.1.2",
"unplugin-icons": "0.18.5", "unplugin-icons": "22.1.0",
"unplugin-vue-components": "28.0.0", "unplugin-vue-components": "28.5.0",
"unplugin-vue-setup-extend-plus": "1.0.1", "unplugin-vue-setup-extend-plus": "1.0.1",
"vite": "5.4.11", "vite": "6.3.2",
"vite-plugin-compression": "0.5.1", "vite-plugin-compression": "0.5.1",
"vite-plugin-svg-icons-ng": "^1.2.2", "vite-plugin-svg-icons-ng": "^1.4.0",
"vite-plugin-vue-devtools": "7.7.1", "vite-plugin-vue-devtools": "7.7.5",
"vitest": "3.0.5", "vitest": "3.1.2",
"vue-tsc": "^2.2.2" "vue-tsc": "^2.2.8"
},
"overrides": {
"quill": "2.0.2"
}, },
"engines": { "engines": {
"node": ">=18.18.0", "node": ">=18.18.0",

View File

@ -0,0 +1,240 @@
import { DeptTreeVO, DeptVO } from './../dept/types';
import { RoleVO } from '@/api/system/role/types';
import request from '@/utils/request';
import { AxiosPromise } from 'axios';
import { UserForm, UserQuery, UserVO, UserInfoVO } from './types';
import { parseStrEmpty } from '@/utils/ruoyi';
/**
*
* @param query
*/
export const listUser = (query: UserQuery): AxiosPromise<UserVO[]> => {
return request({
url: '/operate/user/list',
method: 'get',
params: query
});
};
/**
* ids查询用户
* @param userIds
*/
export const optionSelect = (userIds: (number | string)[]): AxiosPromise<UserVO[]> => {
return request({
url: '/operate/user/optionselect?userIds=' + userIds,
method: 'get'
});
};
/**
*
* @param userId
*/
export const getUser = (userId?: string | number): AxiosPromise<UserInfoVO> => {
return request({
url: '/operate/user/' + parseStrEmpty(userId),
method: 'get'
});
};
/**
*
*/
export const addUser = (data: UserForm) => {
return request({
url: '/operate/user',
method: 'post',
data: data
});
};
/**
*
*/
export const updateUser = (data: UserForm) => {
return request({
url: '/operate/user',
method: 'put',
data: data
});
};
/**
*
* @param userId ID
*/
export const delUser = (userId: Array<string | number> | string | number) => {
return request({
url: '/operate/user/' + userId,
method: 'delete'
});
};
/**
*
* @param userId ID
* @param password
*/
export const resetUserPwd = (userId: string | number, password: string) => {
const data = {
userId,
password
};
return request({
url: '/operate/user/resetPwd',
method: 'put',
headers: {
isEncrypt: true,
repeatSubmit: false
},
data: data
});
};
/**
*
* @param userId ID
* @param status
*/
export const changeUserStatus = (userId: number | string, status: string) => {
const data = {
userId,
status
};
return request({
url: '/operate/user/changeStatus',
method: 'put',
data: data
});
};
/**
*
*/
export const getUserProfile = (): AxiosPromise<UserInfoVO> => {
return request({
url: '/operate/user/profile',
method: 'get'
});
};
/**
*
* @param data
*/
export const updateUserProfile = (data: UserForm) => {
return request({
url: '/operate/user/profile',
method: 'put',
data: data
});
};
/**
*
* @param oldPassword
* @param newPassword
*/
export const updateUserPwd = (oldPassword: string, newPassword: string) => {
const data = {
oldPassword,
newPassword
};
return request({
url: '/operate/user/profile/updatePwd',
method: 'put',
headers: {
isEncrypt: true,
repeatSubmit: false
},
data: data
});
};
/**
*
* @param data
*/
export const uploadAvatar = (data: FormData) => {
return request({
url: '/operate/user/profile/avatar',
method: 'post',
data: data
});
};
/**
*
* @param userId ID
*/
export const getAuthRole = (userId: string | number): AxiosPromise<{ user: UserVO; roles: RoleVO[] }> => {
return request({
url: '/operate/user/authRole/' + userId,
method: 'get'
});
};
/**
*
* @param data ID
*/
export const updateAuthRole = (data: { userId: string; roleIds: string }) => {
return request({
url: '/operate/user/authRole',
method: 'put',
params: data
});
};
/**
*
* @param deptId
*/
export const listUserByDeptId = (deptId: string | number): AxiosPromise<UserVO[]> => {
return request({
url: '/operate/user/list/dept/' + deptId,
method: 'get'
});
};
/**
*
*/
export const deptTreeSelect = (): AxiosPromise<DeptTreeVO[]> => {
return request({
url: '/operate/user/deptTree',
method: 'get'
});
};
/**
*
*/
export const setDeptAdmin = (userId: Array<string | number> | string | number) => {
return request({
url: '/operate/user/setDeptAdmin/' + userId,
method: 'get'
});
};
export default {
listUser,
getUser,
optionSelect,
addUser,
updateUser,
delUser,
resetUserPwd,
changeUserStatus,
getUserProfile,
updateUserProfile,
updateUserPwd,
uploadAvatar,
getAuthRole,
updateAuthRole,
deptTreeSelect,
listUserByDeptId,
setDeptAdmin
};

View File

@ -0,0 +1,90 @@
import { RoleVO } from '@/api/system/role/types';
import { PostVO } from '@/api/system/post/types';
/**
*
*/
export interface UserInfo {
user: UserVO;
roles: string[];
permissions: string[];
}
/**
*
*/
export interface UserQuery extends PageQuery {
userName?: string;
nickName?: string;
phonenumber?: string;
status?: string;
deptId?: string | number;
roleId?: string | number;
userIds?: string;
employeeName?: string;
}
/**
*
*/
export interface UserVO extends BaseEntity {
userId: string | number;
tenantId: string;
deptId: number;
userName: string;
nickName: string;
userType: string;
email: string;
phonenumber: string;
sex: string;
avatar: string;
status: string;
delFlag: string;
loginIp: string;
loginDate: string;
remark: string;
deptName: string;
roles: RoleVO[];
roleIds: any;
postIds: any;
roleId: any;
admin: boolean;
employeeName: string;
}
/**
*
*/
export interface UserForm {
id?: string;
userId?: string;
deptId?: number;
userName: string;
employeeName?: string;
nickName?: string;
password: string;
phonenumber?: string;
email?: string;
sex?: string;
status: string;
remark?: string;
postIds: string[];
roleIds: string[];
}
export interface UserInfoVO {
user: UserVO;
roles: RoleVO[];
roleIds: string[];
posts: PostVO[];
postIds: string[];
roleGroup: string;
postGroup: string;
}
export interface ResetPwdForm {
oldPassword: string;
newPassword: string;
confirmPassword: string;
}

View File

@ -1,6 +1,6 @@
import request from '@/utils/request'; import request from '@/utils/request';
import { AxiosPromise } from 'axios'; import { AxiosPromise } from 'axios';
import {DeptForm, DeptQuery, DeptTreeVO, DeptVO} from './types'; import { DeptForm, DeptQuery, DeptTreeVO, DeptVO } from './types';
// 查询部门列表 // 查询部门列表
export const listDept = (query?: DeptQuery) => { export const listDept = (query?: DeptQuery) => {

View File

@ -68,3 +68,11 @@ export const delMenu = (menuId: string | number) => {
method: 'delete' method: 'delete'
}); });
}; };
// 级联删除菜单
export const cascadeDelMenu = (menuIds: Array<string | number>) => {
return request({
url: '/system/menu/cascade/' + menuIds,
method: 'delete'
});
};

View File

@ -1,4 +1,4 @@
import {DeptTreeVO, DeptVO} from './../dept/types'; import { DeptTreeVO, DeptVO } from './../dept/types';
import { RoleVO } from '@/api/system/role/types'; import { RoleVO } from '@/api/system/role/types';
import request from '@/utils/request'; import request from '@/utils/request';
import { AxiosPromise } from 'axios'; import { AxiosPromise } from 'axios';

View File

@ -1,6 +1,5 @@
import { RoleVO } from '@/api/system/role/types'; import { RoleVO } from '@/api/system/role/types';
import { PostVO } from '@/api/system/post/types'; import { PostVO } from '@/api/system/post/types';
import { string } from 'vue-types';
/** /**
* *
@ -16,6 +15,7 @@ export interface UserInfo {
*/ */
export interface UserQuery extends PageQuery { export interface UserQuery extends PageQuery {
userName?: string; userName?: string;
nickName?: string;
phonenumber?: string; phonenumber?: string;
status?: string; status?: string;
deptId?: string | number; deptId?: string | number;
@ -61,6 +61,7 @@ export interface UserForm {
deptId?: number; deptId?: number;
userName: string; userName: string;
employeeName?: string; employeeName?: string;
nickName?: string;
password: string; password: string;
phonenumber?: string; phonenumber?: string;
email?: string; email?: string;

View File

@ -31,9 +31,9 @@ export const pageByFinish = (query: FlowInstanceQuery): AxiosPromise<FlowInstanc
/** /**
* id获取历史流程图 * id获取历史流程图
*/ */
export const flowImage = (businessId: string | number) => { export const flowHisTaskList = (businessId: string | number) => {
return request({ return request({
url: `/workflow/instance/flowImage/${businessId}` + '?t' + Math.random(), url: `/workflow/instance/flowHisTaskList/${businessId}` + '?t' + Math.random(),
method: 'get' method: 'get'
}); });
}; };

View File

@ -26,7 +26,7 @@
z-index: 1001; z-index: 1001;
overflow: hidden; overflow: hidden;
-webkit-box-shadow: 2px 0 6px rgba(0, 21, 41, 0.35); -webkit-box-shadow: 2px 0 6px rgba(0, 21, 41, 0.35);
box-shadow: 2px 0 6px rgba(0, 21, 41, 0.35); box-shadow: 0 0 8px 0 rgba(0, 0, 0, 0.1);
// reset element-ui css // reset element-ui css
.horizontal-collapse-transition { .horizontal-collapse-transition {

View File

@ -44,7 +44,7 @@ const findPathNum = (str, char = '/') => {
return str.split(char).length - 1; return str.split(char).length - 1;
}; };
const getMatched = (pathList, routeList, matched) => { const getMatched = (pathList, routeList, matched) => {
let data = routeList.find((item) => item.path == pathList[0] || (item.name += '').toLowerCase() == pathList[0]); const data = routeList.find((item) => item.path == pathList[0] || (item.name += '').toLowerCase() == pathList[0]);
if (data) { if (data) {
matched.push(data); matched.push(data);
if (data.children && pathList.length) { if (data.children && pathList.length) {

View File

@ -95,7 +95,7 @@ const options = ref<any>({
}); });
const styles = computed(() => { const styles = computed(() => {
let style: any = {}; const style: any = {};
if (props.minHeight) { if (props.minHeight) {
style.minHeight = `${props.minHeight}px`; style.minHeight = `${props.minHeight}px`;
} }
@ -121,9 +121,9 @@ const handleUploadSuccess = (res: any) => {
// //
if (res.code === 200) { if (res.code === 200) {
// //
let quill = toRaw(quillEditorRef.value).getQuill(); const quill = toRaw(quillEditorRef.value).getQuill();
// //
let length = quill.selection.savedRange.index; const length = quill.selection.savedRange.index;
// res // res
quill.insertEmbed(length, 'image', res.data.url); quill.insertEmbed(length, 'image', res.data.url);
// //

View File

@ -176,7 +176,7 @@ const handleUploadSuccess = (res: any, file: UploadFile) => {
// //
const handleDelete = (index: number) => { const handleDelete = (index: number) => {
let ossId = fileList.value[index].ossId; const ossId = fileList.value[index].ossId;
delOss(ossId); delOss(ossId);
fileList.value.splice(index, 1); fileList.value.splice(index, 1);
emit('update:modelValue', listToString(fileList.value)); emit('update:modelValue', listToString(fileList.value));

View File

@ -27,7 +27,7 @@ const realSrc = computed(() => {
if (!props.src) { if (!props.src) {
return; return;
} }
let real_src = props.src.split(',')[0]; const real_src = props.src.split(',')[0];
return real_src; return real_src;
}); });
@ -35,8 +35,8 @@ const realSrcList = computed(() => {
if (!props.src) { if (!props.src) {
return []; return [];
} }
let real_src_list = props.src.split(','); const real_src_list = props.src.split(',');
let srcList: string[] = []; const srcList: string[] = [];
real_src_list.forEach((item: string) => { real_src_list.forEach((item: string) => {
if (item.trim() === '') { if (item.trim() === '') {
return; return;

View File

@ -189,7 +189,7 @@ const handleUploadSuccess = (res: any, file: UploadFile) => {
const handleDelete = (file: UploadFile): boolean => { const handleDelete = (file: UploadFile): boolean => {
const findex = fileList.value.map((f) => f.name).indexOf(file.name); const findex = fileList.value.map((f) => f.name).indexOf(file.name);
if (findex > -1 && uploadList.value.length === number.value) { if (findex > -1 && uploadList.value.length === number.value) {
let ossId = fileList.value[findex].ossId; const ossId = fileList.value[findex].ossId;
delOss(ossId); delOss(ossId);
fileList.value.splice(findex, 1); fileList.value.splice(findex, 1);
emit('update:modelValue', listToString(fileList.value)); emit('update:modelValue', listToString(fileList.value));
@ -225,7 +225,7 @@ const handlePictureCardPreview = (file: any) => {
const listToString = (list: any[], separator?: string) => { const listToString = (list: any[], separator?: string) => {
let strs = ''; let strs = '';
separator = separator || ','; separator = separator || ',';
for (let i in list) { for (const i in list) {
if (undefined !== list[i].ossId && list[i].url.indexOf('blob:') !== 0) { if (undefined !== list[i].ossId && list[i].url.indexOf('blob:') !== 0) {
strs += list[i].ossId + separator; strs += list[i].ossId + separator;
} }

View File

@ -0,0 +1,56 @@
<template>
<div style="display: flex; justify-content: space-between">
<div>
<el-button v-if="submitButtonShow" :loading="props.buttonLoading" type="info" @click="submitForm('draft')">暂存</el-button>
<el-button v-if="submitButtonShow" :loading="props.buttonLoading" type="primary" @click="submitForm('submit')"> </el-button>
<el-button v-if="approvalButtonShow" :loading="props.buttonLoading" type="primary" @click="approvalVerifyOpen">审批</el-button>
<el-button v-if="props.id && props.status !== 'draft'" type="primary" @click="handleApprovalRecord">流程进度</el-button>
<slot />
</div>
<div>
<el-button style="float: right" @click="goBack()">返回</el-button>
</div>
</div>
</template>
<script setup lang="ts">
import { propTypes } from '@/utils/propTypes';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const props = defineProps({
status: propTypes.string.def(''),
pageType: propTypes.string.def(''),
buttonLoading: propTypes.bool.def(false),
id: propTypes.string.def('') || propTypes.number.def()
});
const emits = defineEmits(['submitForm', 'approvalVerifyOpen', 'handleApprovalRecord']);
//
const submitForm = async (type) => {
emits('submitForm', type);
};
//
const approvalVerifyOpen = async () => {
emits('approvalVerifyOpen');
};
//
const handleApprovalRecord = () => {
emits('handleApprovalRecord');
};
//
const submitButtonShow = computed(() => {
return (
props.pageType === 'add' ||
(props.pageType === 'update' && props.status && (props.status === 'draft' || props.status === 'cancel' || props.status === 'back'))
);
});
//
const approvalButtonShow = computed(() => {
return props.pageType === 'approval' && props.status && props.status === 'waiting';
});
//
const goBack = () => {
proxy.$tab.closePage(proxy.$route);
proxy.$router.go(-1);
};
</script>

View File

@ -3,21 +3,7 @@
<el-dialog v-model="visible" draggable title="审批记录" :width="props.width" :height="props.height" :close-on-click-modal="false"> <el-dialog v-model="visible" draggable title="审批记录" :width="props.width" :height="props.height" :close-on-click-modal="false">
<el-tabs v-model="tabActiveName" class="demo-tabs"> <el-tabs v-model="tabActiveName" class="demo-tabs">
<el-tab-pane v-loading="loading" label="流程图" name="image" style="height: 68vh"> <el-tab-pane v-loading="loading" label="流程图" name="image" style="height: 68vh">
<div <flowChart :ins-id="insId" v-if="insId" />
ref="imageWrapperRef"
class="image-wrapper"
@wheel="handleMouseWheel"
@mousedown="handleMouseDown"
@mousemove="handleMouseMove"
@mouseup="handleMouseUp"
@mouseleave="handleMouseLeave"
@dblclick="resetTransform"
:style="transformStyle"
>
<el-card class="box-card">
<el-image :src="imgUrl" class="scalable-image" />
</el-card>
</div>
</el-tab-pane> </el-tab-pane>
<el-tab-pane v-loading="loading" label="审批信息" name="info"> <el-tab-pane v-loading="loading" label="审批信息" name="info">
<div> <div>
@ -73,10 +59,10 @@
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { flowImage } from '@/api/workflow/instance'; import { flowHisTaskList } from '@/api/workflow/instance';
import { propTypes } from '@/utils/propTypes'; import { propTypes } from '@/utils/propTypes';
import { listByIds } from '@/api/system/oss'; import { listByIds } from '@/api/system/oss';
import FlowChart from '@/components/Process/flowChart.vue';
const { proxy } = getCurrentInstance() as ComponentInternalInstance; const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const { wf_task_status } = toRefs<any>(proxy?.useDict('wf_task_status')); const { wf_task_status } = toRefs<any>(proxy?.useDict('wf_task_status'));
const props = defineProps({ const props = defineProps({
@ -87,7 +73,7 @@ const loading = ref(false);
const visible = ref(false); const visible = ref(false);
const historyList = ref<Array<any>>([]); const historyList = ref<Array<any>>([]);
const tabActiveName = ref('image'); const tabActiveName = ref('image');
const imgUrl = ref(''); const insId = ref(null);
// //
const init = async (businessId: string | number) => { const init = async (businessId: string | number) => {
@ -95,10 +81,10 @@ const init = async (businessId: string | number) => {
loading.value = true; loading.value = true;
tabActiveName.value = 'image'; tabActiveName.value = 'image';
historyList.value = []; historyList.value = [];
flowImage(businessId).then((resp) => { flowHisTaskList(businessId).then((resp) => {
if (resp.data) { if (resp.data) {
historyList.value = resp.data.list; historyList.value = resp.data.list;
imgUrl.value = 'data:image/gif;base64,' + resp.data.image; insId.value = resp.data.instanceId;
if (historyList.value.length > 0) { if (historyList.value.length > 0) {
historyList.value.forEach((item) => { historyList.value.forEach((item) => {
if (item.ext) { if (item.ext) {
@ -124,109 +110,6 @@ const handleDownload = (ossId: string) => {
proxy?.$download.oss(ossId); proxy?.$download.oss(ossId);
}; };
const imageWrapperRef = ref<HTMLElement | null>(null);
const scale = ref(1); //
const maxScale = 3; //
const minScale = 0.5; //
let isDragging = false;
let startX = 0;
let startY = 0;
let currentTranslateX = 0;
let currentTranslateY = 0;
const handleMouseWheel = (event: WheelEvent) => {
event.preventDefault();
let newScale = scale.value - event.deltaY / 1000;
newScale = Math.max(minScale, Math.min(newScale, maxScale));
if (newScale !== scale.value) {
scale.value = newScale;
resetDragPosition(); // 使
}
};
const handleMouseDown = (event: MouseEvent) => {
if (scale.value > 1) {
event.preventDefault(); //
isDragging = true;
startX = event.clientX;
startY = event.clientY;
}
};
const handleMouseMove = (event: MouseEvent) => {
if (!isDragging || !imageWrapperRef.value) return;
const deltaX = event.clientX - startX;
const deltaY = event.clientY - startY;
startX = event.clientX;
startY = event.clientY;
currentTranslateX += deltaX;
currentTranslateY += deltaY;
//
const bounds = getBounds();
if (currentTranslateX > bounds.maxTranslateX) {
currentTranslateX = bounds.maxTranslateX;
} else if (currentTranslateX < bounds.minTranslateX) {
currentTranslateX = bounds.minTranslateX;
}
if (currentTranslateY > bounds.maxTranslateY) {
currentTranslateY = bounds.maxTranslateY;
} else if (currentTranslateY < bounds.minTranslateY) {
currentTranslateY = bounds.minTranslateY;
}
applyTransform();
};
const handleMouseUp = () => {
isDragging = false;
};
const handleMouseLeave = () => {
isDragging = false;
};
const resetTransform = () => {
scale.value = 1;
currentTranslateX = 0;
currentTranslateY = 0;
applyTransform();
};
const resetDragPosition = () => {
currentTranslateX = 0;
currentTranslateY = 0;
applyTransform();
};
const applyTransform = () => {
if (imageWrapperRef.value) {
imageWrapperRef.value.style.transform = `translate(${currentTranslateX}px, ${currentTranslateY}px) scale(${scale.value})`;
}
};
const getBounds = () => {
if (!imageWrapperRef.value) return { minTranslateX: 0, maxTranslateX: 0, minTranslateY: 0, maxTranslateY: 0 };
const imgRect = imageWrapperRef.value.getBoundingClientRect();
const containerRect = imageWrapperRef.value.parentElement?.getBoundingClientRect() ?? imgRect;
const minTranslateX = (containerRect.width - imgRect.width * scale.value) / 2;
const maxTranslateX = -(containerRect.width - imgRect.width * scale.value) / 2;
const minTranslateY = (containerRect.height - imgRect.height * scale.value) / 2;
const maxTranslateY = -(containerRect.height - imgRect.height * scale.value) / 2;
return { minTranslateX, maxTranslateX, minTranslateY, maxTranslateY };
};
const transformStyle = computed(() => ({
transition: isDragging ? 'none' : 'transform 0.2s ease'
}));
/** /**
* 对外暴露子组件方法 * 对外暴露子组件方法
*/ */
@ -235,46 +118,10 @@ defineExpose({
}); });
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.triangle {
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3);
border-radius: 6px;
}
.triangle::after {
content: ' ';
position: absolute;
top: 8em;
right: 215px;
border: 15px solid;
border-color: transparent #fff transparent transparent;
}
.container { .container {
:deep(.el-dialog .el-dialog__body) { :deep(.el-dialog .el-dialog__body) {
max-height: calc(100vh - 170px) !important; max-height: calc(100vh - 170px) !important;
min-height: calc(100vh - 170px) !important; min-height: calc(100vh - 170px) !important;
} }
} }
.image-wrapper {
width: 100%;
overflow: hidden;
position: relative;
margin: 0 auto;
display: flex;
justify-content: center;
align-items: center;
user-select: none; /* 禁用文本选择 */
cursor: grab; /* 设置初始鼠标指针为可拖动 */
}
.image-wrapper:active {
cursor: grabbing; /* 当正在拖动时改变鼠标指针 */
}
.scalable-image {
object-fit: contain;
width: 100%;
padding: 15px;
}
</style> </style>

View File

@ -0,0 +1,40 @@
<template>
<div>
<div style="height: 68vh" class="iframe-wrapper">
<iframe :src="iframeUrl" style="width: 100%; height: 100%" frameborder="0" scrolling="no" class="custom-iframe" />
</div>
</div>
</template>
<script setup lang="ts">
import { getToken } from '@/utils/auth';
// Props
const props = defineProps({
insId: {
type: [String, Number],
default: null
}
});
const iframeUrl = ref('');
const baseUrl = import.meta.env.VITE_APP_BASE_API;
onMounted(async () => {
const url = baseUrl + `/warm-flow-ui/index.html?id=${props.insId}&type=FlowChart`;
iframeUrl.value = url + '&Authorization=Bearer ' + getToken() + '&clientid=' + import.meta.env.VITE_APP_CLIENT_ID;
});
</script>
<style scoped>
.iframe-wrapper {
border-radius: 12px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
overflow: hidden;
}
.custom-iframe {
width: 100%;
border: none;
background: transparent;
}
</style>

View File

@ -0,0 +1,154 @@
<template>
<div
ref="imageWrapperRef"
class="image-wrapper"
@wheel="handleMouseWheel"
@mousedown="handleMouseDown"
@mousemove="handleMouseMove"
@mouseup="handleMouseUp"
@mouseleave="handleMouseLeave"
@dblclick="resetTransform"
:style="transformStyle"
>
<el-card class="box-card">
<el-image :src="props.imgUrl" class="scalable-image" />
</el-card>
</div>
</template>
<script setup lang="ts">
// Props
const props = defineProps({
imgUrl: {
type: String,
default: () => ''
}
});
const imageWrapperRef = ref<HTMLElement | null>(null);
const scale = ref(1); //
const maxScale = 3; //
const minScale = 0.5; //
let isDragging = false;
let startX = 0;
let startY = 0;
let currentTranslateX = 0;
let currentTranslateY = 0;
const handleMouseWheel = (event: WheelEvent) => {
event.preventDefault();
let newScale = scale.value - event.deltaY / 1000;
newScale = Math.max(minScale, Math.min(newScale, maxScale));
if (newScale !== scale.value) {
scale.value = newScale;
resetDragPosition(); // 使
}
};
const handleMouseDown = (event: MouseEvent) => {
if (scale.value > 1) {
event.preventDefault(); //
isDragging = true;
startX = event.clientX;
startY = event.clientY;
}
};
const handleMouseMove = (event: MouseEvent) => {
if (!isDragging || !imageWrapperRef.value) return;
const deltaX = event.clientX - startX;
const deltaY = event.clientY - startY;
startX = event.clientX;
startY = event.clientY;
currentTranslateX += deltaX;
currentTranslateY += deltaY;
//
const bounds = getBounds();
if (currentTranslateX > bounds.maxTranslateX) {
currentTranslateX = bounds.maxTranslateX;
} else if (currentTranslateX < bounds.minTranslateX) {
currentTranslateX = bounds.minTranslateX;
}
if (currentTranslateY > bounds.maxTranslateY) {
currentTranslateY = bounds.maxTranslateY;
} else if (currentTranslateY < bounds.minTranslateY) {
currentTranslateY = bounds.minTranslateY;
}
applyTransform();
};
const handleMouseUp = () => {
isDragging = false;
};
const handleMouseLeave = () => {
isDragging = false;
};
const resetTransform = () => {
scale.value = 1;
currentTranslateX = 0;
currentTranslateY = 0;
applyTransform();
};
const resetDragPosition = () => {
currentTranslateX = 0;
currentTranslateY = 0;
applyTransform();
};
const applyTransform = () => {
if (imageWrapperRef.value) {
imageWrapperRef.value.style.transform = `translate(${currentTranslateX}px, ${currentTranslateY}px) scale(${scale.value})`;
}
};
const getBounds = () => {
if (!imageWrapperRef.value) return { minTranslateX: 0, maxTranslateX: 0, minTranslateY: 0, maxTranslateY: 0 };
const imgRect = imageWrapperRef.value.getBoundingClientRect();
const containerRect = imageWrapperRef.value.parentElement?.getBoundingClientRect() ?? imgRect;
const minTranslateX = (containerRect.width - imgRect.width * scale.value) / 2;
const maxTranslateX = -(containerRect.width - imgRect.width * scale.value) / 2;
const minTranslateY = (containerRect.height - imgRect.height * scale.value) / 2;
const maxTranslateY = -(containerRect.height - imgRect.height * scale.value) / 2;
return { minTranslateX, maxTranslateX, minTranslateY, maxTranslateY };
};
const transformStyle = computed(() => ({
transition: isDragging ? 'none' : 'transform 0.2s ease'
}));
</script>
<style scoped>
.image-wrapper {
width: 100%;
overflow: hidden;
position: relative;
margin: 0 auto;
display: flex;
justify-content: center;
align-items: center;
user-select: none; /* 禁用文本选择 */
cursor: grab; /* 设置初始鼠标指针为可拖动 */
}
.image-wrapper:active {
cursor: grabbing; /* 当正在拖动时改变鼠标指针 */
}
.scalable-image {
object-fit: contain;
width: 100%;
padding: 15px;
}
</style>

View File

@ -8,10 +8,10 @@
<el-checkbox value="3" name="type">短信</el-checkbox> <el-checkbox value="3" name="type">短信</el-checkbox>
</el-checkbox-group> </el-checkbox-group>
</el-form-item> </el-form-item>
<el-form-item v-if="task.flowStatus === 'waiting'" label="附件"> <el-form-item label="附件">
<fileUpload v-model="form.fileId" :file-type="['png', 'jpg', 'jpeg', 'doc', 'docx', 'xlsx', 'xls', 'ppt', 'txt', 'pdf']" :file-size="20" /> <fileUpload v-model="form.fileId" :file-type="['png', 'jpg', 'jpeg', 'doc', 'docx', 'xlsx', 'xls', 'ppt', 'txt', 'pdf']" :file-size="20" />
</el-form-item> </el-form-item>
<el-form-item label="抄送" v-if="task.flowStatus === 'waiting' && buttonObj.copy"> <el-form-item label="抄送" v-if="buttonObj.copy">
<el-button type="primary" icon="Plus" circle @click="openUserSelectCopy" /> <el-button type="primary" icon="Plus" circle @click="openUserSelectCopy" />
<el-tag v-for="user in selectCopyUserList" :key="user.userId" closable style="margin: 2px" @close="handleCopyCloseTag(user)"> <el-tag v-for="user in selectCopyUserList" :key="user.userId" closable style="margin: 2px" @close="handleCopyCloseTag(user)">
{{ user.employeeName }} {{ user.employeeName }}

View File

@ -47,11 +47,11 @@ const routers = computed(() => permissionStore.getTopbarRoutes());
// //
const topMenus = computed(() => { const topMenus = computed(() => {
let topMenus: RouteRecordRaw[] = []; const topMenus: RouteRecordRaw[] = [];
routers.value.map((menu) => { routers.value.map((menu) => {
if (menu.hidden !== true) { if (menu.hidden !== true) {
// //
if (menu.path === '/') { if (menu.path === '/' && menu.children) {
topMenus.push(menu.children ? menu.children[0] : menu); topMenus.push(menu.children ? menu.children[0] : menu);
} else { } else {
topMenus.push(menu); topMenus.push(menu);
@ -63,7 +63,7 @@ const topMenus = computed(() => {
// //
const childrenMenus = computed(() => { const childrenMenus = computed(() => {
let childrenMenus: RouteRecordRaw[] = []; const childrenMenus: RouteRecordRaw[] = [];
routers.value.map((router) => { routers.value.map((router) => {
router.children?.forEach((item) => { router.children?.forEach((item) => {
if (item.parentPath === undefined) { if (item.parentPath === undefined) {
@ -118,7 +118,7 @@ const handleSelect = (key: string) => {
// //
const routeMenu = childrenMenus.value.find((item) => item.path === key); const routeMenu = childrenMenus.value.find((item) => item.path === key);
if (routeMenu && routeMenu.query) { if (routeMenu && routeMenu.query) {
let query = JSON.parse(routeMenu.query); const query = JSON.parse(routeMenu.query);
router.push({ path: key, query: query }); router.push({ path: key, query: query });
} else { } else {
router.push({ path: key }); router.push({ path: key });
@ -132,7 +132,7 @@ const handleSelect = (key: string) => {
}; };
const activeRoutes = (key: string) => { const activeRoutes = (key: string) => {
let routes: RouteRecordRaw[] = []; const routes: RouteRecordRaw[] = [];
if (childrenMenus.value && childrenMenus.value.length > 0) { if (childrenMenus.value && childrenMenus.value.length > 0) {
childrenMenus.value.map((item) => { childrenMenus.value.map((item) => {
if (key == item.parentPath || (key == 'index' && '' == item.path)) { if (key == item.parentPath || (key == 'index' && '' == item.path)) {

View File

@ -40,16 +40,16 @@ watch(
); );
onMounted(() => { onMounted(() => {
addIframe() addIframe();
}) });
watchEffect((route) => { watchEffect(() => {
addIframe() addIframe();
}) });
function addIframe() { function addIframe() {
if (route.meta.link) { if (route.meta.link) {
useTagsViewStore().addIframeView(route) useTagsViewStore().addIframeView(route);
} }
} }
</script> </script>

View File

@ -18,7 +18,7 @@ const tagsViewStore = useTagsViewStore();
function iframeUrl(url: string | undefined, query: any) { function iframeUrl(url: string | undefined, query: any) {
if (Object.keys(query).length > 0) { if (Object.keys(query).length > 0) {
let params = Object.keys(query) const params = Object.keys(query)
.map((key) => key + '=' + query[key]) .map((key) => key + '=' + query[key])
.join('&'); .join('&');
return url + '?' + params; return url + '?' + params;

View File

@ -33,7 +33,7 @@
<el-popover placement="bottom" trigger="click" transition="el-zoom-in-top" :width="300" :persistent="false"> <el-popover placement="bottom" trigger="click" transition="el-zoom-in-top" :width="300" :persistent="false">
<template #reference> <template #reference>
<el-badge :value="newNotice > 0 ? newNotice : ''" :max="99"> <el-badge :value="newNotice > 0 ? newNotice : ''" :max="99">
<svg-icon icon-class="message" /> <div class="right-menu-item hover-effect" style="display: block"><svg-icon icon-class="message" /></div>
</el-badge> </el-badge>
</template> </template>
<template #default> <template #default>
@ -98,7 +98,7 @@ import { dynamicClear, dynamicTenant } from '@/api/system/tenant';
import { TenantVO } from '@/api/types'; import { TenantVO } from '@/api/types';
import notice from './notice/index.vue'; import notice from './notice/index.vue';
import router from '@/router'; import router from '@/router';
import {ElMessageBoxOptions} from "element-plus/es/components/message-box/src/message-box.type"; import { ElMessageBoxOptions } from 'element-plus/es/components/message-box/src/message-box.type';
const appStore = useAppStore(); const appStore = useAppStore();
const userStore = useUserStore(); const userStore = useUserStore();
@ -171,6 +171,7 @@ const logout = async () => {
redirect: encodeURIComponent(router.currentRoute.value.fullPath || '/') redirect: encodeURIComponent(router.currentRoute.value.fullPath || '/')
} }
}); });
proxy?.$tab.closeAllPage();
}); });
}; };

View File

@ -59,6 +59,13 @@
</span> </span>
</div> </div>
<div class="drawer-item">
<span>显示页签图标</span>
<span class="comp-style">
<el-switch v-model="settingsStore.tagsIcon" :disabled="!settingsStore.tagsView" class="drawer-switch" />
</span>
</div>
<div class="drawer-item"> <div class="drawer-item">
<span>固定 Header</span> <span>固定 Header</span>
<span class="comp-style"> <span class="comp-style">
@ -153,6 +160,7 @@ const saveSetting = () => {
const settings = useStorage<LayoutSetting>('layout-setting', defaultSettings); const settings = useStorage<LayoutSetting>('layout-setting', defaultSettings);
settings.value.topNav = storeSettings.value.topNav; settings.value.topNav = storeSettings.value.topNav;
settings.value.tagsView = storeSettings.value.tagsView; settings.value.tagsView = storeSettings.value.tagsView;
settings.value.tagsIcon = storeSettings.value.tagsIcon;
settings.value.fixedHeader = storeSettings.value.fixedHeader; settings.value.fixedHeader = storeSettings.value.fixedHeader;
settings.value.sidebarLogo = storeSettings.value.sidebarLogo; settings.value.sidebarLogo = storeSettings.value.sidebarLogo;
settings.value.dynamicTitle = storeSettings.value.dynamicTitle; settings.value.dynamicTitle = storeSettings.value.dynamicTitle;

View File

@ -86,7 +86,7 @@ const resolvePath = (routePath: string, routeQuery?: string): any => {
return props.basePath; return props.basePath;
} }
if (routeQuery) { if (routeQuery) {
let query = JSON.parse(routeQuery); const query = JSON.parse(routeQuery);
return { path: getNormalPath(props.basePath + '/' + routePath), query: query }; return { path: getNormalPath(props.basePath + '/' + routePath), query: query };
} }
return getNormalPath(props.basePath + '/' + routePath); return getNormalPath(props.basePath + '/' + routePath);

View File

@ -63,9 +63,9 @@ const loginByCode = async (data: LoginData) => {
const init = async () => { const init = async () => {
// //
let host = window.location.host; const host = window.location.host;
if (domain !== host) { if (domain !== host) {
let urlFull = new URL(window.location.href); const urlFull = new URL(window.location.href);
urlFull.host = domain; urlFull.host = domain;
window.location.href = urlFull.toString(); window.location.href = urlFull.toString();
return; return;

View File

@ -5,13 +5,14 @@
v-for="tag in visitedViews" v-for="tag in visitedViews"
:key="tag.path" :key="tag.path"
:data-path="tag.path" :data-path="tag.path"
:class="isActive(tag) ? 'active' : ''" :class="{ 'active': isActive(tag), 'has-icon': tagsIcon }"
:to="{ path: tag.path ? tag.path : '', query: tag.query, fullPath: tag.fullPath ? tag.fullPath : '' }" :to="{ path: tag.path ? tag.path : '', query: tag.query, fullPath: tag.fullPath ? tag.fullPath : '' }"
class="tags-view-item" class="tags-view-item"
:style="activeStyle(tag)" :style="activeStyle(tag)"
@click.middle="!isAffix(tag) ? closeSelectedTag(tag) : ''" @click.middle="!isAffix(tag) ? closeSelectedTag(tag) : ''"
@contextmenu.prevent="openMenu(tag, $event)" @contextmenu.prevent="openMenu(tag, $event)"
> >
<svg-icon v-if="tagsIcon && tag.meta && tag.meta.icon && tag.meta.icon !== '#'" :icon-class="tag.meta.icon"/>
{{ tag.title }} {{ tag.title }}
<span v-if="!isAffix(tag)" @click.prevent.stop="closeSelectedTag(tag)"> <span v-if="!isAffix(tag)" @click.prevent.stop="closeSelectedTag(tag)">
<close class="el-icon-close" style="width: 1em; height: 1em; vertical-align: middle" /> <close class="el-icon-close" style="width: 1em; height: 1em; vertical-align: middle" />
@ -51,6 +52,7 @@ const router = useRouter();
const visitedViews = computed(() => useTagsViewStore().getVisitedViews()); const visitedViews = computed(() => useTagsViewStore().getVisitedViews());
const routes = computed(() => usePermissionStore().getRoutes()); const routes = computed(() => usePermissionStore().getRoutes());
const theme = computed(() => useSettingsStore().theme); const theme = computed(() => useSettingsStore().theme);
const tagsIcon = computed(() => useSettingsStore().tagsIcon)
watch(route, () => { watch(route, () => {
addTags(); addTags();
@ -285,6 +287,9 @@ onMounted(() => {
} }
} }
} }
.tags-view-item.active.has-icon::before {
content: none !important;
}
.contextmenu { .contextmenu {
margin: 0; margin: 0;
background: var(--el-bg-color); background: var(--el-bg-color);

View File

@ -67,7 +67,7 @@ const closeSearch = () => {
}; };
// //
const menuSearch = (queryString: string, cb: (options: any[]) => void) => { const menuSearch = (queryString: string, cb: (options: any[]) => void) => {
let options = state.menuList.filter((item) => { const options = state.menuList.filter((item) => {
return item.title.indexOf(queryString) > -1; return item.title.indexOf(queryString) > -1;
}); });
cb(options); cb(options);

View File

@ -24,10 +24,9 @@
</template> </template>
<script setup lang="ts" name="layoutBreadcrumbUserNews"> <script setup lang="ts" name="layoutBreadcrumbUserNews">
import { storeToRefs } from 'pinia';
import { useNoticeStore } from '@/store/modules/notice'; import { useNoticeStore } from '@/store/modules/notice';
const noticeStore = storeToRefs(useNoticeStore()); const noticeStore = useNoticeStore();
const { readAll } = useNoticeStore(); const { readAll } = useNoticeStore();
// //
@ -42,7 +41,7 @@ const newsList = ref([]) as any;
*/ */
const getTableData = async () => { const getTableData = async () => {
state.loading = true; state.loading = true;
newsList.value = noticeStore.state.value.notices; newsList.value = noticeStore.state.notices;
state.loading = false; state.loading = false;
}; };
@ -50,7 +49,7 @@ const getTableData = async () => {
const onNewsClick = (item: any) => { const onNewsClick = (item: any) => {
newsList.value[item].read = true; newsList.value[item].read = true;
//pinia //pinia
noticeStore.state.value.notices = newsList.value; noticeStore.state.notices = newsList.value;
}; };
// //

View File

@ -34,7 +34,7 @@ import i18n from '@/lang/index';
// vxeTable // vxeTable
import VXETable from 'vxe-table'; import VXETable from 'vxe-table';
import 'vxe-table/lib/style.css'; import 'vxe-table/lib/style.css';
VXETable.config({ VXETable.setConfig({
zIndex: 999999 zIndex: 999999
}); });

View File

@ -14,8 +14,8 @@ NProgress.configure({ showSpinner: false });
const whiteList = ['/login', '/register', '/social-callback', '/register*', '/register/*']; const whiteList = ['/login', '/register', '/social-callback', '/register*', '/register/*'];
const isWhiteList = (path: string) => { const isWhiteList = (path: string) => {
return whiteList.some(pattern => isPathMatch(pattern, path)) return whiteList.some((pattern) => isPathMatch(pattern, path));
} };
router.beforeEach(async (to, from, next) => { router.beforeEach(async (to, from, next) => {
NProgress.start(); NProgress.start();

View File

@ -93,132 +93,7 @@ export const constantRoutes: RouteRecordRaw[] = [
// 动态路由,基于用户权限动态去加载 // 动态路由,基于用户权限动态去加载
export const dynamicRoutes: RouteRecordRaw[] = [ export const dynamicRoutes: RouteRecordRaw[] = [
{
path: '/system/user-auth',
component: Layout,
hidden: true,
permissions: ['system:user:edit'],
children: [
{
path: 'role/:userId(\\d+)',
component: () => import('@/views/system/user/authRole.vue'),
name: 'AuthRole',
meta: { title: '分配角色', activeMenu: '/system/user', icon: '', noCache: true }
}
]
},
{
path: '/system/role-auth',
component: Layout,
hidden: true,
permissions: ['system:role:edit'],
children: [
{
path: 'user/:roleId(\\d+)',
component: () => import('@/views/system/role/authUser.vue'),
name: 'AuthUser',
meta: { title: '分配用户', activeMenu: '/system/role', icon: '', noCache: true }
}
]
},
{
path: '/system/dict-data',
component: Layout,
hidden: true,
permissions: ['system:dict:list'],
children: [
{
path: 'index/:dictId(\\d+)',
component: () => import('@/views/system/dict/data.vue'),
name: 'Data',
meta: { title: '字典数据', activeMenu: '/system/dict', icon: '', noCache: true }
}
]
},
{
path: '/system/oss-config',
component: Layout,
hidden: true,
permissions: ['system:ossConfig:list'],
children: [
{
path: 'index',
component: () => import('@/views/system/oss/config.vue'),
name: 'OssConfig',
meta: { title: '配置管理', activeMenu: '/system/oss', icon: '', noCache: true }
}
]
},
{
path: '/tool/gen-edit',
component: Layout,
hidden: true,
permissions: ['tool:gen:edit'],
children: [
{
path: 'index/:tableId(\\d+)',
component: () => import('@/views/tool/gen/editTable.vue'),
name: 'GenEdit',
meta: { title: '修改生成配置', activeMenu: '/tool/gen', icon: '', noCache: true }
}
]
},
{
path: '/workflow/leaveEdit',
component: Layout,
hidden: true,
permissions: ['workflow:leave:edit'],
children: [
{
path: 'index',
component: () => import('@/views/workflow/leave/leaveEdit.vue'),
name: 'leaveEdit',
meta: { title: '请假申请', activeMenu: '/workflow/leave', noCache: true }
}
]
},
{
path: '/workflow/tripEdit',
component: Layout,
hidden: true,
permissions: ['workflow:businessTrip:edit'],
children: [
{
path: 'index',
component: () => import('@/views/workflow/businessTrip/tripEdit.vue'),
name: 'tripEdit',
meta: { title: '出差申请', activeMenu: '/workflow/businessTrip', noCache: true }
}
]
},
{
path: '/workflow/sealEdit',
component: Layout,
hidden: true,
permissions: ['workflow:seal:edit'],
children: [
{
path: 'index',
component: () => import('@/views/workflow/seal/sealEdit.vue'),
name: 'sealEdit',
meta: { title: '用章申请', activeMenu: '/workflow/seal', noCache: true }
}
]
},
{
path: '/workflow/design',
component: Layout,
hidden: true,
permissions: ['workflow:leave:edit'],
children: [
{
path: 'index',
component: () => import('@/views/workflow/processDefinition/design.vue'),
name: 'design',
meta: { title: '流程设计', activeMenu: '/workflow/processDefinition', noCache: true }
}
]
}
]; ];
/** /**

View File

@ -27,6 +27,11 @@ const setting: DefaultSettings = {
*/ */
tagsView: true, tagsView: true,
/**
*
*/
tagsIcon: false,
/** /**
* *
*/ */
@ -42,14 +47,6 @@ const setting: DefaultSettings = {
*/ */
dynamicTitle: false, dynamicTitle: false,
/**
* @type {string | array} 'production' | ['production', 'development']
* @description Need show err logs component.
* The default is only used in the production env
* If you want to also use it in dev, you can pass ['production', 'development']
*/
errorLog: 'production',
/** /**
* *
*/ */

View File

@ -1,4 +1,4 @@
import { createPinia } from "pinia"; import { createPinia } from 'pinia';
const store = createPinia(); const store = createPinia();

View File

@ -99,14 +99,14 @@ export const usePermissionStore = defineStore('permission', () => {
}; };
const filterChildren = (childrenMap: RouteRecordRaw[], lastRouter?: RouteRecordRaw): RouteRecordRaw[] => { const filterChildren = (childrenMap: RouteRecordRaw[], lastRouter?: RouteRecordRaw): RouteRecordRaw[] => {
let children: RouteRecordRaw[] = []; let children: RouteRecordRaw[] = [];
childrenMap.forEach(el => { childrenMap.forEach((el) => {
el.path = lastRouter ? lastRouter.path + '/' + el.path : el.path; el.path = lastRouter ? lastRouter.path + '/' + el.path : el.path;
if (el.children && el.children.length && el.component?.toString() === 'ParentView') { if (el.children && el.children.length && el.component?.toString() === 'ParentView') {
children = children.concat(filterChildren(el.children, el)); children = children.concat(filterChildren(el.children, el));
} else { } else {
children.push(el); children.push(el);
} }
}) });
return children; return children;
}; };
return { return {

View File

@ -5,10 +5,10 @@ import { useStorage } from '@vueuse/core';
import { ref } from 'vue'; import { ref } from 'vue';
export const useSettingsStore = defineStore('setting', () => { export const useSettingsStore = defineStore('setting', () => {
// @ts-ignore
const storageSetting = useStorage<LayoutSetting>('layout-setting', { const storageSetting = useStorage<LayoutSetting>('layout-setting', {
topNav: defaultSettings.topNav, topNav: defaultSettings.topNav,
tagsView: defaultSettings.tagsView, tagsView: defaultSettings.tagsView,
tagsIcon: defaultSettings.tagsIcon,
fixedHeader: defaultSettings.fixedHeader, fixedHeader: defaultSettings.fixedHeader,
sidebarLogo: defaultSettings.sidebarLogo, sidebarLogo: defaultSettings.sidebarLogo,
dynamicTitle: defaultSettings.dynamicTitle, dynamicTitle: defaultSettings.dynamicTitle,
@ -21,6 +21,7 @@ export const useSettingsStore = defineStore('setting', () => {
const showSettings = ref<boolean>(defaultSettings.showSettings); const showSettings = ref<boolean>(defaultSettings.showSettings);
const topNav = ref<boolean>(storageSetting.value.topNav); const topNav = ref<boolean>(storageSetting.value.topNav);
const tagsView = ref<boolean>(storageSetting.value.tagsView); const tagsView = ref<boolean>(storageSetting.value.tagsView);
const tagsIcon = ref<boolean>(storageSetting.value.tagsIcon);
const fixedHeader = ref<boolean>(storageSetting.value.fixedHeader); const fixedHeader = ref<boolean>(storageSetting.value.fixedHeader);
const sidebarLogo = ref<boolean>(storageSetting.value.sidebarLogo); const sidebarLogo = ref<boolean>(storageSetting.value.sidebarLogo);
const dynamicTitle = ref<boolean>(storageSetting.value.dynamicTitle); const dynamicTitle = ref<boolean>(storageSetting.value.dynamicTitle);
@ -38,6 +39,7 @@ export const useSettingsStore = defineStore('setting', () => {
showSettings, showSettings,
topNav, topNav,
tagsView, tagsView,
tagsIcon,
fixedHeader, fixedHeader,
sidebarLogo, sidebarLogo,
dynamicTitle, dynamicTitle,

View File

@ -98,6 +98,10 @@ declare global {
* *
*/ */
tagsView: boolean; tagsView: boolean;
/**
*
*/
tagsIcon: boolean;
/** /**
* *
*/ */
@ -157,8 +161,6 @@ declare global {
* false: * false:
*/ */
dark: boolean; dark: boolean;
errorLog: string;
} }
} }
export {}; export {};

View File

@ -191,7 +191,8 @@ export function download(url: string, params: any, fileName: string) {
const blob = new Blob([resp]); const blob = new Blob([resp]);
FileSaver.saveAs(blob, fileName); FileSaver.saveAs(blob, fileName);
} else { } else {
const resText = await resp.data.text(); const blob = new Blob([resp]);
const resText = await blob.text();
const rspObj = JSON.parse(resText); const rspObj = JSON.parse(resText);
const errMsg = errorCode[rspObj.code] || rspObj.msg || errorCode['default']; const errMsg = errorCode[rspObj.code] || rspObj.msg || errorCode['default'];
ElMessage.error(errMsg); ElMessage.error(errMsg);

View File

@ -178,11 +178,11 @@ export const handleTree = <T>(data: any[], id?: string, parentId?: string, child
for (const d of data) { for (const d of data) {
const parentId = d[config.parentId]; const parentId = d[config.parentId];
const parentObj = childrenListMap[parentId] const parentObj = childrenListMap[parentId];
if (!parentObj) { if (!parentObj) {
tree.push(d); tree.push(d);
} else { } else {
parentObj[config.childrenList].push(d) parentObj[config.childrenList].push(d);
} }
} }
return tree; return tree;

View File

@ -49,7 +49,7 @@
</el-row> </el-row>
</template> </template>
<el-table v-loading="loading" :data="demoList" @selection-change="handleSelectionChange"> <el-table v-loading="loading" border :data="demoList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" /> <el-table-column type="selection" width="55" align="center" />
<el-table-column v-if="true" label="主键" align="center" prop="id" /> <el-table-column v-if="true" label="主键" align="center" prop="id" />
<el-table-column label="部门id" align="center" prop="deptId" /> <el-table-column label="部门id" align="center" prop="deptId" />

View File

@ -33,6 +33,7 @@
v-loading="loading" v-loading="loading"
:data="treeList" :data="treeList"
row-key="id" row-key="id"
border
:default-expand-all="isExpandAll" :default-expand-all="isExpandAll"
:tree-props="{ children: 'children', hasChildren: 'hasChildren' }" :tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
> >

View File

@ -22,7 +22,7 @@
<script setup lang="ts"> <script setup lang="ts">
import errImage from '@/assets/401_images/401.gif'; import errImage from '@/assets/401_images/401.gif';
let { proxy } = getCurrentInstance() as ComponentInternalInstance; const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const errGif = ref(errImage + '?' + +new Date()); const errGif = ref(errImage + '?' + +new Date());

View File

@ -22,7 +22,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
let message = computed(() => { const message = computed(() => {
return '找不到网页!'; return '找不到网页!';
}); });
</script> </script>

View File

@ -260,10 +260,9 @@ onMounted(() => {
background: #ffffff; background: #ffffff;
width: 400px; width: 400px;
padding: 25px 25px 5px 25px; padding: 25px 25px 5px 25px;
z-index: 1;
.el-input { .el-input {
height: 40px; height: 40px;
input { input {
height: 40px; height: 40px;
} }

View File

@ -4,12 +4,12 @@
<div v-show="showSearch" class="mb-[10px]"> <div v-show="showSearch" class="mb-[10px]">
<el-card shadow="hover"> <el-card shadow="hover">
<el-form ref="queryFormRef" :model="queryParams" :inline="true"> <el-form ref="queryFormRef" :model="queryParams" :inline="true">
<el-form-item label="合同名称" prop="contractName">
<el-input v-model="queryParams.contractName" placeholder="请输入合同名称" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="合同编码" prop="contractCode"> <el-form-item label="合同编码" prop="contractCode">
<el-input v-model="queryParams.contractCode" placeholder="请输入合同编码" clearable @keyup.enter="handleQuery" /> <el-input v-model="queryParams.contractCode" placeholder="请输入合同编码" clearable @keyup.enter="handleQuery" />
</el-form-item> </el-form-item>
<el-form-item label="合同名称" prop="contractName">
<el-input v-model="queryParams.contractName" placeholder="请输入合同名称" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button> <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button> <el-button icon="Refresh" @click="resetQuery">重置</el-button>
@ -40,10 +40,23 @@
<el-table v-loading="loading" :data="contractInfoList" @selection-change="handleSelectionChange"> <el-table v-loading="loading" :data="contractInfoList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" /> <el-table-column type="selection" width="55" align="center" />
<el-table-column label="" align="center" prop="id" v-if="true" /> <!-- <el-table-column label="" align="center" prop="id" v-if="true" />-->
<el-table-column label="合同名称" align="center" prop="contractName" /> <el-table-column label="合同编码" align="center" prop="contractCode" fixed="left"/>
<el-table-column label="合同名称" align="center" prop="contractName" width="300" fixed="left"/>
<el-table-column label="合同类型" align="center" prop="contractType" /> <el-table-column label="合同类型" align="center" prop="contractType" />
<el-table-column label="合同编码" align="center" prop="contractCode" /> <el-table-column label="合同负责人" align="center" prop="contractCode" />
<el-table-column label="重要性" align="center" prop="contractCode" />
<el-table-column label="委托单位" align="center" prop="contractCode" />
<el-table-column label="签约日期" align="center" prop="contractCode" />
<el-table-column label="合同类型" align="center" prop="contractCode" />
<el-table-column label="已开票" align="center" prop="contractCode" />
<el-table-column label="已收款" align="center" prop="contractCode" />
<el-table-column label="未履行" align="center" prop="contractCode" />
<el-table-column label="合同额" align="center" prop="contractCode" />
<el-table-column label="合同结算额" align="center" prop="contractCode" />
<el-table-column label="合同状态" align="center" prop="contractCode" />
<el-table-column label="咨询类型" align="center" prop="contractCode" />
<el-table-column label="业务类型" align="center" prop="contractCode" />
<el-table-column label="备注" align="center" prop="remark" /> <el-table-column label="备注" align="center" prop="remark" />
<el-table-column label="操作" align="center" class-name="small-padding fixed-width"> <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template #default="scope"> <template #default="scope">

View File

@ -63,6 +63,7 @@
v-loading="loading" v-loading="loading"
:data="loginInfoList" :data="loginInfoList"
:default-sort="defaultSort" :default-sort="defaultSort"
border
@selection-change="handleSelectionChange" @selection-change="handleSelectionChange"
@sort-change="handleSortChange" @sort-change="handleSortChange"
> >

View File

@ -19,6 +19,7 @@
<el-card shadow="hover"> <el-card shadow="hover">
<el-table <el-table
v-loading="loading" v-loading="loading"
border
:data="onlineList.slice((queryParams.pageNum - 1) * queryParams.pageSize, queryParams.pageNum * queryParams.pageSize)" :data="onlineList.slice((queryParams.pageNum - 1) * queryParams.pageSize, queryParams.pageNum * queryParams.pageSize)"
style="width: 100%" style="width: 100%"
> >

View File

@ -65,6 +65,7 @@
ref="operLogTableRef" ref="operLogTableRef"
v-loading="loading" v-loading="loading"
:data="operlogList" :data="operlogList"
border
:default-sort="defaultSort" :default-sort="defaultSort"
@selection-change="handleSelectionChange" @selection-change="handleSelectionChange"
@sort-change="handleSortChange" @sort-change="handleSortChange"

View File

@ -108,8 +108,8 @@
<el-table-column v-if="columns[3].visible" key="sex" label="性别" align="center" prop="sex" :show-overflow-tooltip="true" > <el-table-column v-if="columns[3].visible" key="sex" label="性别" align="center" prop="sex" :show-overflow-tooltip="true" >
<template #default="scope"> <template #default="scope">
<dict-tag :options="sys_user_sex" :value="scope.row.sex" /> <dict-tag :options="sys_user_sex" :value="scope.row.sex" />
</template> </template>
</el-table-column> </el-table-column>
<el-table-column v-if="columns[4].visible" key="deptName" label="部门" align="center" prop="deptName" :show-overflow-tooltip="true" width="180"/> <el-table-column v-if="columns[4].visible" key="deptName" label="部门" align="center" prop="deptName" :show-overflow-tooltip="true" width="180"/>
<el-table-column v-if="columns[5].visible" key="phonenumber" label="手机号码" align="center" prop="phonenumber" width="120" /> <el-table-column v-if="columns[5].visible" key="phonenumber" label="手机号码" align="center" prop="phonenumber" width="120" />
<el-table-column v-if="columns[6].visible" key="employeeHireDate" label="入职时间" align="center" prop="employeeHireDate" width="120" /> <el-table-column v-if="columns[6].visible" key="employeeHireDate" label="入职时间" align="center" prop="employeeHireDate" width="120" />
@ -117,12 +117,12 @@
<template #default="scope"> <template #default="scope">
<dict-tag :options="opr_yes_no" :value="scope.row.deptAdminFlag" /> <dict-tag :options="opr_yes_no" :value="scope.row.deptAdminFlag" />
</template> </template>
</el-table-column> </el-table-column>
<el-table-column v-if="columns[8].visible" key="employeeStatus" label="用工状态" align="center" prop="employeeStatus" width="100"> <el-table-column v-if="columns[8].visible" key="employeeStatus" label="用工状态" align="center" prop="employeeStatus" width="100">
<template #default="scope"> <template #default="scope">
<dict-tag :options="opr_employee_status" :value="scope.row.employeeStatus" /> <dict-tag :options="opr_employee_status" :value="scope.row.employeeStatus" />
</template> </template>
</el-table-column> </el-table-column>
<el-table-column v-if="columns[9].visible" key="status" label="状态" align="center"> <el-table-column v-if="columns[9].visible" key="status" label="状态" align="center">
<template #default="scope"> <template #default="scope">
<el-switch v-model="scope.row.status" active-value="0" inactive-value="1" @change="handleStatusChange(scope.row)"></el-switch> <el-switch v-model="scope.row.status" active-value="0" inactive-value="1" @change="handleStatusChange(scope.row)"></el-switch>

View File

@ -203,7 +203,6 @@ onMounted(() => {
line-height: 0; line-height: 0;
color: #7483a3; color: #7483a3;
} }
} }
.register-form { .register-form {

View File

@ -45,7 +45,7 @@
</el-row> </el-row>
</template> </template>
<el-table v-loading="loading" :data="clientList" @selection-change="handleSelectionChange"> <el-table v-loading="loading" :data="clientList" border @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" /> <el-table-column type="selection" width="55" align="center" />
<el-table-column v-if="true" label="id" align="center" prop="id" /> <el-table-column v-if="true" label="id" align="center" prop="id" />
<el-table-column label="客户端id" align="center" prop="clientId" /> <el-table-column label="客户端id" align="center" prop="clientId" />
@ -300,7 +300,7 @@ const handleExport = () => {
/** 状态修改 */ /** 状态修改 */
const handleStatusChange = async (row: ClientVO) => { const handleStatusChange = async (row: ClientVO) => {
let text = row.status === '0' ? '启用' : '停用'; const text = row.status === '0' ? '启用' : '停用';
try { try {
await proxy?.$modal.confirm('确认要"' + text + '"吗?'); await proxy?.$modal.confirm('确认要"' + text + '"吗?');
await changeStatus(row.clientId, row.status); await changeStatus(row.clientId, row.status);

View File

@ -60,7 +60,7 @@
</el-row> </el-row>
</template> </template>
<el-table v-loading="loading" :data="configList" @selection-change="handleSelectionChange"> <el-table v-loading="loading" border :data="configList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" /> <el-table-column type="selection" width="55" align="center" />
<el-table-column v-if="false" label="参数主键" align="center" prop="configId" /> <el-table-column v-if="false" label="参数主键" align="center" prop="configId" />
<el-table-column label="参数名称" align="center" prop="configName" :show-overflow-tooltip="true" /> <el-table-column label="参数名称" align="center" prop="configName" :show-overflow-tooltip="true" />

View File

@ -42,6 +42,7 @@
v-loading="loading" v-loading="loading"
:data="deptList" :data="deptList"
row-key="deptId" row-key="deptId"
border
:tree-props="{ children: 'children', hasChildren: 'hasChildren' }" :tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
:default-expand-all="isExpandAll" :default-expand-all="isExpandAll"
> >

View File

@ -44,7 +44,7 @@
</el-row> </el-row>
</template> </template>
<el-table v-loading="loading" :data="dataList" @selection-change="handleSelectionChange"> <el-table v-loading="loading" border :data="dataList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" /> <el-table-column type="selection" width="55" align="center" />
<el-table-column v-if="false" label="字典编码" align="center" prop="dictCode" /> <el-table-column v-if="false" label="字典编码" align="center" prop="dictCode" />
<el-table-column label="字典标签" align="center" prop="dictLabel"> <el-table-column label="字典标签" align="center" prop="dictLabel">

View File

@ -53,7 +53,7 @@
</el-row> </el-row>
</template> </template>
<el-table v-loading="loading" :data="typeList" @selection-change="handleSelectionChange"> <el-table v-loading="loading" border :data="typeList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" /> <el-table-column type="selection" width="55" align="center" />
<el-table-column v-if="false" label="字典编号" align="center" prop="dictId" /> <el-table-column v-if="false" label="字典编号" align="center" prop="dictId" />
<el-table-column label="字典名称" align="center" prop="dictName" :show-overflow-tooltip="true" /> <el-table-column label="字典名称" align="center" prop="dictName" :show-overflow-tooltip="true" />

View File

@ -30,6 +30,9 @@
<el-col :span="1.5"> <el-col :span="1.5">
<el-button type="info" plain icon="Sort" @click="handleToggleExpandAll">展开/折叠</el-button> <el-button type="info" plain icon="Sort" @click="handleToggleExpandAll">展开/折叠</el-button>
</el-col> </el-col>
<el-col :span="1.5">
<el-button type="danger" plain icon="Delete" @click="handleCascadeDelete" :loading="deleteLoading">级联删除</el-button>
</el-col>
<right-toolbar v-model:show-search="showSearch" @query-table="getList"></right-toolbar> <right-toolbar v-model:show-search="showSearch" @query-table="getList"></right-toolbar>
</el-row> </el-row>
</template> </template>
@ -39,6 +42,7 @@
v-loading="loading" v-loading="loading"
:data="menuList" :data="menuList"
row-key="menuId" row-key="menuId"
border
:tree-props="{ children: 'children', hasChildren: 'hasChildren' }" :tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
:default-expand-all="isExpandAll" :default-expand-all="isExpandAll"
> >
@ -129,8 +133,8 @@
</span> </span>
</template> </template>
<el-radio-group v-model="form.isFrame"> <el-radio-group v-model="form.isFrame">
<el-radio label="0"></el-radio> <el-radio value="0"></el-radio>
<el-radio label="1"></el-radio> <el-radio value="1"></el-radio>
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item>
</el-col> </el-col>
@ -207,8 +211,8 @@
</span> </span>
</template> </template>
<el-radio-group v-model="form.isCache"> <el-radio-group v-model="form.isCache">
<el-radio label="0">缓存</el-radio> <el-radio value="0">缓存</el-radio>
<el-radio label="1">不缓存</el-radio> <el-radio value="1">不缓存</el-radio>
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item>
</el-col> </el-col>
@ -225,7 +229,7 @@
</span> </span>
</template> </template>
<el-radio-group v-model="form.visible"> <el-radio-group v-model="form.visible">
<el-radio v-for="dict in sys_show_hide" :key="dict.value" :label="dict.value">{{ dict.label }} </el-radio> <el-radio v-for="dict in sys_show_hide" :key="dict.value" :value="dict.value">{{ dict.label }} </el-radio>
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item>
</el-col> </el-col>
@ -242,7 +246,7 @@
</span> </span>
</template> </template>
<el-radio-group v-model="form.status"> <el-radio-group v-model="form.status">
<el-radio v-for="dict in sys_normal_disable" :key="dict.value" :label="dict.value"> <el-radio v-for="dict in sys_normal_disable" :key="dict.value" :value="dict.value">
{{ dict.label }} {{ dict.label }}
</el-radio> </el-radio>
</el-radio-group> </el-radio-group>
@ -257,11 +261,31 @@
</div> </div>
</template> </template>
</el-dialog> </el-dialog>
<el-dialog v-model="deleteDialog.visible" :title="deleteDialog.title" destroy-on-close append-to-bod width="750px">
<el-tree
ref="menuTreeRef"
class="tree-border"
:data="menuOptions"
show-checkbox
node-key="menuId"
:check-strictly="false"
empty-text="加载中,请稍候"
:default-expanded-keys="[0]"
:props="{ value: 'menuId', label: 'menuName', children: 'children' } as any"
/>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="submitDeleteForm" :loading="deleteLoading"> </el-button>
<el-button @click="cancelCascade"> </el-button>
</div>
</template>
</el-dialog>
</div> </div>
</template> </template>
<script setup name="Menu" lang="ts"> <script setup name="Menu" lang="ts">
import { addMenu, delMenu, getMenu, listMenu, updateMenu } from '@/api/system/menu'; import { addMenu, cascadeDelMenu, delMenu, getMenu, listMenu, updateMenu } from '@/api/system/menu';
import { MenuForm, MenuQuery, MenuVO } from '@/api/system/menu/types'; import { MenuForm, MenuQuery, MenuVO } from '@/api/system/menu/types';
import { MenuTypeEnum } from '@/enums/MenuTypeEnum'; import { MenuTypeEnum } from '@/enums/MenuTypeEnum';
@ -404,7 +428,50 @@ const handleDelete = async (row: MenuVO) => {
proxy?.$modal.msgSuccess('删除成功'); proxy?.$modal.msgSuccess('删除成功');
}; };
const deleteLoading = ref<boolean>(false);
const menuTreeRef = ref<ElTreeInstance>();
const deleteDialog = reactive<DialogOption>({
visible: false,
title: '级联删除菜单'
});
/** 级联删除按钮操作 */
const handleCascadeDelete = () => {
menuTreeRef.value?.setCheckedKeys([]);
getTreeselect();
deleteDialog.visible = true;
};
/** 取消按钮 */
const cancelCascade = () => {
menuTreeRef.value?.setCheckedKeys([]);
deleteDialog.visible = false;
};
/** 删除提交按钮 */
const submitDeleteForm = async () => {
const menuIds = menuTreeRef.value?.getCheckedKeys();
if (menuIds.length < 0) {
proxy?.$modal.msgWarning('请选择要删除的菜单');
return;
}
deleteLoading.value = true;
await cascadeDelMenu(menuIds).finally(() => (deleteLoading.value = false));
await getList();
proxy?.$modal.msgSuccess('删除成功');
deleteDialog.visible = false;
};
onMounted(() => { onMounted(() => {
getList(); getList();
}); });
</script> </script>
<style scoped lang="scss">
.tree-border {
height: 300px;
overflow: auto;
}
</style>

View File

@ -44,7 +44,7 @@
</el-row> </el-row>
</template> </template>
<el-table v-loading="loading" :data="noticeList" @selection-change="handleSelectionChange"> <el-table v-loading="loading" border :data="noticeList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" /> <el-table-column type="selection" width="55" align="center" />
<el-table-column v-if="false" label="序号" align="center" prop="noticeId" width="100" /> <el-table-column v-if="false" label="序号" align="center" prop="noticeId" width="100" />
<el-table-column label="公告标题" align="center" prop="noticeTitle" :show-overflow-tooltip="true" /> <el-table-column label="公告标题" align="center" prop="noticeTitle" :show-overflow-tooltip="true" />

View File

@ -87,10 +87,18 @@
<el-input v-model="form.configKey" placeholder="请输入配置key" /> <el-input v-model="form.configKey" placeholder="请输入配置key" />
</el-form-item> </el-form-item>
<el-form-item label="访问站点" prop="endpoint"> <el-form-item label="访问站点" prop="endpoint">
<el-input v-model="form.endpoint" placeholder="请输入访问站点" /> <el-input v-model="form.endpoint" placeholder="请输入访问站点">
<template #prefix>
<span style="color: #999">{{ protocol }}</span>
</template>
</el-input>
</el-form-item> </el-form-item>
<el-form-item label="自定义域名" prop="domain"> <el-form-item label="自定义域名" prop="domain">
<el-input v-model="form.domain" placeholder="请输入自定义域名" /> <el-input v-model="form.domain" placeholder="请输入自定义域名">
<template #prefix>
<span style="color: #999">{{ protocol }}</span>
</template>
</el-input>
</el-form-item> </el-form-item>
<el-form-item label="accessKey" prop="accessKey"> <el-form-item label="accessKey" prop="accessKey">
<el-input v-model="form.accessKey" placeholder="请输入accessKey" /> <el-input v-model="form.accessKey" placeholder="请输入accessKey" />
@ -239,6 +247,8 @@ const data = reactive<PageData<OssConfigForm, OssConfigQuery>>({
const { queryParams, form, rules } = toRefs(data); const { queryParams, form, rules } = toRefs(data);
const protocol = computed(() => (form.value.isHttps === 'Y' ? 'https://' : 'http://'));
/** 查询对象存储配置列表 */ /** 查询对象存储配置列表 */
const getList = async () => { const getList = async () => {
loading.value = true; loading.value = true;
@ -306,7 +316,7 @@ const submitForm = () => {
}; };
/** 状态修改 */ /** 状态修改 */
const handleStatusChange = async (row: OssConfigVO) => { const handleStatusChange = async (row: OssConfigVO) => {
let text = row.status === '0' ? '启用' : '停用'; const text = row.status === '0' ? '启用' : '停用';
try { try {
await proxy?.$modal.confirm('确认要"' + text + '""' + row.configKey + '"配置吗?'); await proxy?.$modal.confirm('确认要"' + text + '""' + row.configKey + '"配置吗?');
await changeOssConfigStatus(row.ossConfigId, row.status, row.configKey); await changeOssConfigStatus(row.ossConfigId, row.status, row.configKey);

View File

@ -70,6 +70,7 @@
v-if="showTable" v-if="showTable"
v-loading="loading" v-loading="loading"
:data="ossList" :data="ossList"
border
:header-cell-class-name="handleHeaderClass" :header-cell-class-name="handleHeaderClass"
@selection-change="handleSelectionChange" @selection-change="handleSelectionChange"
@header-click="handleHeaderCLick" @header-click="handleHeaderCLick"
@ -255,9 +256,9 @@ const handleHeaderCLick = (column: any) => {
handleOrderChange(column.property, column.multiOrder); handleOrderChange(column.property, column.multiOrder);
}; };
const handleOrderChange = (prop: string, order: string) => { const handleOrderChange = (prop: string, order: string) => {
let orderByArr = queryParams.value.orderByColumn ? queryParams.value.orderByColumn.split(',') : []; const orderByArr = queryParams.value.orderByColumn ? queryParams.value.orderByColumn.split(',') : [];
let isAscArr = queryParams.value.isAsc ? queryParams.value.isAsc.split(',') : []; const isAscArr = queryParams.value.isAsc ? queryParams.value.isAsc.split(',') : [];
let propIndex = orderByArr.indexOf(prop); const propIndex = orderByArr.indexOf(prop);
if (propIndex !== -1) { if (propIndex !== -1) {
if (order) { if (order) {
// //
@ -306,7 +307,7 @@ const handleDownload = (row: OssVO) => {
}; };
/** 预览开关按钮 */ /** 预览开关按钮 */
const handlePreviewListResource = async (preview: boolean) => { const handlePreviewListResource = async (preview: boolean) => {
let text = preview ? '启用' : '停用'; const text = preview ? '启用' : '停用';
try { try {
await proxy?.$modal.confirm('确认要"' + text + '""预览列表图片"配置吗?'); await proxy?.$modal.confirm('确认要"' + text + '""预览列表图片"配置吗?');
await proxy?.updateConfigByKey('sys.oss.previewListResource', preview); await proxy?.updateConfigByKey('sys.oss.previewListResource', preview);

View File

@ -84,7 +84,7 @@
<right-toolbar v-model:show-search="showSearch" @query-table="getList"></right-toolbar> <right-toolbar v-model:show-search="showSearch" @query-table="getList"></right-toolbar>
</el-row> </el-row>
</template> </template>
<el-table v-loading="loading" :data="postList" @selection-change="handleSelectionChange"> <el-table v-loading="loading" border :data="postList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" /> <el-table-column type="selection" width="55" align="center" />
<el-table-column v-if="false" label="岗位编号" align="center" prop="postId" /> <el-table-column v-if="false" label="岗位编号" align="center" prop="postId" />
<el-table-column label="岗位编码" align="center" prop="postCode" /> <el-table-column label="岗位编码" align="center" prop="postCode" />

View File

@ -33,7 +33,7 @@
<right-toolbar v-model:show-search="showSearch" :search="true" @query-table="getList"></right-toolbar> <right-toolbar v-model:show-search="showSearch" :search="true" @query-table="getList"></right-toolbar>
</el-row> </el-row>
</template> </template>
<el-table v-loading="loading" :data="userList" @selection-change="handleSelectionChange"> <el-table v-loading="loading" border :data="userList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" /> <el-table-column type="selection" width="55" align="center" />
<el-table-column label="用户账号" prop="userName" :show-overflow-tooltip="true" /> <el-table-column label="用户账号" prop="userName" :show-overflow-tooltip="true" />
<el-table-column label="用户姓名" prop="nickName" :show-overflow-tooltip="true" /> <el-table-column label="用户姓名" prop="nickName" :show-overflow-tooltip="true" />

View File

@ -55,7 +55,7 @@
</el-row> </el-row>
</template> </template>
<el-table ref="roleTableRef" v-loading="loading" :data="roleList" @selection-change="handleSelectionChange"> <el-table ref="roleTableRef" border v-loading="loading" :data="roleList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" /> <el-table-column type="selection" width="55" align="center" />
<el-table-column v-if="false" label="角色编号" prop="roleId" width="120" /> <el-table-column v-if="false" label="角色编号" prop="roleId" width="120" />
<el-table-column label="角色名称" prop="roleName" :show-overflow-tooltip="true" width="150" /> <el-table-column label="角色名称" prop="roleName" :show-overflow-tooltip="true" width="150" />
@ -323,7 +323,7 @@ const handleSelectionChange = (selection: RoleVO[]) => {
/** 角色状态修改 */ /** 角色状态修改 */
const handleStatusChange = async (row: RoleVO) => { const handleStatusChange = async (row: RoleVO) => {
let text = row.status === '0' ? '启用' : '停用'; const text = row.status === '0' ? '启用' : '停用';
try { try {
await proxy?.$modal.confirm('确认要"' + text + '""' + row.roleName + '"角色吗?'); await proxy?.$modal.confirm('确认要"' + text + '""' + row.roleName + '"角色吗?');
await changeRoleStatus(row.roleId, row.status); await changeRoleStatus(row.roleId, row.status);
@ -346,11 +346,11 @@ const getMenuTreeselect = async () => {
/** 所有部门节点数据 */ /** 所有部门节点数据 */
const getDeptAllCheckedKeys = (): any => { const getDeptAllCheckedKeys = (): any => {
// //
let checkedKeys = deptRef.value?.getCheckedKeys(); const checkedKeys = deptRef.value?.getCheckedKeys();
// //
let halfCheckedKeys = deptRef.value?.getHalfCheckedKeys(); const halfCheckedKeys = deptRef.value?.getHalfCheckedKeys();
if (halfCheckedKeys) { if (halfCheckedKeys) {
checkedKeys?.unshift.apply(checkedKeys, halfCheckedKeys); checkedKeys?.unshift(...halfCheckedKeys);
} }
return checkedKeys; return checkedKeys;
}; };
@ -404,14 +404,14 @@ const getRoleDeptTreeSelect = async (roleId: string | number) => {
/** 树权限(展开/折叠)*/ /** 树权限(展开/折叠)*/
const handleCheckedTreeExpand = (value: boolean, type: string) => { const handleCheckedTreeExpand = (value: boolean, type: string) => {
if (type == 'menu') { if (type == 'menu') {
let treeList = menuOptions.value; const treeList = menuOptions.value;
for (let i = 0; i < treeList.length; i++) { for (let i = 0; i < treeList.length; i++) {
if (menuRef.value) { if (menuRef.value) {
menuRef.value.store.nodesMap[treeList[i].id].expanded = value; menuRef.value.store.nodesMap[treeList[i].id].expanded = value;
} }
} }
} else if (type == 'dept') { } else if (type == 'dept') {
let treeList = deptOptions.value; const treeList = deptOptions.value;
for (let i = 0; i < treeList.length; i++) { for (let i = 0; i < treeList.length; i++) {
if (deptRef.value) { if (deptRef.value) {
deptRef.value.store.nodesMap[treeList[i].id].expanded = value; deptRef.value.store.nodesMap[treeList[i].id].expanded = value;
@ -438,11 +438,11 @@ const handleCheckedTreeConnect = (value: any, type: string) => {
/** 所有菜单节点数据 */ /** 所有菜单节点数据 */
const getMenuAllCheckedKeys = (): any => { const getMenuAllCheckedKeys = (): any => {
// //
let checkedKeys = menuRef.value?.getCheckedKeys(); const checkedKeys = menuRef.value?.getCheckedKeys();
// //
let halfCheckedKeys = menuRef.value?.getHalfCheckedKeys(); const halfCheckedKeys = menuRef.value?.getHalfCheckedKeys();
if (halfCheckedKeys) { if (halfCheckedKeys) {
checkedKeys?.unshift.apply(checkedKeys, halfCheckedKeys); checkedKeys?.unshift(...halfCheckedKeys);
} }
return checkedKeys; return checkedKeys;
}; };

View File

@ -14,10 +14,10 @@
</el-form-item> </el-form-item>
</el-form> </el-form>
<el-row> <el-row>
<el-table ref="tableRef" :data="userList" height="260px" @row-click="clickRow" @selection-change="handleSelectionChange"> <el-table ref="tableRef" border :data="userList" height="260px" @row-click="clickRow" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55"></el-table-column> <el-table-column type="selection" width="55"></el-table-column>
<el-table-column label="用户账号" prop="userName" :show-overflow-tooltip="true" /> <el-table-column label="用户名称" prop="userName" :show-overflow-tooltip="true" />
<el-table-column label="用户姓名" prop="nickName" :show-overflow-tooltip="true" /> <el-table-column label="用户昵称" prop="nickName" :show-overflow-tooltip="true" />
<el-table-column label="邮箱" prop="email" :show-overflow-tooltip="true" /> <el-table-column label="邮箱" prop="email" :show-overflow-tooltip="true" />
<el-table-column label="手机" prop="phonenumber" :show-overflow-tooltip="true" /> <el-table-column label="手机" prop="phonenumber" :show-overflow-tooltip="true" />
<el-table-column label="状态" align="center" prop="status"> <el-table-column label="状态" align="center" prop="status">

View File

@ -51,7 +51,7 @@
</el-row> </el-row>
</template> </template>
<el-table v-loading="loading" :data="tenantList" @selection-change="handleSelectionChange"> <el-table v-loading="loading" border :data="tenantList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" /> <el-table-column type="selection" width="55" align="center" />
<el-table-column v-if="false" label="id" align="center" prop="id" /> <el-table-column v-if="false" label="id" align="center" prop="id" />
<el-table-column label="租户编号" align="center" prop="tenantId" /> <el-table-column label="租户编号" align="center" prop="tenantId" />
@ -245,7 +245,7 @@ const getList = async () => {
// //
const handleStatusChange = async (row: TenantVO) => { const handleStatusChange = async (row: TenantVO) => {
let text = row.status === '0' ? '启用' : '停用'; const text = row.status === '0' ? '启用' : '停用';
try { try {
await proxy?.$modal.confirm('确认要"' + text + '""' + row.companyName + '"租户吗?'); await proxy?.$modal.confirm('确认要"' + text + '""' + row.companyName + '"租户吗?');
await changeTenantStatus(row.id, row.tenantId, row.status); await changeTenantStatus(row.id, row.tenantId, row.status);
@ -361,7 +361,7 @@ const handleExport = () => {
/**同步租户字典*/ /**同步租户字典*/
const handleSyncTenantDict = async () => { const handleSyncTenantDict = async () => {
await proxy?.$modal.confirm('确认要同步所有租户字典吗?'); await proxy?.$modal.confirm('确认要同步所有租户字典吗?');
let res = await syncTenantDict(); const res = await syncTenantDict();
proxy?.$modal.msgSuccess(res.msg); proxy?.$modal.msgSuccess(res.msg);
}; };

View File

@ -39,7 +39,7 @@
</el-row> </el-row>
</template> </template>
<el-table v-loading="loading" :data="tenantPackageList" @selection-change="handleSelectionChange"> <el-table v-loading="loading" border :data="tenantPackageList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" /> <el-table-column type="selection" width="55" align="center" />
<el-table-column v-if="false" label="租户套餐id" align="center" prop="packageId" /> <el-table-column v-if="false" label="租户套餐id" align="center" prop="packageId" />
<el-table-column label="套餐名称" align="center" prop="packageName" /> <el-table-column label="套餐名称" align="center" prop="packageName" />
@ -167,11 +167,11 @@ const getMenuTreeselect = async () => {
// //
const getMenuAllCheckedKeys = (): any => { const getMenuAllCheckedKeys = (): any => {
// //
let checkedKeys = menuTreeRef.value?.getCheckedKeys(); const checkedKeys = menuTreeRef.value?.getCheckedKeys();
// //
let halfCheckedKeys = menuTreeRef.value?.getHalfCheckedKeys(); const halfCheckedKeys = menuTreeRef.value?.getHalfCheckedKeys();
if (halfCheckedKeys) { if (halfCheckedKeys) {
checkedKeys?.unshift.apply(checkedKeys, halfCheckedKeys); checkedKeys?.unshift(...halfCheckedKeys);
} }
return checkedKeys; return checkedKeys;
}; };
@ -194,7 +194,7 @@ const getList = async () => {
// //
const handleStatusChange = async (row: TenantPkgVO) => { const handleStatusChange = async (row: TenantPkgVO) => {
let text = row.status === '0' ? '启用' : '停用'; const text = row.status === '0' ? '启用' : '停用';
const [err] = await to(proxy?.$modal.confirm('确认要"' + text + '""' + row.packageName + '"套餐吗?') as Promise<any>); const [err] = await to(proxy?.$modal.confirm('确认要"' + text + '""' + row.packageName + '"套餐吗?') as Promise<any>);
if (err) { if (err) {
row.status = row.status === '0' ? '1' : '0'; row.status = row.status === '0' ? '1' : '0';
@ -241,7 +241,7 @@ const handleSelectionChange = (selection: TenantPkgVO[]) => {
// / // /
const handleCheckedTreeExpand = (value: CheckboxValueType, type: string) => { const handleCheckedTreeExpand = (value: CheckboxValueType, type: string) => {
if (type == 'menu') { if (type == 'menu') {
let treeList = menuOptions.value; const treeList = menuOptions.value;
for (let i = 0; i < treeList.length; i++) { for (let i = 0; i < treeList.length; i++) {
if (menuTreeRef.value) { if (menuTreeRef.value) {
menuTreeRef.value.store.nodesMap[treeList[i].id].expanded = value as boolean; menuTreeRef.value.store.nodesMap[treeList[i].id].expanded = value as boolean;

View File

@ -7,6 +7,8 @@
<el-col :span="2.5"> <el-col :span="2.5">
<el-form-item label="员工姓名" prop="employeeName"> <el-form-item label="员工姓名" prop="employeeName">
<el-input v-model="form.employeeName" disabled /> <el-input v-model="form.employeeName" disabled />
<el-form-item label="用户昵称" prop="nickName">
<el-input v-model="form.nickName" disabled />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="2.5"> <el-col :span="2.5">
@ -23,6 +25,7 @@
<el-table <el-table
ref="tableRef" ref="tableRef"
v-loading="loading" v-loading="loading"
border
:row-key="getRowKey" :row-key="getRowKey"
:data="roles.slice((pageNum - 1) * pageSize, pageNum * pageSize)" :data="roles.slice((pageNum - 1) * pageSize, pageNum * pageSize)"
@row-click="clickRow" @row-click="clickRow"
@ -33,7 +36,7 @@
<span>{{ (pageNum - 1) * pageSize + scope.$index + 1 }}</span> <span>{{ (pageNum - 1) * pageSize + scope.$index + 1 }}</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column type="selection" :reserve-selection="true" width="55"></el-table-column> <el-table-column type="selection" :reserve-selection="true" :selectable="checkSelectable" width="55"></el-table-column>
<el-table-column label="角色编号" align="center" prop="roleId" /> <el-table-column label="角色编号" align="center" prop="roleId" />
<el-table-column label="角色名称" align="center" prop="roleName" /> <el-table-column label="角色名称" align="center" prop="roleName" />
<el-table-column label="权限字符" align="center" prop="roleKey" /> <el-table-column label="权限字符" align="center" prop="roleKey" />
@ -72,6 +75,7 @@ const roleIds = ref<Array<string | number>>([]);
const roles = ref<RoleVO[]>([]); const roles = ref<RoleVO[]>([]);
const form = ref<Partial<UserForm>>({ const form = ref<Partial<UserForm>>({
employeeName: undefined, employeeName: undefined,
nickName: undefined,
userName: '', userName: '',
userId: undefined userId: undefined
}); });
@ -80,8 +84,10 @@ const tableRef = ref<ElTableInstance>();
/** 单击选中行数据 */ /** 单击选中行数据 */
const clickRow = (row: RoleVO) => { const clickRow = (row: RoleVO) => {
row.flag = !row.flag; if (checkSelectable(row)) {
tableRef.value?.toggleRowSelection(row, row.flag); row.flag = !row.flag;
tableRef.value?.toggleRowSelection(row, row.flag);
}
}; };
/** 多选框选中数据 */ /** 多选框选中数据 */
const handleSelectionChange = (selection: RoleVO[]) => { const handleSelectionChange = (selection: RoleVO[]) => {
@ -91,6 +97,10 @@ const handleSelectionChange = (selection: RoleVO[]) => {
const getRowKey = (row: RoleVO): string => { const getRowKey = (row: RoleVO): string => {
return String(row.roleId); return String(row.roleId);
}; };
/** 检查角色状态 */
const checkSelectable = (row: RoleVO): boolean => {
return row.status === '0';
};
/** 关闭按钮 */ /** 关闭按钮 */
const close = () => { const close = () => {
const obj: RouteLocationNormalized = { const obj: RouteLocationNormalized = {

View File

@ -27,6 +27,9 @@
<el-form-item label="用户名称" prop="userName"> <el-form-item label="用户名称" prop="userName">
<el-input v-model="queryParams.userName" placeholder="请输入用户名称" clearable @keyup.enter="handleQuery" /> <el-input v-model="queryParams.userName" placeholder="请输入用户名称" clearable @keyup.enter="handleQuery" />
</el-form-item> </el-form-item>
<el-form-item label="用户昵称" prop="nickName">
<el-input v-model="queryParams.nickName" placeholder="请输入用户昵称" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="手机号码" prop="phonenumber"> <el-form-item label="手机号码" prop="phonenumber">
<el-input v-model="queryParams.phonenumber" placeholder="请输入手机号码" clearable @keyup.enter="handleQuery" /> <el-input v-model="queryParams.phonenumber" placeholder="请输入手机号码" clearable @keyup.enter="handleQuery" />
</el-form-item> </el-form-item>
@ -92,11 +95,11 @@
</el-row> </el-row>
</template> </template>
<el-table v-loading="loading" :data="userList" @selection-change="handleSelectionChange"> <el-table v-loading="loading" border :data="userList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="50" align="center" /> <el-table-column type="selection" width="50" align="center" />
<el-table-column v-if="columns[0].visible" key="userId" label="用户编号" align="center" prop="userId" /> <el-table-column v-if="columns[0].visible" key="userId" label="用户编号" align="center" prop="userId" />
<el-table-column v-if="columns[1].visible" key="userName" label="用户账号" align="center" prop="userName" :show-overflow-tooltip="true" /> <el-table-column v-if="columns[1].visible" key="userName" label="用户名称" align="center" prop="userName" :show-overflow-tooltip="true" />
<el-table-column v-if="columns[2].visible" key="nickName" label="用户姓名" align="center" prop="nickName" :show-overflow-tooltip="true" /> <el-table-column v-if="columns[2].visible" key="nickName" label="用户昵称" align="center" prop="nickName" :show-overflow-tooltip="true" />
<el-table-column v-if="columns[3].visible" key="deptName" label="部门" align="center" prop="deptName" :show-overflow-tooltip="true" /> <el-table-column v-if="columns[3].visible" key="deptName" label="部门" align="center" prop="deptName" :show-overflow-tooltip="true" />
<el-table-column v-if="columns[4].visible" key="phonenumber" label="手机号码" align="center" prop="phonenumber" width="120" /> <el-table-column v-if="columns[4].visible" key="phonenumber" label="手机号码" align="center" prop="phonenumber" width="120" />
<el-table-column v-if="columns[5].visible" key="status" label="状态" align="center"> <el-table-column v-if="columns[5].visible" key="status" label="状态" align="center">
@ -147,8 +150,8 @@
<el-form ref="userFormRef" :model="form" :rules="rules" label-width="80px"> <el-form ref="userFormRef" :model="form" :rules="rules" label-width="80px">
<el-row> <el-row>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="用户姓名" prop="nickName"> <el-form-item label="用户昵称" prop="nickName">
<el-input v-model="form.nickName" placeholder="请输入用户姓名" maxlength="30" /> <el-input v-model="form.nickName" placeholder="请输入用户昵称" maxlength="30" />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
@ -334,7 +337,7 @@ const upload = reactive<ImportOption>({
const columns = ref<FieldOption[]>([ const columns = ref<FieldOption[]>([
{ key: 0, label: `用户编号`, visible: false, children: [] }, { key: 0, label: `用户编号`, visible: false, children: [] },
{ key: 1, label: `用户名称`, visible: true, children: [] }, { key: 1, label: `用户名称`, visible: true, children: [] },
{ key: 2, label: `用户姓名`, visible: true, children: [] }, { key: 2, label: `用户昵称`, visible: true, children: [] },
{ key: 3, label: `部门`, visible: true, children: [] }, { key: 3, label: `部门`, visible: true, children: [] },
{ key: 4, label: `手机号码`, visible: true, children: [] }, { key: 4, label: `手机号码`, visible: true, children: [] },
{ key: 5, label: `状态`, visible: true, children: [] }, { key: 5, label: `状态`, visible: true, children: [] },
@ -498,7 +501,7 @@ const handleDelete = async (row?: UserVO) => {
/** 用户状态修改 */ /** 用户状态修改 */
const handleStatusChange = async (row: UserVO) => { const handleStatusChange = async (row: UserVO) => {
let text = row.status === '0' ? '启用' : '停用'; const text = row.status === '0' ? '启用' : '停用';
try { try {
await proxy?.$modal.confirm('确认要"' + text + '""' + row.userName + '"用户吗?'); await proxy?.$modal.confirm('确认要"' + text + '""' + row.userName + '"用户吗?');
await api.changeUserStatus(row.userId, row.status); await api.changeUserStatus(row.userId, row.status);

View File

@ -1,6 +1,6 @@
<template> <template>
<div> <div>
<el-table :data="devices" style="width: 100%; height: 100%; font-size: 14px"> <el-table :data="devices" border style="width: 100%; height: 100%; font-size: 14px">
<el-table-column label="设备类型" align="center"> <el-table-column label="设备类型" align="center">
<template #default="scope"> <template #default="scope">
<dict-tag :options="sys_device_type" :value="scope.row.deviceType" /> <dict-tag :options="sys_device_type" :value="scope.row.deviceType" />

View File

@ -1,6 +1,6 @@
<template> <template>
<div> <div>
<el-table :data="auths" style="width: 100%; height: 100%; font-size: 14px"> <el-table :data="auths" border style="width: 100%; height: 100%; font-size: 14px">
<el-table-column label="序号" width="50" type="index" /> <el-table-column label="序号" width="50" type="index" />
<el-table-column label="绑定账号平台" width="140" align="center" prop="source" show-overflow-tooltip /> <el-table-column label="绑定账号平台" width="140" align="center" prop="source" show-overflow-tooltip />
<el-table-column label="头像" width="120" align="center" prop="avatar"> <el-table-column label="头像" width="120" align="center" prop="avatar">

View File

@ -134,7 +134,7 @@ const beforeUpload = (file: UploadRawFile): any => {
/** 上传图片 */ /** 上传图片 */
const uploadImg = async () => { const uploadImg = async () => {
cropper.value.getCropBlob(async (data: any) => { cropper.value.getCropBlob(async (data: any) => {
let formData = new FormData(); const formData = new FormData();
formData.append('avatarfile', data, options.fileName); formData.append('avatarfile', data, options.fileName);
const res = await uploadAvatar(formData); const res = await uploadAvatar(formData);
open.value = false; open.value = false;

View File

@ -33,7 +33,7 @@ const userForm = computed(() => props.user);
const { proxy } = getCurrentInstance() as ComponentInternalInstance; const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const userRef = ref<ElFormInstance>(); const userRef = ref<ElFormInstance>();
const rule: ElFormRules = { const rule: ElFormRules = {
nickName: [{ required: true, message: '用户姓名不能为空', trigger: 'blur' }], nickName: [{ required: true, message: '用户昵称不能为空', trigger: 'blur' }],
email: [ email: [
{ required: true, message: '邮箱地址不能为空', trigger: 'blur' }, { required: true, message: '邮箱地址不能为空', trigger: 'blur' },
{ {

View File

@ -5,7 +5,7 @@
<basic-info-form ref="basicInfo" :info="info" /> <basic-info-form ref="basicInfo" :info="info" />
</el-tab-pane> </el-tab-pane>
<el-tab-pane label="字段信息" name="columnInfo"> <el-tab-pane label="字段信息" name="columnInfo">
<el-table ref="dragTable" :data="columns" row-key="columnId" :max-height="tableHeight"> <el-table ref="dragTable" border :data="columns" row-key="columnId" :max-height="tableHeight">
<el-table-column label="序号" type="index" min-width="5%" /> <el-table-column label="序号" type="index" min-width="5%" />
<el-table-column label="字段列名" prop="columnName" min-width="10%" :show-overflow-tooltip="true" /> <el-table-column label="字段列名" prop="columnName" min-width="10%" :show-overflow-tooltip="true" />
<el-table-column label="字段描述" min-width="10%"> <el-table-column label="字段描述" min-width="10%">

View File

@ -19,7 +19,7 @@
</el-form-item> </el-form-item>
</el-form> </el-form>
<el-row> <el-row>
<el-table ref="tableRef" :data="dbTableList" height="260px" @row-click="clickRow" @selection-change="handleSelectionChange"> <el-table ref="tableRef" border :data="dbTableList" height="260px" @row-click="clickRow" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55"></el-table-column> <el-table-column type="selection" width="55"></el-table-column>
<el-table-column prop="tableName" label="表名称" :show-overflow-tooltip="true"></el-table-column> <el-table-column prop="tableName" label="表名称" :show-overflow-tooltip="true"></el-table-column>
<el-table-column prop="tableComment" label="表描述" :show-overflow-tooltip="true"></el-table-column> <el-table-column prop="tableComment" label="表描述" :show-overflow-tooltip="true"></el-table-column>

View File

@ -56,7 +56,7 @@
</el-row> </el-row>
</template> </template>
<el-table v-loading="loading" :data="tableList" @selection-change="handleSelectionChange"> <el-table v-loading="loading" border :data="tableList" @selection-change="handleSelectionChange">
<el-table-column type="selection" align="center" width="55"></el-table-column> <el-table-column type="selection" align="center" width="55"></el-table-column>
<el-table-column label="序号" type="index" width="50" align="center"> <el-table-column label="序号" type="index" width="50" align="center">
<template #default="scope"> <template #default="scope">
@ -113,8 +113,8 @@
</template> </template>
<script setup name="Gen" lang="ts"> <script setup name="Gen" lang="ts">
import {delTable, genCode, getDataNames, listTable, previewTable, synchDb} from '@/api/tool/gen'; import { delTable, genCode, getDataNames, listTable, previewTable, synchDb } from '@/api/tool/gen';
import {TableQuery, TableVO} from '@/api/tool/gen/types'; import { TableQuery, TableVO } from '@/api/tool/gen/types';
import router from '@/router'; import router from '@/router';
import ImportTable from './importTable.vue'; import ImportTable from './importTable.vue';

View File

@ -31,10 +31,11 @@
v-loading="loading" v-loading="loading"
:data="categoryList" :data="categoryList"
row-key="categoryId" row-key="categoryId"
border
:default-expand-all="isExpandAll" :default-expand-all="isExpandAll"
:tree-props="{ children: 'children', hasChildren: 'hasChildren' }" :tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
> >
<el-table-column label="分类名称" prop="categoryName" width="260"/> <el-table-column label="分类名称" prop="categoryName" width="260" />
<el-table-column label="显示顺序" align="center" prop="orderNum" width="200" /> <el-table-column label="显示顺序" align="center" prop="orderNum" width="200" />
<el-table-column label="创建时间" align="center" prop="createTime" width="180" /> <el-table-column label="创建时间" align="center" prop="createTime" width="180" />
<el-table-column label="操作" fixed="right" align="center" class-name="small-padding fixed-width"> <el-table-column label="操作" fixed="right" align="center" class-name="small-padding fixed-width">
@ -77,7 +78,7 @@
</el-col> </el-col>
</el-row> </el-row>
</el-form> </el-form>
<template #footer> <template #footer>
<div class="dialog-footer"> <div class="dialog-footer">
<el-button :loading="buttonLoading" type="primary" @click="submitForm"> </el-button> <el-button :loading="buttonLoading" type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button> <el-button @click="cancel"> </el-button>
@ -88,17 +89,16 @@
</template> </template>
<script setup name="Category" lang="ts"> <script setup name="Category" lang="ts">
import { listCategory, getCategory, delCategory, addCategory, updateCategory } from "@/api/workflow/category"; import { listCategory, getCategory, delCategory, addCategory, updateCategory } from '@/api/workflow/category';
import { CategoryVO, CategoryQuery, CategoryForm } from '@/api/workflow/category/types'; import { CategoryVO, CategoryQuery, CategoryForm } from '@/api/workflow/category/types';
type CategoryOption = { type CategoryOption = {
categoryId: number; categoryId: number;
categoryName: string; categoryName: string;
children?: CategoryOption[]; children?: CategoryOption[];
} };
const { proxy } = getCurrentInstance() as ComponentInternalInstance;;
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const categoryList = ref<CategoryVO[]>([]); const categoryList = ref<CategoryVO[]>([]);
const categoryOptions = ref<CategoryOption[]>([]); const categoryOptions = ref<CategoryOption[]>([]);
@ -109,32 +109,29 @@ const loading = ref(false);
const queryFormRef = ref<ElFormInstance>(); const queryFormRef = ref<ElFormInstance>();
const categoryFormRef = ref<ElFormInstance>(); const categoryFormRef = ref<ElFormInstance>();
const categoryTableRef = ref<ElTableInstance>() const categoryTableRef = ref<ElTableInstance>();
const dialog = reactive<DialogOption>({ const dialog = reactive<DialogOption>({
visible: false, visible: false,
title: '' title: ''
}); });
const initFormData: CategoryForm = { const initFormData: CategoryForm = {
categoryId: undefined, categoryId: undefined,
categoryName: "", categoryName: '',
parentId: undefined, parentId: undefined,
orderNum: 0, orderNum: 0
} };
const data = reactive<PageData<CategoryForm, CategoryQuery>>({ const data = reactive<PageData<CategoryForm, CategoryQuery>>({
form: {...initFormData}, form: { ...initFormData },
queryParams: { queryParams: {
categoryName: undefined, categoryName: undefined
}, },
rules: { rules: {
categoryId: [ categoryId: [{ required: true, message: '流程分类ID不能为空', trigger: 'blur' }],
{ required: true, message: "流程分类ID不能为空", trigger: "blur" } parentId: [{ required: true, message: '请选择上级分类', trigger: 'change' }],
], categoryName: [{ required: true, message: '请输入分类名称', trigger: 'blur' }]
parentId: [{ required: true, message: "请选择上级分类", trigger: "change" }],
categoryName: [{ required: true, message: "请输入分类名称", trigger: "blur" }]
} }
}); });
@ -144,19 +141,19 @@ const { queryParams, form, rules } = toRefs(data);
const getList = async () => { const getList = async () => {
loading.value = true; loading.value = true;
const res = await listCategory(queryParams.value); const res = await listCategory(queryParams.value);
const data = proxy?.handleTree<CategoryVO>(res.data, "categoryId", "parentId"); const data = proxy?.handleTree<CategoryVO>(res.data, 'categoryId', 'parentId');
if (data) { if (data) {
categoryList.value = data; categoryList.value = data;
loading.value = false; loading.value = false;
} }
} };
/** 查询流程分类下拉树结构 */ /** 查询流程分类下拉树结构 */
const getTreeselect = async () => { const getTreeselect = async () => {
const res = await listCategory(); const res = await listCategory();
categoryOptions.value = []; categoryOptions.value = [];
// //
const data = proxy?.handleTree<CategoryOption>(res.data, "categoryId", "parentId"); const data = proxy?.handleTree<CategoryOption>(res.data, 'categoryId', 'parentId');
if (data) { if (data) {
categoryOptions.value = data; // categoryOptions.value = data; //
} }
@ -166,24 +163,24 @@ const getTreeselect = async () => {
const cancel = () => { const cancel = () => {
reset(); reset();
dialog.visible = false; dialog.visible = false;
} };
// //
const reset = () => { const reset = () => {
form.value = {...initFormData} form.value = { ...initFormData };
categoryFormRef.value?.resetFields(); categoryFormRef.value?.resetFields();
} };
/** 搜索按钮操作 */ /** 搜索按钮操作 */
const handleQuery = () => { const handleQuery = () => {
getList(); getList();
} };
/** 重置按钮操作 */ /** 重置按钮操作 */
const resetQuery = () => { const resetQuery = () => {
queryFormRef.value?.resetFields(); queryFormRef.value?.resetFields();
handleQuery(); handleQuery();
} };
/** 新增按钮操作 */ /** 新增按钮操作 */
const handleAdd = (row?: CategoryVO) => { const handleAdd = (row?: CategoryVO) => {
@ -195,22 +192,22 @@ const handleAdd = (row?: CategoryVO) => {
form.value.parentId = undefined; form.value.parentId = undefined;
} }
dialog.visible = true; dialog.visible = true;
dialog.title = "添加流程分类"; dialog.title = '添加流程分类';
} };
/** 展开/折叠操作 */ /** 展开/折叠操作 */
const handleToggleExpandAll = () => { const handleToggleExpandAll = () => {
isExpandAll.value = !isExpandAll.value; isExpandAll.value = !isExpandAll.value;
toggleExpandAll(categoryList.value, isExpandAll.value) toggleExpandAll(categoryList.value, isExpandAll.value);
} };
/** 展开/折叠操作 */ /** 展开/折叠操作 */
const toggleExpandAll = (data: CategoryVO[], status: boolean) => { const toggleExpandAll = (data: CategoryVO[], status: boolean) => {
data.forEach((item) => { data.forEach((item) => {
categoryTableRef.value?.toggleRowExpansion(item, status) categoryTableRef.value?.toggleRowExpansion(item, status);
if (item.children && item.children.length > 0) toggleExpandAll(item.children, status) if (item.children && item.children.length > 0) toggleExpandAll(item.children, status);
}) });
} };
/** 修改按钮操作 */ /** 修改按钮操作 */
const handleUpdate = async (row: CategoryVO) => { const handleUpdate = async (row: CategoryVO) => {
@ -222,8 +219,8 @@ const handleUpdate = async (row: CategoryVO) => {
const res = await getCategory(row.categoryId); const res = await getCategory(row.categoryId);
Object.assign(form.value, res.data); Object.assign(form.value, res.data);
dialog.visible = true; dialog.visible = true;
dialog.title = "修改流程分类"; dialog.title = '修改流程分类';
} };
/** 提交按钮 */ /** 提交按钮 */
const submitForm = () => { const submitForm = () => {
@ -231,25 +228,25 @@ const submitForm = () => {
if (valid) { if (valid) {
buttonLoading.value = true; buttonLoading.value = true;
if (form.value.categoryId) { if (form.value.categoryId) {
await updateCategory(form.value).finally(() => buttonLoading.value = false); await updateCategory(form.value).finally(() => (buttonLoading.value = false));
} else { } else {
await addCategory(form.value).finally(() => buttonLoading.value = false); await addCategory(form.value).finally(() => (buttonLoading.value = false));
} }
proxy?.$modal.msgSuccess("操作成功"); proxy?.$modal.msgSuccess('操作成功');
dialog.visible = false; dialog.visible = false;
getList(); getList();
} }
}); });
} };
/** 删除按钮操作 */ /** 删除按钮操作 */
const handleDelete = async (row: CategoryVO) => { const handleDelete = async (row: CategoryVO) => {
await proxy?.$modal.confirm('是否确认删除"' + row.categoryName + '"的分类?'); await proxy?.$modal.confirm('是否确认删除"' + row.categoryName + '"的分类?');
loading.value = true; loading.value = true;
await delCategory(row.categoryId).finally(() => loading.value = false); await delCategory(row.categoryId).finally(() => (loading.value = false));
await getList(); await getList();
proxy?.$modal.msgSuccess("删除成功"); proxy?.$modal.msgSuccess('删除成功');
} };
onMounted(() => { onMounted(() => {
getList(); getList();

View File

@ -34,10 +34,10 @@
<el-table v-loading="loading" border :data="leaveList" @selection-change="handleSelectionChange"> <el-table v-loading="loading" border :data="leaveList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" /> <el-table-column type="selection" width="55" align="center" />
<el-table-column v-if="false" label="主键" align="center" prop="id" /> <el-table-column v-if="false" label="主键" align="center" prop="id" />
<el-table-column label="请假类型" align="center" prop="leaveType"> <el-table-column label="请假类型" align="center">
<template #default="scope"> <template #default="scope">
<dict-tag :options="opr_oa_leave_type" :value="scope.row.leaveType" /> <el-tag>{{ options.find((e) => e.value === scope.row.leaveType)?.label }}</el-tag>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="开始时间" align="center" prop="startDate"> <el-table-column label="开始时间" align="center" prop="startDate">
<template #default="scope"> <template #default="scope">
@ -50,10 +50,7 @@
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="请假天数" align="center" prop="leaveDays" /> <el-table-column label="请假天数" align="center" prop="leaveDays" />
<el-table-column label="请假原因" align="center" prop="reason" /> <el-table-column label="请假原因" align="center" prop="remark" />
<el-table-column label="在办项目" align="center" prop="currentProjects" />
<!-- <el-table-column label="附件" align="center" prop="attachment" /> -->
<el-table-column label="备注" align="center" prop="remark" />
<el-table-column align="center" label="流程状态" min-width="70"> <el-table-column align="center" label="流程状态" min-width="70">
<template #default="scope"> <template #default="scope">
<dict-tag :options="wf_business_status" :value="scope.row.status"></dict-tag> <dict-tag :options="wf_business_status" :value="scope.row.status"></dict-tag>
@ -104,27 +101,27 @@ const ids = ref<Array<string | number>>([]);
const single = ref(true); const single = ref(true);
const multiple = ref(true); const multiple = ref(true);
const total = ref(0); const total = ref(0);
// const options = [ const options = [
// { {
// value: '1', value: '1',
// label: '' label: '事假'
// }, },
// { {
// value: '2', value: '2',
// label: '' label: '调休'
// }, },
// { {
// value: '3', value: '3',
// label: '' label: '病假'
// }, },
// { {
// value: '4', value: '4',
// label: '' label: '婚假'
// } }
// ]; ];
const queryFormRef = ref<ElFormInstance>(); const queryFormRef = ref<ElFormInstance>();
const { opr_oa_leave_type } = toRefs<any>(proxy?.useDict('opr_oa_leave_type'));
const data = reactive<PageData<LeaveForm, LeaveQuery>>({ const data = reactive<PageData<LeaveForm, LeaveQuery>>({
form: {}, form: {},
queryParams: { queryParams: {
@ -225,7 +222,7 @@ const handleExport = () => {
const handleCancelProcessApply = async (id: string) => { const handleCancelProcessApply = async (id: string) => {
await proxy?.$modal.confirm('是否确认撤销当前单据?'); await proxy?.$modal.confirm('是否确认撤销当前单据?');
loading.value = true; loading.value = true;
let data = { const data = {
businessId: id, businessId: id,
message: '申请人撤销流程!' message: '申请人撤销流程!'
}; };

View File

@ -1,17 +1,15 @@
<template> <template>
<div class="p-2"> <div class="p-2">
<el-card shadow="never"> <el-card shadow="never">
<div style="display: flex; justify-content: space-between"> <approvalButton
<div> @submitForm="submitForm"
<el-button v-if="submitButtonShow" :loading="buttonLoading" type="info" @click="submitForm('draft')">暂存</el-button> @approvalVerifyOpen="approvalVerifyOpen"
<el-button v-if="submitButtonShow" :loading="buttonLoading" type="primary" @click="submitForm('submit')"> </el-button> @handleApprovalRecord="handleApprovalRecord"
<el-button v-if="approvalButtonShow" :loading="buttonLoading" type="primary" @click="approvalVerifyOpen">审批</el-button> :buttonLoading="buttonLoading"
<el-button v-if="form && form.id && form.status !== 'draft'" type="primary" @click="handleApprovalRecord">流程进度</el-button> :id="form.id"
</div> :status="form.status"
<div> :pageType="routeParams.type"
<el-button style="float: right" @click="goBack()">返回</el-button> />
</div>
</div>
</el-card> </el-card>
<el-card shadow="never" style="height: 78vh; overflow-y: auto"> <el-card shadow="never" style="height: 78vh; overflow-y: auto">
<el-form ref="leaveFormRef" v-loading="loading" :disabled="routeParams.type === 'view'" :model="form" :rules="rules" label-width="80px"> <el-form ref="leaveFormRef" v-loading="loading" :disabled="routeParams.type === 'view'" :model="form" :rules="rules" label-width="80px">
@ -73,6 +71,7 @@ import { LeaveForm, LeaveQuery, LeaveVO } from '@/api/workflow/leave/types';
import { startWorkFlow } from '@/api/workflow/task'; import { startWorkFlow } from '@/api/workflow/task';
import SubmitVerify from '@/components/Process/submitVerify.vue'; import SubmitVerify from '@/components/Process/submitVerify.vue';
import ApprovalRecord from '@/components/Process/approvalRecord.vue'; import ApprovalRecord from '@/components/Process/approvalRecord.vue';
import ApprovalButton from '@/components/Process/approvalButton.vue';
import { AxiosResponse } from 'axios'; import { AxiosResponse } from 'axios';
import { StartProcessBo } from '@/api/workflow/workflowCommon/types'; import { StartProcessBo } from '@/api/workflow/workflowCommon/types';
const { proxy } = getCurrentInstance() as ComponentInternalInstance; const { proxy } = getCurrentInstance() as ComponentInternalInstance;
@ -139,6 +138,8 @@ const dialogVisible = reactive<DialogOption>({
const submitVerifyRef = ref<InstanceType<typeof SubmitVerify>>(); const submitVerifyRef = ref<InstanceType<typeof SubmitVerify>>();
// //
const approvalRecordRef = ref<InstanceType<typeof ApprovalRecord>>(); const approvalRecordRef = ref<InstanceType<typeof ApprovalRecord>>();
//
const approvalButtonRef = ref<InstanceType<typeof ApprovalButton>>();
const leaveFormRef = ref<ElFormInstance>(); const leaveFormRef = ref<ElFormInstance>();
@ -223,9 +224,9 @@ const submitForm = (status: string) => {
buttonLoading.value = true; buttonLoading.value = true;
let res: AxiosResponse<LeaveVO>; let res: AxiosResponse<LeaveVO>;
if (form.value.id) { if (form.value.id) {
res = await updateLeave(form.value); res = await updateLeave(form.value).finally(() => (buttonLoading.value = false));
} else { } else {
res = await addLeave(form.value); res = await addLeave(form.value).finally(() => (buttonLoading.value = false));
} }
form.value = res.data; form.value = res.data;
if (status === 'draft') { if (status === 'draft') {
@ -263,7 +264,9 @@ const handleStartWorkFlow = async (data: LeaveForm) => {
submitFormData.value.businessId = data.id; submitFormData.value.businessId = data.id;
// //
taskVariables.value = { taskVariables.value = {
// leave2/6 使
leaveDays: data.leaveDays, leaveDays: data.leaveDays,
// leave4/5 使
userList: ['1', '3', '4'] userList: ['1', '3', '4']
}; };
submitFormData.value.variables = taskVariables.value; submitFormData.value.variables = taskVariables.value;
@ -285,30 +288,10 @@ const submitCallback = async () => {
await proxy.$tab.closePage(proxy.$route); await proxy.$tab.closePage(proxy.$route);
proxy.$router.go(-1); proxy.$router.go(-1);
}; };
//
const goBack = () => {
proxy.$tab.closePage(proxy.$route);
proxy.$router.go(-1);
};
// //
const approvalVerifyOpen = async () => { const approvalVerifyOpen = async () => {
submitVerifyRef.value.openDialog(routeParams.value.taskId); 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(() => { onMounted(() => {
nextTick(async () => { nextTick(async () => {

View File

@ -4,7 +4,7 @@
</div> </div>
</template> </template>
<script setup name="WarmFlow"> <script setup name="WarmFlow" lang="ts">
const { proxy } = getCurrentInstance(); const { proxy } = getCurrentInstance();
import { onMounted } from 'vue'; import { onMounted } from 'vue';
import { getToken } from '@/utils/auth'; import { getToken } from '@/utils/auth';
@ -24,12 +24,12 @@ const iframeLoaded = () => {
}; };
}; };
const open = async (definitionId, disabled) => { const open = async (definitionId, disabled) => {
let url = baseUrl + `/warm-flow-ui/index.html?id=${definitionId}&disabled=${disabled}`; const url = baseUrl + `/warm-flow-ui/index.html?id=${definitionId}&disabled=${disabled}`;
iframeUrl.value = url + '&Authorization=Bearer ' + getToken() + '&clientid=' + import.meta.env.VITE_APP_CLIENT_ID; iframeUrl.value = url + '&Authorization=Bearer ' + getToken() + '&clientid=' + import.meta.env.VITE_APP_CLIENT_ID;
}; };
/** 关闭按钮 */ /** 关闭按钮 */
function close() { function close() {
const obj = { path: '/workflow/processDefinition', query: {activeName: proxy.$route.query.activeName}}; const obj = { path: '/workflow/processDefinition', query: { activeName: proxy.$route.query.activeName } };
proxy.$tab.closeOpenPage(obj); proxy.$tab.closeOpenPage(obj);
} }

View File

@ -197,7 +197,7 @@ import { categoryTree } from '@/api/workflow/category';
import { CategoryTreeVO } from '@/api/workflow/category/types'; import { CategoryTreeVO } from '@/api/workflow/category/types';
import { FlowDefinitionQuery, FlowDefinitionVo, FlowDefinitionForm } from '@/api/workflow/definition/types'; import { FlowDefinitionQuery, FlowDefinitionVo, FlowDefinitionForm } from '@/api/workflow/definition/types';
import { UploadRequestOptions, TabsPaneContext } from 'element-plus'; import { UploadRequestOptions, TabsPaneContext } from 'element-plus';
import { ElMessageBoxOptions } from "element-plus/es/components/message-box/src/message-box.type"; import { ElMessageBoxOptions } from 'element-plus/es/components/message-box/src/message-box.type';
const { proxy } = getCurrentInstance() as ComponentInternalInstance; const { proxy } = getCurrentInstance() as ComponentInternalInstance;
@ -326,7 +326,7 @@ const handleSelectionChange = (selection: any) => {
}; };
// //
const getPageList = async () => { const getPageList = async () => {
let query = proxy.$route.query; const query = proxy.$route.query;
if (query.activeName) { if (query.activeName) {
activeName.value = query.activeName; activeName.value = query.activeName;
} }
@ -411,7 +411,7 @@ const handlerBeforeUpload = () => {
}; };
// //
const handlerImportDefinition = (data: UploadRequestOptions): XMLHttpRequest => { const handlerImportDefinition = (data: UploadRequestOptions): XMLHttpRequest => {
let formData = new FormData(); const formData = new FormData();
uploadDialogLoading.value = true; uploadDialogLoading.value = true;
formData.append('file', data.file); formData.append('file', data.file);
formData.append('category', selectCategory.value); formData.append('category', selectCategory.value);
@ -466,6 +466,9 @@ const reset = () => {
*/ */
const handleAdd = async () => { const handleAdd = async () => {
reset(); reset();
if (queryParams.value.category != '') {
form.value.category = queryParams.value.category;
}
modelDialog.visible = true; modelDialog.visible = true;
modelDialog.title = '新增流程'; modelDialog.title = '新增流程';
}; };

View File

@ -352,7 +352,7 @@ const handleInvalid = async (row: FlowInstanceVO) => {
await proxy?.$modal.confirm('是否确认作废?'); await proxy?.$modal.confirm('是否确认作废?');
loading.value = true; loading.value = true;
if ('running' === tab.value) { if ('running' === tab.value) {
let param = { const param = {
id: row.id, id: row.id,
comment: deleteReason.value comment: deleteReason.value
}; };
@ -381,7 +381,7 @@ const handleInstanceVariable = async (row: FlowInstanceVO) => {
variableLoading.value = true; variableLoading.value = true;
variableVisible.value = true; variableVisible.value = true;
processDefinitionName.value = row.flowName; processDefinitionName.value = row.flowName;
let data = await instanceVariable(row.id); const data = await instanceVariable(row.id);
variables.value = data.data.variable; variables.value = data.data.variable;
variableLoading.value = false; variableLoading.value = false;
}; };

View File

@ -227,7 +227,8 @@ const handleView = (row) => {
taskId: row.id, taskId: row.id,
type: 'view', type: 'view',
formCustom: row.formCustom, formCustom: row.formCustom,
formPath: row.formPath formPath: row.formPath,
instanceId: row.instanceId
}); });
workflowCommon.routerJump(routerJumpVo, proxy); workflowCommon.routerJump(routerJumpVo, proxy);
}; };

View File

@ -222,7 +222,7 @@ const handleCancelProcessApply = async (businessId: string) => {
await proxy?.$modal.confirm('是否确认撤销当前单据?'); await proxy?.$modal.confirm('是否确认撤销当前单据?');
loading.value = true; loading.value = true;
if ('running' === tab.value) { if ('running' === tab.value) {
let data = { const data = {
businessId: businessId, businessId: businessId,
message: '申请人撤销流程!' message: '申请人撤销流程!'
}; };