Compare commits
24 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
70f7c06e55 | ||
![]() |
369f48ced5 | ||
![]() |
7f15f0e15a | ||
![]() |
7b48bd44a2 | ||
![]() |
7affcd27b7 | ||
![]() |
afc35feb8c | ||
![]() |
84d682a4a2 | ||
![]() |
b29c5bd2fa | ||
![]() |
e4c24a511a | ||
![]() |
9955a52059 | ||
![]() |
de22609196 | ||
![]() |
e5de3f4e9d | ||
![]() |
660d5b3d4f | ||
![]() |
d5eac17097 | ||
![]() |
6fe2317681 | ||
![]() |
e9e8a2eaaf | ||
![]() |
5ec984ac7d | ||
![]() |
c98a14e2ac | ||
![]() |
bbc656a26c | ||
![]() |
722acf0ae7 | ||
![]() |
15acd995f9 | ||
![]() |
35b90aa746 | ||
![]() |
de926211ef | ||
![]() |
30e1ea1c6d |
@ -315,6 +315,9 @@
|
||||
"watchThrottled": true,
|
||||
"watchTriggerable": true,
|
||||
"watchWithFilter": true,
|
||||
"whenever": true
|
||||
"whenever": true,
|
||||
"Slot": true,
|
||||
"Slots": true,
|
||||
"createRef": true
|
||||
}
|
||||
}
|
||||
|
19
README.md
19
README.md
@ -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) 版本。
|
||||
- 成员项目: 基于 vben5(ant-design-vue) 的前端项目 [ruoyi-plus-vben5](https://gitee.com/dapppp/ruoyi-plus-vben5)
|
||||
- 配套后端代码仓库地址
|
||||
- [RuoYi-Vue-Plus 5.X(注意版本号)](https://gitee.com/dromara/RuoYi-Vue-Plus)
|
||||
- [RuoYi-Cloud-Plus 2.X(注意版本号)](https://gitee.com/dromara/RuoYi-Cloud-Plus)
|
||||
- 成员项目: 基于soybean 的前端项目 [ruoyi-plus-soybean](https://gitee.com/xlsea/ruoyi-plus-soybean)
|
||||
|
||||
## 配套后端代码仓库地址
|
||||
|
||||
| 介绍 | 项目名 | 项目地址 |
|
||||
|------------|:-----------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| 🔥 分布式集群框架 | 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
|
||||
# 克隆项目
|
||||
git clone https://gitee.com/JavaLionLi/plus-ui.git
|
||||
|
||||
# 安装依赖
|
||||
npm install --registry=https://registry.npmmirror.com
|
||||
|
||||
|
47
package.json
47
package.json
@ -23,31 +23,31 @@
|
||||
"@element-plus/icons-vue": "2.3.1",
|
||||
"@highlightjs/vue-plugin": "2.1.0",
|
||||
"@vueup/vue-quill": "1.2.0",
|
||||
"@vueuse/core": "12.7.0",
|
||||
"@vueuse/core": "13.1.0",
|
||||
"animate.css": "4.1.1",
|
||||
"await-to-js": "3.0.0",
|
||||
"axios": "1.7.8",
|
||||
"axios": "1.8.4",
|
||||
"crypto-js": "4.2.0",
|
||||
"echarts": "5.5.0",
|
||||
"element-plus": "2.8.8",
|
||||
"echarts": "5.6.0",
|
||||
"element-plus": "2.9.8",
|
||||
"file-saver": "2.0.5",
|
||||
"highlight.js": "11.9.0",
|
||||
"image-conversion": "2.1.1",
|
||||
"js-cookie": "3.0.5",
|
||||
"jsencrypt": "3.3.2",
|
||||
"nprogress": "0.2.0",
|
||||
"pinia": "2.2.6",
|
||||
"pinia": "3.0.2",
|
||||
"screenfull": "6.0.2",
|
||||
"vue": "3.5.13",
|
||||
"vue-cropper": "1.1.1",
|
||||
"vue-i18n": "10.0.5",
|
||||
"vue-i18n": "11.1.3",
|
||||
"vue-json-pretty": "2.4.0",
|
||||
"vue-router": "4.4.5",
|
||||
"vue-types": "5.1.3",
|
||||
"vxe-table": "4.5.22"
|
||||
"vue-router": "4.5.0",
|
||||
"vue-types": "6.0.0",
|
||||
"vxe-table": "4.13.7"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@iconify/json": "2.2.276",
|
||||
"@iconify/json": "^2.2.276",
|
||||
"@types/crypto-js": "4.2.2",
|
||||
"@types/file-saver": "2.0.7",
|
||||
"@types/js-cookie": "3.0.6",
|
||||
@ -56,8 +56,8 @@
|
||||
"@unocss/preset-attributify": "66.0.0",
|
||||
"@unocss/preset-icons": "66.0.0",
|
||||
"@unocss/preset-uno": "66.0.0",
|
||||
"@vitejs/plugin-vue": "5.2.1",
|
||||
"@vue/compiler-sfc": "3.4.23",
|
||||
"@vitejs/plugin-vue": "5.2.3",
|
||||
"@vue/compiler-sfc": "3.5.13",
|
||||
"@vue/eslint-config-prettier": "10.2.0",
|
||||
"@vue/eslint-config-typescript": "14.4.0",
|
||||
"autoprefixer": "10.4.20",
|
||||
@ -66,19 +66,22 @@
|
||||
"eslint-plugin-vue": "9.32.0",
|
||||
"globals": "16.0.0",
|
||||
"prettier": "3.5.2",
|
||||
"sass": "1.84.0",
|
||||
"typescript": "~5.7.3",
|
||||
"sass": "1.87.0",
|
||||
"typescript": "~5.8.3",
|
||||
"unocss": "66.0.0",
|
||||
"unplugin-auto-import": "0.17.5",
|
||||
"unplugin-icons": "0.18.5",
|
||||
"unplugin-vue-components": "28.0.0",
|
||||
"unplugin-auto-import": "19.1.2",
|
||||
"unplugin-icons": "22.1.0",
|
||||
"unplugin-vue-components": "28.5.0",
|
||||
"unplugin-vue-setup-extend-plus": "1.0.1",
|
||||
"vite": "5.4.11",
|
||||
"vite": "6.3.2",
|
||||
"vite-plugin-compression": "0.5.1",
|
||||
"vite-plugin-svg-icons-ng": "^1.2.2",
|
||||
"vite-plugin-vue-devtools": "7.7.1",
|
||||
"vitest": "3.0.5",
|
||||
"vue-tsc": "^2.2.2"
|
||||
"vite-plugin-svg-icons-ng": "^1.4.0",
|
||||
"vite-plugin-vue-devtools": "7.7.5",
|
||||
"vitest": "3.1.2",
|
||||
"vue-tsc": "^2.2.8"
|
||||
},
|
||||
"overrides": {
|
||||
"quill": "2.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.18.0",
|
||||
|
@ -1,6 +1,6 @@
|
||||
import request from '@/utils/request';
|
||||
import { AxiosPromise } from 'axios';
|
||||
import {DeptForm, DeptQuery, DeptTreeVO, DeptVO} from './types';
|
||||
import { DeptForm, DeptQuery, DeptTreeVO, DeptVO } from './types';
|
||||
|
||||
// 查询部门列表
|
||||
export const listDept = (query?: DeptQuery) => {
|
||||
|
@ -1,4 +1,4 @@
|
||||
import {DeptTreeVO, DeptVO} from './../dept/types';
|
||||
import { DeptTreeVO, DeptVO } from './../dept/types';
|
||||
import { RoleVO } from '@/api/system/role/types';
|
||||
import request from '@/utils/request';
|
||||
import { AxiosPromise } from 'axios';
|
||||
|
@ -26,7 +26,7 @@
|
||||
z-index: 1001;
|
||||
overflow: hidden;
|
||||
-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
|
||||
.horizontal-collapse-transition {
|
||||
|
@ -44,7 +44,7 @@ const findPathNum = (str, char = '/') => {
|
||||
return str.split(char).length - 1;
|
||||
};
|
||||
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) {
|
||||
matched.push(data);
|
||||
if (data.children && pathList.length) {
|
||||
|
@ -95,7 +95,7 @@ const options = ref<any>({
|
||||
});
|
||||
|
||||
const styles = computed(() => {
|
||||
let style: any = {};
|
||||
const style: any = {};
|
||||
if (props.minHeight) {
|
||||
style.minHeight = `${props.minHeight}px`;
|
||||
}
|
||||
@ -121,9 +121,9 @@ const handleUploadSuccess = (res: any) => {
|
||||
// 如果上传成功
|
||||
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为服务器返回的图片链接地址
|
||||
quill.insertEmbed(length, 'image', res.data.url);
|
||||
// 调整光标到最后
|
||||
|
@ -176,7 +176,7 @@ const handleUploadSuccess = (res: any, file: UploadFile) => {
|
||||
|
||||
// 删除文件
|
||||
const handleDelete = (index: number) => {
|
||||
let ossId = fileList.value[index].ossId;
|
||||
const ossId = fileList.value[index].ossId;
|
||||
delOss(ossId);
|
||||
fileList.value.splice(index, 1);
|
||||
emit('update:modelValue', listToString(fileList.value));
|
||||
|
@ -27,7 +27,7 @@ const realSrc = computed(() => {
|
||||
if (!props.src) {
|
||||
return;
|
||||
}
|
||||
let real_src = props.src.split(',')[0];
|
||||
const real_src = props.src.split(',')[0];
|
||||
return real_src;
|
||||
});
|
||||
|
||||
@ -35,8 +35,8 @@ const realSrcList = computed(() => {
|
||||
if (!props.src) {
|
||||
return [];
|
||||
}
|
||||
let real_src_list = props.src.split(',');
|
||||
let srcList: string[] = [];
|
||||
const real_src_list = props.src.split(',');
|
||||
const srcList: string[] = [];
|
||||
real_src_list.forEach((item: string) => {
|
||||
if (item.trim() === '') {
|
||||
return;
|
||||
|
@ -189,7 +189,7 @@ const handleUploadSuccess = (res: any, file: UploadFile) => {
|
||||
const handleDelete = (file: UploadFile): boolean => {
|
||||
const findex = fileList.value.map((f) => f.name).indexOf(file.name);
|
||||
if (findex > -1 && uploadList.value.length === number.value) {
|
||||
let ossId = fileList.value[findex].ossId;
|
||||
const ossId = fileList.value[findex].ossId;
|
||||
delOss(ossId);
|
||||
fileList.value.splice(findex, 1);
|
||||
emit('update:modelValue', listToString(fileList.value));
|
||||
@ -225,7 +225,7 @@ const handlePictureCardPreview = (file: any) => {
|
||||
const listToString = (list: any[], separator?: string) => {
|
||||
let strs = '';
|
||||
separator = separator || ',';
|
||||
for (let i in list) {
|
||||
for (const i in list) {
|
||||
if (undefined !== list[i].ossId && list[i].url.indexOf('blob:') !== 0) {
|
||||
strs += list[i].ossId + separator;
|
||||
}
|
||||
|
56
src/components/Process/approvalButton.vue
Normal file
56
src/components/Process/approvalButton.vue
Normal 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>
|
@ -8,10 +8,10 @@
|
||||
<el-checkbox value="3" name="type">短信</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</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" />
|
||||
</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-tag v-for="user in selectCopyUserList" :key="user.userId" closable style="margin: 2px" @close="handleCopyCloseTag(user)">
|
||||
{{ user.nickName }}
|
||||
|
@ -47,11 +47,11 @@ const routers = computed(() => permissionStore.getTopbarRoutes());
|
||||
|
||||
// 顶部显示菜单
|
||||
const topMenus = computed(() => {
|
||||
let topMenus: RouteRecordRaw[] = [];
|
||||
const topMenus: RouteRecordRaw[] = [];
|
||||
routers.value.map((menu) => {
|
||||
if (menu.hidden !== true) {
|
||||
// 兼容顶部栏一级菜单内部跳转
|
||||
if (menu.path === '/') {
|
||||
if (menu.path === '/' && menu.children) {
|
||||
topMenus.push(menu.children ? menu.children[0] : menu);
|
||||
} else {
|
||||
topMenus.push(menu);
|
||||
@ -63,7 +63,7 @@ const topMenus = computed(() => {
|
||||
|
||||
// 设置子路由
|
||||
const childrenMenus = computed(() => {
|
||||
let childrenMenus: RouteRecordRaw[] = [];
|
||||
const childrenMenus: RouteRecordRaw[] = [];
|
||||
routers.value.map((router) => {
|
||||
router.children?.forEach((item) => {
|
||||
if (item.parentPath === undefined) {
|
||||
@ -118,7 +118,7 @@ const handleSelect = (key: string) => {
|
||||
// 没有子路由路径内部打开
|
||||
const routeMenu = childrenMenus.value.find((item) => item.path === key);
|
||||
if (routeMenu && routeMenu.query) {
|
||||
let query = JSON.parse(routeMenu.query);
|
||||
const query = JSON.parse(routeMenu.query);
|
||||
router.push({ path: key, query: query });
|
||||
} else {
|
||||
router.push({ path: key });
|
||||
@ -132,7 +132,7 @@ const handleSelect = (key: string) => {
|
||||
};
|
||||
|
||||
const activeRoutes = (key: string) => {
|
||||
let routes: RouteRecordRaw[] = [];
|
||||
const routes: RouteRecordRaw[] = [];
|
||||
if (childrenMenus.value && childrenMenus.value.length > 0) {
|
||||
childrenMenus.value.map((item) => {
|
||||
if (key == item.parentPath || (key == 'index' && '' == item.path)) {
|
||||
|
@ -1,147 +0,0 @@
|
||||
<template>
|
||||
<div class="el-tree-select">
|
||||
<el-select
|
||||
ref="treeSelect"
|
||||
v-model="valueId"
|
||||
style="width: 100%"
|
||||
:filterable="true"
|
||||
:clearable="true"
|
||||
:filter-method="selectFilterData as any"
|
||||
:placeholder="placeholder"
|
||||
@clear="clearHandle"
|
||||
>
|
||||
<el-option :value="valueId" :label="valueTitle">
|
||||
<el-tree
|
||||
id="tree-option"
|
||||
ref="selectTree"
|
||||
:accordion="accordion"
|
||||
:data="options"
|
||||
:props="objMap as any"
|
||||
:node-key="objMap.value"
|
||||
:expand-on-click-node="false"
|
||||
:default-expanded-keys="defaultExpandedKey"
|
||||
:filter-node-method="filterNode"
|
||||
@node-click="handleNodeClick"
|
||||
></el-tree>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
interface ObjMap {
|
||||
value: string;
|
||||
label: string;
|
||||
children: string;
|
||||
}
|
||||
interface Props {
|
||||
objMap: ObjMap;
|
||||
accordion: boolean;
|
||||
value: string | number;
|
||||
options: any[];
|
||||
placeholder: string;
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
objMap: () => {
|
||||
return {
|
||||
value: 'id',
|
||||
label: 'label',
|
||||
children: 'children'
|
||||
};
|
||||
},
|
||||
accordion: false,
|
||||
value: '',
|
||||
options: () => [],
|
||||
placeholder: ''
|
||||
});
|
||||
|
||||
const selectTree = ref<ElTreeSelectInstance>();
|
||||
|
||||
const emit = defineEmits(['update:value']);
|
||||
|
||||
const valueId = computed({
|
||||
get: () => props.value,
|
||||
set: (val) => {
|
||||
emit('update:value', val);
|
||||
}
|
||||
});
|
||||
const valueTitle = ref('');
|
||||
const defaultExpandedKey = ref<any[]>([]);
|
||||
|
||||
const initHandle = () => {
|
||||
nextTick(() => {
|
||||
const selectedValue = valueId.value;
|
||||
if (selectedValue !== null && typeof selectedValue !== 'undefined') {
|
||||
const node = selectTree.value?.getNode(selectedValue);
|
||||
if (node) {
|
||||
valueTitle.value = node.data[props.objMap.label];
|
||||
selectTree.value?.setCurrentKey(selectedValue); // 设置默认选中
|
||||
defaultExpandedKey.value = [selectedValue]; // 设置默认展开
|
||||
}
|
||||
} else {
|
||||
clearHandle();
|
||||
}
|
||||
});
|
||||
};
|
||||
const handleNodeClick = (node: any) => {
|
||||
valueTitle.value = node[props.objMap.label];
|
||||
valueId.value = node[props.objMap.value];
|
||||
defaultExpandedKey.value = [];
|
||||
selectTree.value?.blur();
|
||||
selectFilterData('');
|
||||
};
|
||||
const selectFilterData = (val: any) => {
|
||||
selectTree.value?.filter(val);
|
||||
};
|
||||
const filterNode = (value: any, data: any) => {
|
||||
if (!value) return true;
|
||||
return data[props.objMap['label']].indexOf(value) !== -1;
|
||||
};
|
||||
const clearHandle = () => {
|
||||
valueTitle.value = '';
|
||||
valueId.value = '';
|
||||
defaultExpandedKey.value = [];
|
||||
clearSelected();
|
||||
};
|
||||
const clearSelected = () => {
|
||||
const allNode = document.querySelectorAll('#tree-option .el-tree-node');
|
||||
allNode.forEach((element) => element.classList.remove('is-current'));
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
initHandle();
|
||||
});
|
||||
|
||||
watch(valueId, () => {
|
||||
initHandle();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '@/assets/styles/variables.module.scss';
|
||||
|
||||
.el-scrollbar .el-scrollbar__view .el-select-dropdown__item {
|
||||
padding: 0;
|
||||
background-color: #fff;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.el-select-dropdown__item.selected {
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
ul li .el-tree .el-tree-node__content {
|
||||
height: auto;
|
||||
padding: 0 20px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
:deep(.el-tree-node__content:hover),
|
||||
:deep(.el-tree-node__content:active),
|
||||
:deep(.is-current > div:first-child),
|
||||
:deep(.el-tree-node__content:focus) {
|
||||
background-color: mix(#fff, $--color-primary, 90%);
|
||||
color: $--color-primary;
|
||||
}
|
||||
</style>
|
@ -40,16 +40,16 @@ watch(
|
||||
);
|
||||
|
||||
onMounted(() => {
|
||||
addIframe()
|
||||
})
|
||||
addIframe();
|
||||
});
|
||||
|
||||
watchEffect((route) => {
|
||||
addIframe()
|
||||
})
|
||||
watchEffect(() => {
|
||||
addIframe();
|
||||
});
|
||||
|
||||
function addIframe() {
|
||||
if (route.meta.link) {
|
||||
useTagsViewStore().addIframeView(route)
|
||||
useTagsViewStore().addIframeView(route);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
@ -18,7 +18,7 @@ const tagsViewStore = useTagsViewStore();
|
||||
|
||||
function iframeUrl(url: string | undefined, query: any) {
|
||||
if (Object.keys(query).length > 0) {
|
||||
let params = Object.keys(query)
|
||||
const params = Object.keys(query)
|
||||
.map((key) => key + '=' + query[key])
|
||||
.join('&');
|
||||
return url + '?' + params;
|
||||
|
@ -33,7 +33,7 @@
|
||||
<el-popover placement="bottom" trigger="click" transition="el-zoom-in-top" :width="300" :persistent="false">
|
||||
<template #reference>
|
||||
<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>
|
||||
</template>
|
||||
<template #default>
|
||||
@ -98,7 +98,7 @@ import { dynamicClear, dynamicTenant } from '@/api/system/tenant';
|
||||
import { TenantVO } from '@/api/types';
|
||||
import notice from './notice/index.vue';
|
||||
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 userStore = useUserStore();
|
||||
@ -171,6 +171,7 @@ const logout = async () => {
|
||||
redirect: encodeURIComponent(router.currentRoute.value.fullPath || '/')
|
||||
}
|
||||
});
|
||||
proxy?.$tab.closeAllPage();
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -86,7 +86,7 @@ const resolvePath = (routePath: string, routeQuery?: string): any => {
|
||||
return props.basePath;
|
||||
}
|
||||
if (routeQuery) {
|
||||
let query = JSON.parse(routeQuery);
|
||||
const query = JSON.parse(routeQuery);
|
||||
return { path: getNormalPath(props.basePath + '/' + routePath), query: query };
|
||||
}
|
||||
return getNormalPath(props.basePath + '/' + routePath);
|
||||
|
@ -63,9 +63,9 @@ const loginByCode = async (data: LoginData) => {
|
||||
|
||||
const init = async () => {
|
||||
// 如果域名不相等 则重定向处理
|
||||
let host = window.location.host;
|
||||
const host = window.location.host;
|
||||
if (domain !== host) {
|
||||
let urlFull = new URL(window.location.href);
|
||||
const urlFull = new URL(window.location.href);
|
||||
urlFull.host = domain;
|
||||
window.location.href = urlFull.toString();
|
||||
return;
|
||||
|
@ -67,7 +67,7 @@ const closeSearch = () => {
|
||||
};
|
||||
// 菜单搜索数据过滤
|
||||
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;
|
||||
});
|
||||
cb(options);
|
||||
|
@ -24,10 +24,9 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts" name="layoutBreadcrumbUserNews">
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { useNoticeStore } from '@/store/modules/notice';
|
||||
|
||||
const noticeStore = storeToRefs(useNoticeStore());
|
||||
const noticeStore = useNoticeStore();
|
||||
const { readAll } = useNoticeStore();
|
||||
|
||||
// 定义变量内容
|
||||
@ -42,7 +41,7 @@ const newsList = ref([]) as any;
|
||||
*/
|
||||
const getTableData = async () => {
|
||||
state.loading = true;
|
||||
newsList.value = noticeStore.state.value.notices;
|
||||
newsList.value = noticeStore.state.notices;
|
||||
state.loading = false;
|
||||
};
|
||||
|
||||
@ -50,7 +49,7 @@ const getTableData = async () => {
|
||||
const onNewsClick = (item: any) => {
|
||||
newsList.value[item].read = true;
|
||||
//并且写入pinia
|
||||
noticeStore.state.value.notices = newsList.value;
|
||||
noticeStore.state.notices = newsList.value;
|
||||
};
|
||||
|
||||
// 前往通知中心点击
|
||||
|
@ -34,7 +34,7 @@ import i18n from '@/lang/index';
|
||||
// vxeTable
|
||||
import VXETable from 'vxe-table';
|
||||
import 'vxe-table/lib/style.css';
|
||||
VXETable.config({
|
||||
VXETable.setConfig({
|
||||
zIndex: 999999
|
||||
});
|
||||
|
||||
|
@ -14,8 +14,8 @@ NProgress.configure({ showSpinner: false });
|
||||
const whiteList = ['/login', '/register', '/social-callback', '/register*', '/register/*'];
|
||||
|
||||
const isWhiteList = (path: string) => {
|
||||
return whiteList.some(pattern => isPathMatch(pattern, path))
|
||||
}
|
||||
return whiteList.some((pattern) => isPathMatch(pattern, path));
|
||||
};
|
||||
|
||||
router.beforeEach(async (to, from, next) => {
|
||||
NProgress.start();
|
||||
|
@ -93,104 +93,7 @@ export const constantRoutes: 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/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 }
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
];
|
||||
|
||||
/**
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { createPinia } from "pinia";
|
||||
import { createPinia } from 'pinia';
|
||||
|
||||
const store = createPinia();
|
||||
|
||||
|
@ -99,14 +99,14 @@ export const usePermissionStore = defineStore('permission', () => {
|
||||
};
|
||||
const filterChildren = (childrenMap: RouteRecordRaw[], lastRouter?: RouteRecordRaw): RouteRecordRaw[] => {
|
||||
let children: RouteRecordRaw[] = [];
|
||||
childrenMap.forEach(el => {
|
||||
childrenMap.forEach((el) => {
|
||||
el.path = lastRouter ? lastRouter.path + '/' + el.path : el.path;
|
||||
if (el.children && el.children.length && el.component?.toString() === 'ParentView') {
|
||||
children = children.concat(filterChildren(el.children, el));
|
||||
} else {
|
||||
children.push(el);
|
||||
}
|
||||
})
|
||||
});
|
||||
return children;
|
||||
};
|
||||
return {
|
||||
|
@ -5,7 +5,6 @@ import { useStorage } from '@vueuse/core';
|
||||
import { ref } from 'vue';
|
||||
|
||||
export const useSettingsStore = defineStore('setting', () => {
|
||||
// @ts-ignore
|
||||
const storageSetting = useStorage<LayoutSetting>('layout-setting', {
|
||||
topNav: defaultSettings.topNav,
|
||||
tagsView: defaultSettings.tagsView,
|
||||
|
1
src/types/module.d.ts
vendored
1
src/types/module.d.ts
vendored
@ -48,4 +48,3 @@ export type ObjKeysToUnion<T, P extends string = ''> = T extends object
|
||||
[K in keyof T]: ObjKeysToUnion<T[K], P extends '' ? `${K & string}` : `${P}.${K & string}`>;
|
||||
}[keyof T]
|
||||
: P;
|
||||
|
||||
|
@ -191,7 +191,8 @@ export function download(url: string, params: any, fileName: string) {
|
||||
const blob = new Blob([resp]);
|
||||
FileSaver.saveAs(blob, fileName);
|
||||
} else {
|
||||
const resText = await resp.data.text();
|
||||
const blob = new Blob([resp]);
|
||||
const resText = await blob.text();
|
||||
const rspObj = JSON.parse(resText);
|
||||
const errMsg = errorCode[rspObj.code] || rspObj.msg || errorCode['default'];
|
||||
ElMessage.error(errMsg);
|
||||
|
@ -178,11 +178,11 @@ export const handleTree = <T>(data: any[], id?: string, parentId?: string, child
|
||||
|
||||
for (const d of data) {
|
||||
const parentId = d[config.parentId];
|
||||
const parentObj = childrenListMap[parentId]
|
||||
const parentObj = childrenListMap[parentId];
|
||||
if (!parentObj) {
|
||||
tree.push(d);
|
||||
} else {
|
||||
parentObj[config.childrenList].push(d)
|
||||
parentObj[config.childrenList].push(d);
|
||||
}
|
||||
}
|
||||
return tree;
|
||||
|
@ -22,7 +22,7 @@
|
||||
<script setup lang="ts">
|
||||
import errImage from '@/assets/401_images/401.gif';
|
||||
|
||||
let { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||
|
||||
const errGif = ref(errImage + '?' + +new Date());
|
||||
|
||||
|
@ -22,7 +22,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
let message = computed(() => {
|
||||
const message = computed(() => {
|
||||
return '找不到网页!';
|
||||
});
|
||||
</script>
|
||||
|
@ -26,7 +26,7 @@
|
||||
* 文件存储 七牛、阿里、腾讯 云存储<br />
|
||||
* 监控框架 SpringBoot-Admin 全方位服务监控<br />
|
||||
* 校验框架 Validation 增强接口安全性 严谨性<br />
|
||||
* Excel框架 Alibaba EasyExcel 性能优异 扩展性强<br />
|
||||
* Excel框架 FastExcel(原Alibaba EasyExcel) 性能优异 扩展性强<br />
|
||||
* 文档框架 SpringDoc、javadoc 无注解零入侵基于java注释<br />
|
||||
* 工具类框架 Hutool、Lombok 减少代码冗余 增加安全性<br />
|
||||
* 代码生成器 适配MP、SpringDoc规范化代码 一键生成前后端代码<br />
|
||||
|
@ -260,10 +260,9 @@ onMounted(() => {
|
||||
background: #ffffff;
|
||||
width: 400px;
|
||||
padding: 25px 25px 5px 25px;
|
||||
|
||||
z-index: 1;
|
||||
.el-input {
|
||||
height: 40px;
|
||||
|
||||
input {
|
||||
height: 40px;
|
||||
}
|
||||
|
@ -203,7 +203,6 @@ onMounted(() => {
|
||||
line-height: 0;
|
||||
color: #7483a3;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.register-form {
|
||||
|
@ -300,7 +300,7 @@ const handleExport = () => {
|
||||
|
||||
/** 状态修改 */
|
||||
const handleStatusChange = async (row: ClientVO) => {
|
||||
let text = row.status === '0' ? '启用' : '停用';
|
||||
const text = row.status === '0' ? '启用' : '停用';
|
||||
try {
|
||||
await proxy?.$modal.confirm('确认要"' + text + '"吗?');
|
||||
await changeStatus(row.clientId, row.status);
|
||||
|
@ -87,10 +87,18 @@
|
||||
<el-input v-model="form.configKey" placeholder="请输入配置key" />
|
||||
</el-form-item>
|
||||
<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 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 label="accessKey" prop="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 protocol = computed(() => (form.value.isHttps === 'Y' ? 'https://' : 'http://'));
|
||||
|
||||
/** 查询对象存储配置列表 */
|
||||
const getList = async () => {
|
||||
loading.value = true;
|
||||
@ -306,7 +316,7 @@ const submitForm = () => {
|
||||
};
|
||||
/** 状态修改 */
|
||||
const handleStatusChange = async (row: OssConfigVO) => {
|
||||
let text = row.status === '0' ? '启用' : '停用';
|
||||
const text = row.status === '0' ? '启用' : '停用';
|
||||
try {
|
||||
await proxy?.$modal.confirm('确认要"' + text + '""' + row.configKey + '"配置吗?');
|
||||
await changeOssConfigStatus(row.ossConfigId, row.status, row.configKey);
|
||||
|
@ -255,9 +255,9 @@ const handleHeaderCLick = (column: any) => {
|
||||
handleOrderChange(column.property, column.multiOrder);
|
||||
};
|
||||
const handleOrderChange = (prop: string, order: string) => {
|
||||
let orderByArr = queryParams.value.orderByColumn ? queryParams.value.orderByColumn.split(',') : [];
|
||||
let isAscArr = queryParams.value.isAsc ? queryParams.value.isAsc.split(',') : [];
|
||||
let propIndex = orderByArr.indexOf(prop);
|
||||
const orderByArr = queryParams.value.orderByColumn ? queryParams.value.orderByColumn.split(',') : [];
|
||||
const isAscArr = queryParams.value.isAsc ? queryParams.value.isAsc.split(',') : [];
|
||||
const propIndex = orderByArr.indexOf(prop);
|
||||
if (propIndex !== -1) {
|
||||
if (order) {
|
||||
//排序里已存在 只修改排序
|
||||
@ -306,7 +306,7 @@ const handleDownload = (row: OssVO) => {
|
||||
};
|
||||
/** 预览开关按钮 */
|
||||
const handlePreviewListResource = async (preview: boolean) => {
|
||||
let text = preview ? '启用' : '停用';
|
||||
const text = preview ? '启用' : '停用';
|
||||
try {
|
||||
await proxy?.$modal.confirm('确认要"' + text + '""预览列表图片"配置吗?');
|
||||
await proxy?.updateConfigByKey('sys.oss.previewListResource', preview);
|
||||
|
@ -323,7 +323,7 @@ const handleSelectionChange = (selection: RoleVO[]) => {
|
||||
|
||||
/** 角色状态修改 */
|
||||
const handleStatusChange = async (row: RoleVO) => {
|
||||
let text = row.status === '0' ? '启用' : '停用';
|
||||
const text = row.status === '0' ? '启用' : '停用';
|
||||
try {
|
||||
await proxy?.$modal.confirm('确认要"' + text + '""' + row.roleName + '"角色吗?');
|
||||
await changeRoleStatus(row.roleId, row.status);
|
||||
@ -346,11 +346,11 @@ const getMenuTreeselect = async () => {
|
||||
/** 所有部门节点数据 */
|
||||
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) {
|
||||
checkedKeys?.unshift.apply(checkedKeys, halfCheckedKeys);
|
||||
checkedKeys?.unshift(...halfCheckedKeys);
|
||||
}
|
||||
return checkedKeys;
|
||||
};
|
||||
@ -404,14 +404,14 @@ const getRoleDeptTreeSelect = async (roleId: string | number) => {
|
||||
/** 树权限(展开/折叠)*/
|
||||
const handleCheckedTreeExpand = (value: boolean, type: string) => {
|
||||
if (type == 'menu') {
|
||||
let treeList = menuOptions.value;
|
||||
const treeList = menuOptions.value;
|
||||
for (let i = 0; i < treeList.length; i++) {
|
||||
if (menuRef.value) {
|
||||
menuRef.value.store.nodesMap[treeList[i].id].expanded = value;
|
||||
}
|
||||
}
|
||||
} else if (type == 'dept') {
|
||||
let treeList = deptOptions.value;
|
||||
const treeList = deptOptions.value;
|
||||
for (let i = 0; i < treeList.length; i++) {
|
||||
if (deptRef.value) {
|
||||
deptRef.value.store.nodesMap[treeList[i].id].expanded = value;
|
||||
@ -438,11 +438,11 @@ const handleCheckedTreeConnect = (value: any, type: string) => {
|
||||
/** 所有菜单节点数据 */
|
||||
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) {
|
||||
checkedKeys?.unshift.apply(checkedKeys, halfCheckedKeys);
|
||||
checkedKeys?.unshift(...halfCheckedKeys);
|
||||
}
|
||||
return checkedKeys;
|
||||
};
|
||||
|
@ -245,7 +245,7 @@ const getList = async () => {
|
||||
|
||||
// 租户套餐状态修改
|
||||
const handleStatusChange = async (row: TenantVO) => {
|
||||
let text = row.status === '0' ? '启用' : '停用';
|
||||
const text = row.status === '0' ? '启用' : '停用';
|
||||
try {
|
||||
await proxy?.$modal.confirm('确认要"' + text + '""' + row.companyName + '"租户吗?');
|
||||
await changeTenantStatus(row.id, row.tenantId, row.status);
|
||||
@ -361,7 +361,7 @@ const handleExport = () => {
|
||||
/**同步租户字典*/
|
||||
const handleSyncTenantDict = async () => {
|
||||
await proxy?.$modal.confirm('确认要同步所有租户字典吗?');
|
||||
let res = await syncTenantDict();
|
||||
const res = await syncTenantDict();
|
||||
proxy?.$modal.msgSuccess(res.msg);
|
||||
};
|
||||
|
||||
|
@ -167,11 +167,11 @@ const getMenuTreeselect = async () => {
|
||||
// 所有菜单节点数据
|
||||
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) {
|
||||
checkedKeys?.unshift.apply(checkedKeys, halfCheckedKeys);
|
||||
checkedKeys?.unshift(...halfCheckedKeys);
|
||||
}
|
||||
return checkedKeys;
|
||||
};
|
||||
@ -194,7 +194,7 @@ const getList = async () => {
|
||||
|
||||
// 租户套餐状态修改
|
||||
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>);
|
||||
if (err) {
|
||||
row.status = row.status === '0' ? '1' : '0';
|
||||
@ -241,7 +241,7 @@ const handleSelectionChange = (selection: TenantPkgVO[]) => {
|
||||
// 树权限(展开/折叠)
|
||||
const handleCheckedTreeExpand = (value: CheckboxValueType, type: string) => {
|
||||
if (type == 'menu') {
|
||||
let treeList = menuOptions.value;
|
||||
const treeList = menuOptions.value;
|
||||
for (let i = 0; i < treeList.length; i++) {
|
||||
if (menuTreeRef.value) {
|
||||
menuTreeRef.value.store.nodesMap[treeList[i].id].expanded = value as boolean;
|
||||
|
@ -33,7 +33,7 @@
|
||||
<span>{{ (pageNum - 1) * pageSize + scope.$index + 1 }}</span>
|
||||
</template>
|
||||
</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="roleName" />
|
||||
<el-table-column label="权限字符" align="center" prop="roleKey" />
|
||||
@ -80,8 +80,10 @@ const tableRef = ref<ElTableInstance>();
|
||||
|
||||
/** 单击选中行数据 */
|
||||
const clickRow = (row: RoleVO) => {
|
||||
row.flag = !row.flag;
|
||||
tableRef.value?.toggleRowSelection(row, row.flag);
|
||||
if (checkSelectable(row)) {
|
||||
row.flag = !row.flag;
|
||||
tableRef.value?.toggleRowSelection(row, row.flag);
|
||||
}
|
||||
};
|
||||
/** 多选框选中数据 */
|
||||
const handleSelectionChange = (selection: RoleVO[]) => {
|
||||
@ -91,6 +93,10 @@ const handleSelectionChange = (selection: RoleVO[]) => {
|
||||
const getRowKey = (row: RoleVO): string => {
|
||||
return String(row.roleId);
|
||||
};
|
||||
/** 检查角色状态 */
|
||||
const checkSelectable = (row: RoleVO): boolean => {
|
||||
return row.status === '0';
|
||||
};
|
||||
/** 关闭按钮 */
|
||||
const close = () => {
|
||||
const obj: RouteLocationNormalized = {
|
||||
|
@ -498,7 +498,7 @@ const handleDelete = async (row?: UserVO) => {
|
||||
|
||||
/** 用户状态修改 */
|
||||
const handleStatusChange = async (row: UserVO) => {
|
||||
let text = row.status === '0' ? '启用' : '停用';
|
||||
const text = row.status === '0' ? '启用' : '停用';
|
||||
try {
|
||||
await proxy?.$modal.confirm('确认要"' + text + '""' + row.userName + '"用户吗?');
|
||||
await api.changeUserStatus(row.userId, row.status);
|
||||
|
@ -134,7 +134,7 @@ const beforeUpload = (file: UploadRawFile): any => {
|
||||
/** 上传图片 */
|
||||
const uploadImg = async () => {
|
||||
cropper.value.getCropBlob(async (data: any) => {
|
||||
let formData = new FormData();
|
||||
const formData = new FormData();
|
||||
formData.append('avatarfile', data, options.fileName);
|
||||
const res = await uploadAvatar(formData);
|
||||
open.value = false;
|
||||
|
@ -113,8 +113,8 @@
|
||||
</template>
|
||||
|
||||
<script setup name="Gen" lang="ts">
|
||||
import {delTable, genCode, getDataNames, listTable, previewTable, synchDb} from '@/api/tool/gen';
|
||||
import {TableQuery, TableVO} from '@/api/tool/gen/types';
|
||||
import { delTable, genCode, getDataNames, listTable, previewTable, synchDb } from '@/api/tool/gen';
|
||||
import { TableQuery, TableVO } from '@/api/tool/gen/types';
|
||||
import router from '@/router';
|
||||
import ImportTable from './importTable.vue';
|
||||
|
||||
|
@ -34,7 +34,7 @@
|
||||
:default-expand-all="isExpandAll"
|
||||
: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="createTime" width="180" />
|
||||
<el-table-column label="操作" fixed="right" align="center" class-name="small-padding fixed-width">
|
||||
@ -77,7 +77,7 @@
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button :loading="buttonLoading" type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="cancel">取 消</el-button>
|
||||
@ -88,17 +88,16 @@
|
||||
</template>
|
||||
|
||||
<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';
|
||||
|
||||
type CategoryOption = {
|
||||
categoryId: number;
|
||||
categoryName: string;
|
||||
children?: CategoryOption[];
|
||||
}
|
||||
|
||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;;
|
||||
};
|
||||
|
||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||
|
||||
const categoryList = ref<CategoryVO[]>([]);
|
||||
const categoryOptions = ref<CategoryOption[]>([]);
|
||||
@ -109,32 +108,29 @@ const loading = ref(false);
|
||||
|
||||
const queryFormRef = ref<ElFormInstance>();
|
||||
const categoryFormRef = ref<ElFormInstance>();
|
||||
const categoryTableRef = ref<ElTableInstance>()
|
||||
const categoryTableRef = ref<ElTableInstance>();
|
||||
|
||||
const dialog = reactive<DialogOption>({
|
||||
visible: false,
|
||||
title: ''
|
||||
});
|
||||
|
||||
|
||||
const initFormData: CategoryForm = {
|
||||
categoryId: undefined,
|
||||
categoryName: "",
|
||||
categoryName: '',
|
||||
parentId: undefined,
|
||||
orderNum: 0,
|
||||
}
|
||||
orderNum: 0
|
||||
};
|
||||
|
||||
const data = reactive<PageData<CategoryForm, CategoryQuery>>({
|
||||
form: {...initFormData},
|
||||
form: { ...initFormData },
|
||||
queryParams: {
|
||||
categoryName: undefined,
|
||||
categoryName: undefined
|
||||
},
|
||||
rules: {
|
||||
categoryId: [
|
||||
{ required: true, message: "流程分类ID不能为空", trigger: "blur" }
|
||||
],
|
||||
parentId: [{ required: true, message: "请选择上级分类", trigger: "change" }],
|
||||
categoryName: [{ required: true, message: "请输入分类名称", trigger: "blur" }]
|
||||
categoryId: [{ required: true, message: '流程分类ID不能为空', trigger: 'blur' }],
|
||||
parentId: [{ required: true, message: '请选择上级分类', trigger: 'change' }],
|
||||
categoryName: [{ required: true, message: '请输入分类名称', trigger: 'blur' }]
|
||||
}
|
||||
});
|
||||
|
||||
@ -144,19 +140,19 @@ const { queryParams, form, rules } = toRefs(data);
|
||||
const getList = async () => {
|
||||
loading.value = true;
|
||||
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) {
|
||||
categoryList.value = data;
|
||||
loading.value = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/** 查询流程分类下拉树结构 */
|
||||
const getTreeselect = async () => {
|
||||
const res = await listCategory();
|
||||
categoryOptions.value = [];
|
||||
// 处理树形数据
|
||||
const data = proxy?.handleTree<CategoryOption>(res.data, "categoryId", "parentId");
|
||||
const data = proxy?.handleTree<CategoryOption>(res.data, 'categoryId', 'parentId');
|
||||
if (data) {
|
||||
categoryOptions.value = data; // 将处理后的树形数据赋值
|
||||
}
|
||||
@ -166,24 +162,24 @@ const getTreeselect = async () => {
|
||||
const cancel = () => {
|
||||
reset();
|
||||
dialog.visible = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 表单重置
|
||||
const reset = () => {
|
||||
form.value = {...initFormData}
|
||||
form.value = { ...initFormData };
|
||||
categoryFormRef.value?.resetFields();
|
||||
}
|
||||
};
|
||||
|
||||
/** 搜索按钮操作 */
|
||||
const handleQuery = () => {
|
||||
getList();
|
||||
}
|
||||
};
|
||||
|
||||
/** 重置按钮操作 */
|
||||
const resetQuery = () => {
|
||||
queryFormRef.value?.resetFields();
|
||||
handleQuery();
|
||||
}
|
||||
};
|
||||
|
||||
/** 新增按钮操作 */
|
||||
const handleAdd = (row?: CategoryVO) => {
|
||||
@ -195,22 +191,22 @@ const handleAdd = (row?: CategoryVO) => {
|
||||
form.value.parentId = undefined;
|
||||
}
|
||||
dialog.visible = true;
|
||||
dialog.title = "添加流程分类";
|
||||
}
|
||||
dialog.title = '添加流程分类';
|
||||
};
|
||||
|
||||
/** 展开/折叠操作 */
|
||||
const handleToggleExpandAll = () => {
|
||||
isExpandAll.value = !isExpandAll.value;
|
||||
toggleExpandAll(categoryList.value, isExpandAll.value)
|
||||
}
|
||||
toggleExpandAll(categoryList.value, isExpandAll.value);
|
||||
};
|
||||
|
||||
/** 展开/折叠操作 */
|
||||
const toggleExpandAll = (data: CategoryVO[], status: boolean) => {
|
||||
data.forEach((item) => {
|
||||
categoryTableRef.value?.toggleRowExpansion(item, status)
|
||||
if (item.children && item.children.length > 0) toggleExpandAll(item.children, status)
|
||||
})
|
||||
}
|
||||
categoryTableRef.value?.toggleRowExpansion(item, status);
|
||||
if (item.children && item.children.length > 0) toggleExpandAll(item.children, status);
|
||||
});
|
||||
};
|
||||
|
||||
/** 修改按钮操作 */
|
||||
const handleUpdate = async (row: CategoryVO) => {
|
||||
@ -222,8 +218,8 @@ const handleUpdate = async (row: CategoryVO) => {
|
||||
const res = await getCategory(row.categoryId);
|
||||
Object.assign(form.value, res.data);
|
||||
dialog.visible = true;
|
||||
dialog.title = "修改流程分类";
|
||||
}
|
||||
dialog.title = '修改流程分类';
|
||||
};
|
||||
|
||||
/** 提交按钮 */
|
||||
const submitForm = () => {
|
||||
@ -231,25 +227,25 @@ const submitForm = () => {
|
||||
if (valid) {
|
||||
buttonLoading.value = true;
|
||||
if (form.value.categoryId) {
|
||||
await updateCategory(form.value).finally(() => buttonLoading.value = false);
|
||||
await updateCategory(form.value).finally(() => (buttonLoading.value = false));
|
||||
} 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;
|
||||
getList();
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/** 删除按钮操作 */
|
||||
const handleDelete = async (row: CategoryVO) => {
|
||||
await proxy?.$modal.confirm('是否确认删除"' + row.categoryName + '"的分类?');
|
||||
loading.value = true;
|
||||
await delCategory(row.categoryId).finally(() => loading.value = false);
|
||||
await delCategory(row.categoryId).finally(() => (loading.value = false));
|
||||
await getList();
|
||||
proxy?.$modal.msgSuccess("删除成功");
|
||||
}
|
||||
proxy?.$modal.msgSuccess('删除成功');
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
getList();
|
||||
|
@ -222,7 +222,7 @@ const handleExport = () => {
|
||||
const handleCancelProcessApply = async (id: string) => {
|
||||
await proxy?.$modal.confirm('是否确认撤销当前单据?');
|
||||
loading.value = true;
|
||||
let data = {
|
||||
const data = {
|
||||
businessId: id,
|
||||
message: '申请人撤销流程!'
|
||||
};
|
||||
|
@ -1,17 +1,15 @@
|
||||
<template>
|
||||
<div class="p-2">
|
||||
<el-card shadow="never">
|
||||
<div style="display: flex; justify-content: space-between">
|
||||
<div>
|
||||
<el-button v-if="submitButtonShow" :loading="buttonLoading" type="info" @click="submitForm('draft')">暂存</el-button>
|
||||
<el-button v-if="submitButtonShow" :loading="buttonLoading" type="primary" @click="submitForm('submit')">提 交</el-button>
|
||||
<el-button v-if="approvalButtonShow" :loading="buttonLoading" type="primary" @click="approvalVerifyOpen">审批</el-button>
|
||||
<el-button v-if="form && form.id && form.status !== 'draft'" type="primary" @click="handleApprovalRecord">流程进度</el-button>
|
||||
</div>
|
||||
<div>
|
||||
<el-button style="float: right" @click="goBack()">返回</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<approvalButton
|
||||
@submitForm="submitForm"
|
||||
@approvalVerifyOpen="approvalVerifyOpen"
|
||||
@handleApprovalRecord="handleApprovalRecord"
|
||||
:buttonLoading="buttonLoading"
|
||||
:id="form.id"
|
||||
:status="form.status"
|
||||
:pageType="routeParams.type"
|
||||
/>
|
||||
</el-card>
|
||||
<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">
|
||||
@ -20,7 +18,7 @@
|
||||
<el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="请假时间">
|
||||
<el-form-item label="请假时间" required>
|
||||
<el-date-picker
|
||||
v-model="leaveTime"
|
||||
value-format="YYYY-MM-DD HH:mm:ss"
|
||||
@ -64,6 +62,7 @@ import { LeaveForm, LeaveQuery, LeaveVO } from '@/api/workflow/leave/types';
|
||||
import { startWorkFlow } from '@/api/workflow/task';
|
||||
import SubmitVerify from '@/components/Process/submitVerify.vue';
|
||||
import ApprovalRecord from '@/components/Process/approvalRecord.vue';
|
||||
import ApprovalButton from '@/components/Process/approvalButton.vue';
|
||||
import { AxiosResponse } from 'axios';
|
||||
import { StartProcessBo } from '@/api/workflow/workflowCommon/types';
|
||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||
@ -128,6 +127,8 @@ const dialogVisible = reactive<DialogOption>({
|
||||
const submitVerifyRef = ref<InstanceType<typeof SubmitVerify>>();
|
||||
//审批记录组件
|
||||
const approvalRecordRef = ref<InstanceType<typeof ApprovalRecord>>();
|
||||
//按钮组件
|
||||
const approvalButtonRef = ref<InstanceType<typeof ApprovalButton>>();
|
||||
|
||||
const leaveFormRef = ref<ElFormInstance>();
|
||||
|
||||
@ -212,9 +213,9 @@ const submitForm = (status: string) => {
|
||||
buttonLoading.value = true;
|
||||
let res: AxiosResponse<LeaveVO>;
|
||||
if (form.value.id) {
|
||||
res = await updateLeave(form.value);
|
||||
res = await updateLeave(form.value).finally(() => (buttonLoading.value = false));
|
||||
} else {
|
||||
res = await addLeave(form.value);
|
||||
res = await addLeave(form.value).finally(() => (buttonLoading.value = false));
|
||||
}
|
||||
form.value = res.data;
|
||||
if (status === 'draft') {
|
||||
@ -252,7 +253,9 @@ const handleStartWorkFlow = async (data: LeaveForm) => {
|
||||
submitFormData.value.businessId = data.id;
|
||||
//流程变量
|
||||
taskVariables.value = {
|
||||
// leave2/6 使用的流程变量
|
||||
leaveDays: data.leaveDays,
|
||||
// leave4/5 使用的流程变量
|
||||
userList: ['1', '3', '4']
|
||||
};
|
||||
submitFormData.value.variables = taskVariables.value;
|
||||
@ -274,12 +277,6 @@ const submitCallback = async () => {
|
||||
await proxy.$tab.closePage(proxy.$route);
|
||||
proxy.$router.go(-1);
|
||||
};
|
||||
|
||||
//返回
|
||||
const goBack = () => {
|
||||
proxy.$tab.closePage(proxy.$route);
|
||||
proxy.$router.go(-1);
|
||||
};
|
||||
//审批
|
||||
const approvalVerifyOpen = async () => {
|
||||
submitVerifyRef.value.openDialog(routeParams.value.taskId);
|
||||
|
@ -4,7 +4,7 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup name="WarmFlow">
|
||||
<script setup name="WarmFlow" lang="ts">
|
||||
const { proxy } = getCurrentInstance();
|
||||
import { onMounted } from 'vue';
|
||||
import { getToken } from '@/utils/auth';
|
||||
@ -24,12 +24,12 @@ const iframeLoaded = () => {
|
||||
};
|
||||
};
|
||||
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;
|
||||
};
|
||||
/** 关闭按钮 */
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -197,7 +197,7 @@ import { categoryTree } from '@/api/workflow/category';
|
||||
import { CategoryTreeVO } from '@/api/workflow/category/types';
|
||||
import { FlowDefinitionQuery, FlowDefinitionVo, FlowDefinitionForm } from '@/api/workflow/definition/types';
|
||||
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;
|
||||
|
||||
@ -326,7 +326,7 @@ const handleSelectionChange = (selection: any) => {
|
||||
};
|
||||
//分页
|
||||
const getPageList = async () => {
|
||||
let query = proxy.$route.query;
|
||||
const query = proxy.$route.query;
|
||||
if (query.activeName) {
|
||||
activeName.value = query.activeName;
|
||||
}
|
||||
@ -411,7 +411,7 @@ const handlerBeforeUpload = () => {
|
||||
};
|
||||
//部署文件
|
||||
const handlerImportDefinition = (data: UploadRequestOptions): XMLHttpRequest => {
|
||||
let formData = new FormData();
|
||||
const formData = new FormData();
|
||||
uploadDialogLoading.value = true;
|
||||
formData.append('file', data.file);
|
||||
formData.append('category', selectCategory.value);
|
||||
@ -466,6 +466,9 @@ const reset = () => {
|
||||
*/
|
||||
const handleAdd = async () => {
|
||||
reset();
|
||||
if (queryParams.value.category != '') {
|
||||
form.value.category = queryParams.value.category;
|
||||
}
|
||||
modelDialog.visible = true;
|
||||
modelDialog.title = '新增流程';
|
||||
};
|
||||
|
@ -352,7 +352,7 @@ const handleInvalid = async (row: FlowInstanceVO) => {
|
||||
await proxy?.$modal.confirm('是否确认作废?');
|
||||
loading.value = true;
|
||||
if ('running' === tab.value) {
|
||||
let param = {
|
||||
const param = {
|
||||
id: row.id,
|
||||
comment: deleteReason.value
|
||||
};
|
||||
@ -381,7 +381,7 @@ const handleInstanceVariable = async (row: FlowInstanceVO) => {
|
||||
variableLoading.value = true;
|
||||
variableVisible.value = true;
|
||||
processDefinitionName.value = row.flowName;
|
||||
let data = await instanceVariable(row.id);
|
||||
const data = await instanceVariable(row.id);
|
||||
variables.value = data.data.variable;
|
||||
variableLoading.value = false;
|
||||
};
|
||||
|
@ -222,7 +222,7 @@ const handleCancelProcessApply = async (businessId: string) => {
|
||||
await proxy?.$modal.confirm('是否确认撤销当前单据?');
|
||||
loading.value = true;
|
||||
if ('running' === tab.value) {
|
||||
let data = {
|
||||
const data = {
|
||||
businessId: businessId,
|
||||
message: '申请人撤销流程!'
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user