mirror of
https://gitee.com/xiangheng/x_admin.git
synced 2025-12-24 08:12:55 +08:00
@@ -53,7 +53,7 @@ stages:
|
||||
- mkdir -p /www/wwwroot/likeadmin
|
||||
- tar zxvf ~/gitee_go/deploy/x_admin.tar.gz -C /www/wwwroot/likeadmin
|
||||
- '# sh /home/admin/app/deploy.sh restart'
|
||||
- pm2 reload 4
|
||||
- pm2 reload x_admin
|
||||
- echo 'Go部署完成'
|
||||
notify: []
|
||||
strategy:
|
||||
|
||||
@@ -1,4 +1,2 @@
|
||||
NODE_ENV = 'development'
|
||||
|
||||
# 请求域名
|
||||
VITE_APP_BASE_URL='http://127.0.0.1:8001'
|
||||
|
||||
@@ -1,4 +1,2 @@
|
||||
NODE_ENV = 'production'
|
||||
|
||||
# 请求域名
|
||||
VITE_APP_BASE_URL=''
|
||||
VITE_APP_BASE_URL=''
|
||||
|
||||
@@ -3,13 +3,14 @@ require('@rushstack/eslint-patch/modern-module-resolution')
|
||||
|
||||
module.exports = {
|
||||
root: true,
|
||||
ignorePatterns: ['/auto-imports.d.ts', '/components.d.ts'],
|
||||
// ignorePatterns 忽略特定的文件和目录
|
||||
ignorePatterns: ['/auto-imports.d.ts', '/components.d.ts', 'scripts'],
|
||||
extends: [
|
||||
'plugin:vue/vue3-essential',
|
||||
'eslint:recommended',
|
||||
'@vue/eslint-config-typescript/recommended',
|
||||
'@vue/eslint-config-prettier',
|
||||
'./.eslintrc-auto-import.json'
|
||||
'@vue/eslint-config-prettier'
|
||||
// './.eslintrc-auto-import.json'
|
||||
],
|
||||
rules: {
|
||||
'prettier/prettier': [
|
||||
@@ -26,12 +27,18 @@ module.exports = {
|
||||
trailingComma: 'none'
|
||||
}
|
||||
],
|
||||
// 'vue/no-undef-components': [
|
||||
// 'error',
|
||||
// {
|
||||
// ignorePatterns: ['el(\\-\\w+)+']
|
||||
// }
|
||||
// ],
|
||||
'vue/multi-word-component-names': 'off',
|
||||
'@typescript-eslint/no-explicit-any': 'off',
|
||||
'@typescript-eslint/ban-ts-comment': 'off',
|
||||
'no-undef': 'off',
|
||||
'vue/prefer-import-from-vue': 'off',
|
||||
'no-prototype-builtins': 'off',
|
||||
// 'no-undef': 'off',
|
||||
// 'vue/prefer-import-from-vue': 'off',
|
||||
// 'no-prototype-builtins': 'off',
|
||||
'prefer-spread': 'off',
|
||||
'@typescript-eslint/no-non-null-assertion': 'off',
|
||||
'@typescript-eslint/no-non-null-asserted-optional-chain': 'off',
|
||||
|
||||
4
admin/.vscode/settings.json
vendored
4
admin/.vscode/settings.json
vendored
@@ -10,10 +10,14 @@
|
||||
"scss.validate": false,
|
||||
"cSpell.words": [
|
||||
"brotli",
|
||||
"btns",
|
||||
"daterange",
|
||||
"datetimerange",
|
||||
"dbclick",
|
||||
"echarts",
|
||||
"execa",
|
||||
"highlightjs",
|
||||
"iconfont",
|
||||
"logicflow",
|
||||
"nprogress",
|
||||
"pinia",
|
||||
|
||||
@@ -10,33 +10,33 @@
|
||||
"build": "node ./scripts/build.mjs",
|
||||
"type-check": "vue-tsc --noEmit --checkJs true --skipLibCheck",
|
||||
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore",
|
||||
"preinstall": "npx only-allow pnpm"
|
||||
"preinstall": "npx only-allow pnpm",
|
||||
"outdated": "pnpm outdated"
|
||||
},
|
||||
"dependencies": {
|
||||
"@element-plus/icons-vue": "^2.3.1",
|
||||
"@highlightjs/vue-plugin": "^2.1.0",
|
||||
"@logicflow/core": "^1.2.27",
|
||||
"@logicflow/extension": "^1.2.27",
|
||||
"@vue/shared": "^3.4.27",
|
||||
"@vueuse/core": "^10.10.0",
|
||||
"@logicflow/core": "^2.0.6",
|
||||
"@logicflow/extension": "^2.0.10",
|
||||
"@vueuse/core": "^10.11.0",
|
||||
"@wangeditor/editor": "^5.1.23",
|
||||
"@wangeditor/editor-for-vue": "^5.1.12",
|
||||
"axios": "^1.7.2",
|
||||
"axios": "^1.7.7",
|
||||
"crypto-js": "^4.2.0",
|
||||
"css-color-function": "^1.3.3",
|
||||
"dayjs": "^1.11.11",
|
||||
"echarts": "^5.5.0",
|
||||
"element-plus": "^2.7.5",
|
||||
"highlight.js": "^11.9.0",
|
||||
"dayjs": "^1.11.13",
|
||||
"echarts": "^5.5.1",
|
||||
"element-plus": "^2.8.6",
|
||||
"highlight.js": "^11.10.0",
|
||||
"lodash-es": "^4.17.21",
|
||||
"nprogress": "^0.2.0",
|
||||
"pinia": "^2.1.7",
|
||||
"query-string": "^9.0.0",
|
||||
"pinia": "^2.2.1",
|
||||
"query-string": "^9.1.0",
|
||||
"vform3-builds": "^3.0.10",
|
||||
"vue": "^3.4.27",
|
||||
"vue": "^3.5.12",
|
||||
"vue-clipboard3": "^2.0.0",
|
||||
"vue-echarts": "^6.7.3",
|
||||
"vue-router": "^4.3.3",
|
||||
"vue-echarts": "^7.0.1",
|
||||
"vue-router": "^4.4.5",
|
||||
"vue3-video-play": "^1.3.2",
|
||||
"vuedraggable": "^4.1.0"
|
||||
},
|
||||
@@ -45,28 +45,28 @@
|
||||
"@types/lodash-es": "^4.17.12",
|
||||
"@types/node": "^20.14.2",
|
||||
"@types/nprogress": "^0.2.3",
|
||||
"@vitejs/plugin-vue": "^5.0.5",
|
||||
"@vitejs/plugin-vue-jsx": "^4.0.0",
|
||||
"@vitejs/plugin-vue": "^5.1.4",
|
||||
"@vitejs/plugin-vue-jsx": "^4.0.1",
|
||||
"@vue/eslint-config-prettier": "^9.0.0",
|
||||
"@vue/eslint-config-typescript": "^13.0.0",
|
||||
"@vue/tsconfig": "^0.5.1",
|
||||
"autoprefixer": "^10.4.19",
|
||||
"autoprefixer": "^10.4.20",
|
||||
"eslint": "^8.57.0",
|
||||
"eslint-plugin-vue": "^9.26.0",
|
||||
"execa": "^9.2.0",
|
||||
"eslint-plugin-vue": "^9.27.0",
|
||||
"execa": "^9.3.0",
|
||||
"fs-extra": "^11.2.0",
|
||||
"postcss": "^8.4.38",
|
||||
"prettier": "^3.3.1",
|
||||
"prettier": "^3.3.3",
|
||||
"rollup-plugin-visualizer": "^5.12.0",
|
||||
"sass": "^1.77.4",
|
||||
"tailwindcss": "^3.4.4",
|
||||
"typescript": "~5.4.5",
|
||||
"unplugin-auto-import": "^0.17.6",
|
||||
"unplugin-vue-components": "^0.27.0",
|
||||
"vite": "^5.2.13",
|
||||
"sass": "^1.77.8",
|
||||
"tailwindcss": "^3.4.13",
|
||||
"typescript": "~5.6.2",
|
||||
"unplugin-auto-import": "^0.18.3",
|
||||
"unplugin-vue-components": "^0.27.4",
|
||||
"vite": "^5.4.7",
|
||||
"vite-plugin-compression": "^0.5.1",
|
||||
"vite-plugin-style-import": "^2.0.0",
|
||||
"vite-plugin-svg-icons": "^2.0.1",
|
||||
"vue-tsc": "^2.0.21"
|
||||
"vue-tsc": "^2.1.6"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
<script setup lang="ts">
|
||||
import { onMounted, watch } from 'vue'
|
||||
|
||||
import { RouterView } from 'vue-router'
|
||||
|
||||
import { useDark, useWindowSize, useThrottleFn } from '@vueuse/core'
|
||||
// import zhCn from "element-plus/lib/locale/lang/zh-cn";
|
||||
import zhCn from 'element-plus/dist/locale/zh-cn.mjs'
|
||||
|
||||
@@ -1,26 +1,83 @@
|
||||
import request from '@/utils/request'
|
||||
import type { Pages } from '@/utils/request'
|
||||
|
||||
export type type_flow_apply = {
|
||||
id?: number
|
||||
templateId?: number
|
||||
applyUserId?: number
|
||||
applyUserNickname?: string
|
||||
flowName?: string
|
||||
flowGroup?: number
|
||||
flowRemark?: string
|
||||
flowFormData?: string
|
||||
flowProcessData?: string
|
||||
flowProcessDataList?: string
|
||||
formValue?: string
|
||||
status?: number
|
||||
isDelete?: number
|
||||
createTime?: string
|
||||
updateTime?: string
|
||||
deleteTime?: string
|
||||
}
|
||||
// 查询
|
||||
export type type_flow_apply_query = {
|
||||
templateId?: number
|
||||
applyUserId?: number
|
||||
applyUserNickname?: string
|
||||
flowName?: string
|
||||
flowGroup?: number
|
||||
flowRemark?: string
|
||||
flowFormData?: string
|
||||
flowProcessData?: string
|
||||
flowProcessDataList?: string
|
||||
formValue?: string
|
||||
status?: number
|
||||
createTimeStart?: string
|
||||
createTimeEnd?: string
|
||||
updateTimeStart?: string
|
||||
updateTimeEnd?: string
|
||||
}
|
||||
// 添加编辑
|
||||
export type type_flow_apply_edit = {
|
||||
id?: number
|
||||
templateId?: number
|
||||
applyUserId?: number
|
||||
applyUserNickname?: string
|
||||
flowName?: string
|
||||
flowGroup?: number
|
||||
flowRemark?: string
|
||||
flowFormData?: string
|
||||
flowProcessData?: string
|
||||
flowProcessDataList?: string
|
||||
formValue?: string
|
||||
status?: number
|
||||
}
|
||||
|
||||
// 申请流程列表
|
||||
export function flow_apply_lists(params?: Record<string, any>) {
|
||||
return request.get({ url: '/flow/flow_apply/list', params })
|
||||
export function flow_apply_lists(params?: type_flow_apply_query) {
|
||||
return request.get<Pages<type_flow_apply>>({ url: '/flow/flow_apply/list', params })
|
||||
}
|
||||
// 申请流程列表-所有
|
||||
export function flow_apply_list_all(params?: type_flow_apply_query) {
|
||||
return request.get<type_flow_apply[]>({ url: '/flow/flow_apply/listAll', params })
|
||||
}
|
||||
|
||||
// 申请流程详情
|
||||
export function flow_apply_detail(params: Record<string, any>) {
|
||||
return request.get({ url: '/flow/flow_apply/detail', params })
|
||||
return request.get<type_flow_apply>({ url: '/flow/flow_apply/detail', params: params })
|
||||
}
|
||||
|
||||
// 申请流程新增
|
||||
export function flow_apply_add(data: Record<string, any>) {
|
||||
return request.post({ url: '/flow/flow_apply/add', data })
|
||||
export function flow_apply_add(data: type_flow_apply_edit) {
|
||||
return request.post<null>({ url: '/flow/flow_apply/add', data })
|
||||
}
|
||||
|
||||
// 申请流程编辑
|
||||
export function flow_apply_edit(data: Record<string, any>) {
|
||||
return request.post({ url: '/flow/flow_apply/edit', data })
|
||||
export function flow_apply_edit(data: type_flow_apply_edit) {
|
||||
return request.post<null>({ url: '/flow/flow_apply/edit', data })
|
||||
}
|
||||
|
||||
// 申请流程删除
|
||||
export function flow_apply_delete(data: Record<string, any>) {
|
||||
return request.post({ url: '/flow/flow_apply/del', data })
|
||||
export function flow_apply_delete(id: number | string) {
|
||||
return request.post<null>({ url: '/flow/flow_apply/del', data: { id } })
|
||||
}
|
||||
|
||||
@@ -1,32 +1,87 @@
|
||||
import request from '@/utils/request/index'
|
||||
import type { Pages } from '@/utils/request'
|
||||
|
||||
export type type_flow_history = {
|
||||
id?: number
|
||||
applyId?: number
|
||||
templateId?: number
|
||||
applyUserId?: number
|
||||
applyUserNickname?: string
|
||||
approverId?: number
|
||||
approverNickname?: string
|
||||
nodeId?: string
|
||||
nodeType?: string
|
||||
nodeLabel?: string
|
||||
formValue?: string
|
||||
passStatus?: number
|
||||
passRemark?: string
|
||||
createTime?: string
|
||||
updateTime?: string
|
||||
deleteTime?: string
|
||||
}
|
||||
// 查询
|
||||
export type type_flow_history_query = {
|
||||
applyId?: number
|
||||
templateId?: number
|
||||
applyUserId?: number
|
||||
applyUserNickname?: string
|
||||
approverId?: number
|
||||
approverNickname?: string
|
||||
nodeId?: string
|
||||
nodeType?: string
|
||||
nodeLabel?: string
|
||||
formValue?: string
|
||||
passStatus?: number
|
||||
passRemark?: string
|
||||
createTimeStart?: string
|
||||
createTimeEnd?: string
|
||||
updateTimeStart?: string
|
||||
updateTimeEnd?: string
|
||||
}
|
||||
// 添加编辑
|
||||
export type type_flow_history_edit = {
|
||||
id?: number
|
||||
applyId?: number
|
||||
templateId?: number
|
||||
applyUserId?: number
|
||||
applyUserNickname?: string
|
||||
approverId?: number
|
||||
approverNickname?: string
|
||||
nodeId?: string
|
||||
nodeType?: string
|
||||
nodeLabel?: string
|
||||
formValue?: string
|
||||
passStatus?: number
|
||||
passRemark?: string
|
||||
}
|
||||
|
||||
// 流程历史列表
|
||||
export function flow_history_list(params?: Record<string, any>) {
|
||||
return request.get({ url: '/flow/flow_history/list', params })
|
||||
export function flow_history_list(params?: type_flow_history_query) {
|
||||
return request.get<Pages<type_flow_history>>({ url: '/flow/flow_history/list', params })
|
||||
}
|
||||
// 流程历史列表-所有
|
||||
export function flow_history_list_all(params?: Record<string, any>) {
|
||||
return request.get({ url: '/flow/flow_history/listAll', params })
|
||||
export function flow_history_list_all(params?: type_flow_history_query) {
|
||||
return request.get<type_flow_history[]>({ url: '/flow/flow_history/listAll', params })
|
||||
}
|
||||
|
||||
// 流程历史详情
|
||||
export function flow_history_detail(params: Record<string, any>) {
|
||||
return request.get({ url: '/flow/flow_history/detail', params })
|
||||
export function flow_history_detail(id: number | string) {
|
||||
return request.get<type_flow_history>({ url: '/flow/flow_history/detail', params: { id } })
|
||||
}
|
||||
|
||||
// 流程历史新增
|
||||
export function flow_history_add(data: Record<string, any>) {
|
||||
return request.post({ url: '/flow/flow_history/add', data })
|
||||
export function flow_history_add(data: type_flow_history_edit) {
|
||||
return request.post<null>({ url: '/flow/flow_history/add', data })
|
||||
}
|
||||
|
||||
// 流程历史编辑
|
||||
export function flow_history_edit(data: Record<string, any>) {
|
||||
return request.post({ url: '/flow/flow_history/edit', data })
|
||||
export function flow_history_edit(data: type_flow_history_edit) {
|
||||
return request.post<null>({ url: '/flow/flow_history/edit', data })
|
||||
}
|
||||
|
||||
// 流程历史删除
|
||||
export function flow_history_delete(data: Record<string, any>) {
|
||||
return request.post({ url: '/flow/flow_history/del', data })
|
||||
export function flow_history_delete(id: number | string) {
|
||||
return request.post<null>({ url: '/flow/flow_history/del', data: { id } })
|
||||
}
|
||||
|
||||
// 获取下一个审批节点,中间可能有系统任务和结束节点被跳过
|
||||
|
||||
@@ -1,31 +1,68 @@
|
||||
import request from '@/utils/request'
|
||||
import type { Pages } from '@/utils/request'
|
||||
|
||||
// 流程模板列表
|
||||
export function flow_template_lists(params?: Record<string, any>) {
|
||||
return request.get({ url: '/flow/flow_template/list', params })
|
||||
export type type_flow_template = {
|
||||
id?: number
|
||||
flowName?: string
|
||||
flowGroup?: number
|
||||
flowRemark?: string
|
||||
flowFormData?: string
|
||||
flowProcessData?: string
|
||||
flowProcessDataList?: string
|
||||
isDelete?: number
|
||||
createTime?: string
|
||||
updateTime?: string
|
||||
deleteTime?: string
|
||||
}
|
||||
// 查询
|
||||
export type type_flow_template_query = {
|
||||
flowName?: string
|
||||
flowGroup?: number
|
||||
flowRemark?: string
|
||||
flowFormData?: string
|
||||
flowProcessData?: string
|
||||
flowProcessDataList?: string
|
||||
createTimeStart?: string
|
||||
createTimeEnd?: string
|
||||
updateTimeStart?: string
|
||||
updateTimeEnd?: string
|
||||
}
|
||||
// 添加编辑
|
||||
export type type_flow_template_edit = {
|
||||
id?: number
|
||||
flowName?: string
|
||||
flowGroup?: number
|
||||
flowRemark?: string
|
||||
flowFormData?: string
|
||||
flowProcessData?: string
|
||||
flowProcessDataList?: string
|
||||
}
|
||||
|
||||
// 流程模板列表
|
||||
export function flow_template_lists(params?: type_flow_template_query) {
|
||||
return request.get<Pages<type_flow_template>>({ url: '/flow/flow_template/list', params })
|
||||
}
|
||||
// 流程模板列表-所有
|
||||
export function flow_template_lists_all(params?: Record<string, any>) {
|
||||
return request.get({ url: '/flow/flow_template/listAll', params })
|
||||
export function flow_template_lists_all(params?: type_flow_template_query) {
|
||||
return request.get<type_flow_template[]>({ url: '/flow/flow_template/listAll', params })
|
||||
}
|
||||
|
||||
// 流程模板详情
|
||||
export function flow_template_detail(params: Record<string, any>) {
|
||||
return request.get({ url: '/flow/flow_template/detail', params })
|
||||
export function flow_template_detail(id: number | string) {
|
||||
return request.get<type_flow_template>({ url: '/flow/flow_template/detail', params: { id } })
|
||||
}
|
||||
|
||||
// 流程模板新增
|
||||
export function flow_template_add(data: Record<string, any>) {
|
||||
return request.post({ url: '/flow/flow_template/add', data })
|
||||
export function flow_template_add(data: type_flow_template_edit) {
|
||||
return request.post<null>({ url: '/flow/flow_template/add', data })
|
||||
}
|
||||
|
||||
// 流程模板编辑
|
||||
export function flow_template_edit(data: Record<string, any>) {
|
||||
return request.post({ url: '/flow/flow_template/edit', data })
|
||||
export function flow_template_edit(data: type_flow_template_edit) {
|
||||
return request.post<null>({ url: '/flow/flow_template/edit', data })
|
||||
}
|
||||
|
||||
// 流程模板删除
|
||||
export function flow_template_delete(data: Record<string, any>) {
|
||||
return request.post({ url: '/flow/flow_template/del', data })
|
||||
export function flow_template_delete(id: number | string) {
|
||||
return request.post<null>({ url: '/flow/flow_template/del', data: { id } })
|
||||
}
|
||||
|
||||
103
admin/src/api/monitor/client.ts
Normal file
103
admin/src/api/monitor/client.ts
Normal file
@@ -0,0 +1,103 @@
|
||||
import request from '@/utils/request'
|
||||
import type { Pages } from '@/utils/request'
|
||||
|
||||
import config from '@/config'
|
||||
import queryString from 'query-string'
|
||||
import { getToken } from '@/utils/auth'
|
||||
import { clearEmpty } from '@/utils/util'
|
||||
|
||||
export type type_monitor_client = {
|
||||
Id?: number
|
||||
ProjectKey?: string
|
||||
ClientId?: string
|
||||
UserId?: string
|
||||
Os?: string
|
||||
Browser?: string
|
||||
City?: string
|
||||
Width?: number
|
||||
Height?: number
|
||||
Ua?: string
|
||||
CreateTime?: string
|
||||
}
|
||||
// 查询
|
||||
export type type_monitor_client_query = {
|
||||
ProjectKey?: string
|
||||
ClientId?: string
|
||||
UserId?: string
|
||||
Os?: string
|
||||
Browser?: string
|
||||
City?: string
|
||||
Width?: number
|
||||
Height?: number
|
||||
Ua?: string
|
||||
CreateTimeStart?: string
|
||||
CreateTimeEnd?: string
|
||||
ClientTimeStart?: string
|
||||
ClientTimeEnd?: string
|
||||
}
|
||||
// 添加编辑
|
||||
export type type_monitor_client_edit = {
|
||||
Id?: number
|
||||
ProjectKey?: string
|
||||
ClientId?: string
|
||||
UserId?: string
|
||||
Os?: string
|
||||
Browser?: string
|
||||
City?: string
|
||||
Width?: number
|
||||
Height?: number
|
||||
Ua?: string
|
||||
}
|
||||
|
||||
// 监控-客户端信息列表
|
||||
export function monitor_client_list(params?: type_monitor_client_query) {
|
||||
return request.get<Pages<type_monitor_client>>({
|
||||
url: '/monitor_client/list',
|
||||
params: clearEmpty(params)
|
||||
})
|
||||
}
|
||||
// 监控-客户端信息列表-所有
|
||||
export function monitor_client_list_all(params?: type_monitor_client_query) {
|
||||
return request.get<type_monitor_client[]>({
|
||||
url: '/monitor_client/listAll',
|
||||
params: clearEmpty(params)
|
||||
})
|
||||
}
|
||||
|
||||
// 监控-客户端信息详情
|
||||
export function monitor_client_detail(Id: number | string) {
|
||||
return request.get<type_monitor_client>({ url: '/monitor_client/detail', params: { Id } })
|
||||
}
|
||||
|
||||
export function monitor_client_errorUsers(Id: number | string) {
|
||||
return request.get<type_monitor_client[]>({ url: '/monitor_client/errorUsers', params: { Id } })
|
||||
}
|
||||
|
||||
// 监控-客户端信息新增
|
||||
export function monitor_client_add(data: type_monitor_client_edit) {
|
||||
return request.post<null>({ url: '/monitor_client/add', data })
|
||||
}
|
||||
|
||||
// 监控-客户端信息编辑
|
||||
export function monitor_client_edit(data: type_monitor_client_edit) {
|
||||
return request.post<null>({ url: '/monitor_client/edit', data })
|
||||
}
|
||||
|
||||
// 监控-客户端信息删除
|
||||
export function monitor_client_delete(Id: number | string) {
|
||||
return request.post<null>({ url: '/monitor_client/del', data: { Id } })
|
||||
}
|
||||
// 监控-客户端信息删除-批量
|
||||
export function monitor_client_delete_batch(data: { Ids: string }) {
|
||||
return request.post<null>({ url: '/monitor_client/delBatch', data })
|
||||
}
|
||||
|
||||
// 监控-客户端信息导入
|
||||
export const monitor_client_import_file = '/monitor_client/ImportFile'
|
||||
|
||||
// 监控-客户端信息导出
|
||||
export function monitor_client_export_file(params: any) {
|
||||
return (window.location.href =
|
||||
`${config.baseUrl}${config.urlPrefix}/monitor_client/ExportFile?token=${getToken()}&` +
|
||||
queryString.stringify(clearEmpty(params)))
|
||||
}
|
||||
83
admin/src/api/monitor/error.ts
Normal file
83
admin/src/api/monitor/error.ts
Normal file
@@ -0,0 +1,83 @@
|
||||
import request from '@/utils/request'
|
||||
import type { Pages } from '@/utils/request'
|
||||
|
||||
import config from '@/config'
|
||||
import queryString from 'query-string'
|
||||
import { getToken } from '@/utils/auth'
|
||||
import { clearEmpty } from '@/utils/util'
|
||||
|
||||
export type type_monitor_error = {
|
||||
Id?: number
|
||||
ProjectKey?: string
|
||||
EventType?: string
|
||||
Path?: string
|
||||
Message?: string
|
||||
Stack?: string
|
||||
Md5?: string
|
||||
CreateTime?: string
|
||||
}
|
||||
// 查询
|
||||
export type type_monitor_error_query = {
|
||||
ProjectKey?: string
|
||||
EventType?: string
|
||||
Path?: string
|
||||
Message?: string
|
||||
Stack?: string
|
||||
Md5?: string
|
||||
CreateTimeStart?: string
|
||||
CreateTimeEnd?: string
|
||||
}
|
||||
// 添加编辑
|
||||
export type type_monitor_error_edit = {
|
||||
Id?: number
|
||||
ProjectKey?: string
|
||||
EventType?: string
|
||||
Path?: string
|
||||
Message?: string
|
||||
Stack?: string
|
||||
Md5?: string
|
||||
}
|
||||
|
||||
// 监控-错误列列表
|
||||
export function monitor_error_list(params?: type_monitor_error_query) {
|
||||
return request.get<Pages<type_monitor_error>>({
|
||||
url: '/monitor_error/list',
|
||||
params: clearEmpty(params)
|
||||
})
|
||||
}
|
||||
// 监控-错误列列表-所有
|
||||
export function monitor_error_list_all(params?: type_monitor_error_query) {
|
||||
return request.get<type_monitor_error[]>({
|
||||
url: '/monitor_error/listAll',
|
||||
params: clearEmpty(params)
|
||||
})
|
||||
}
|
||||
|
||||
// 监控-错误列详情
|
||||
export function monitor_error_detail(Id: number | string) {
|
||||
return request.get<type_monitor_error>({ url: '/monitor_error/detail', params: { Id } })
|
||||
}
|
||||
|
||||
// 监控-错误列新增
|
||||
export function monitor_error_add(data: type_monitor_error_edit) {
|
||||
return request.post<null>({ url: '/monitor_error/add', data })
|
||||
}
|
||||
|
||||
// 监控-错误列删除
|
||||
export function monitor_error_delete(Id: number | string) {
|
||||
return request.post<null>({ url: '/monitor_error/del', data: { Id } })
|
||||
}
|
||||
// 监控-错误列删除-批量
|
||||
export function monitor_error_delete_batch(data: { Ids: string }) {
|
||||
return request.post<null>({ url: '/monitor_error/delBatch', data })
|
||||
}
|
||||
|
||||
// 监控-错误列导入
|
||||
export const monitor_error_import_file = '/monitor_error/ImportFile'
|
||||
|
||||
// 监控-错误列导出
|
||||
export function monitor_error_export_file(params: any) {
|
||||
return (window.location.href =
|
||||
`${config.baseUrl}${config.urlPrefix}/monitor_error/ExportFile?token=${getToken()}&` +
|
||||
queryString.stringify(clearEmpty(params)))
|
||||
}
|
||||
87
admin/src/api/monitor/project.ts
Normal file
87
admin/src/api/monitor/project.ts
Normal file
@@ -0,0 +1,87 @@
|
||||
import request from '@/utils/request'
|
||||
import type { Pages } from '@/utils/request'
|
||||
|
||||
import config from '@/config'
|
||||
import queryString from 'query-string'
|
||||
import { getToken } from '@/utils/auth'
|
||||
import { clearEmpty } from '@/utils/util'
|
||||
|
||||
export type type_monitor_project = {
|
||||
Id?: number
|
||||
ProjectKey?: string
|
||||
ProjectName?: string
|
||||
ProjectType?: string
|
||||
Status?: number
|
||||
IsDelete?: number
|
||||
CreateTime?: string
|
||||
UpdateTime?: string
|
||||
DeleteTime?: string
|
||||
}
|
||||
// 查询
|
||||
export type type_monitor_project_query = {
|
||||
ProjectKey?: string
|
||||
ProjectName?: string
|
||||
ProjectType?: string
|
||||
Status?: number
|
||||
CreateTimeStart?: string
|
||||
CreateTimeEnd?: string
|
||||
UpdateTimeStart?: string
|
||||
UpdateTimeEnd?: string
|
||||
}
|
||||
// 添加编辑
|
||||
export type type_monitor_project_edit = {
|
||||
Id?: number
|
||||
ProjectKey?: string
|
||||
ProjectName?: string
|
||||
ProjectType?: string
|
||||
Status?: number
|
||||
}
|
||||
|
||||
// 监控项目列表
|
||||
export function monitor_project_list(params?: type_monitor_project_query) {
|
||||
return request.get<Pages<type_monitor_project>>({
|
||||
url: '/monitor_project/list',
|
||||
params: clearEmpty(params)
|
||||
})
|
||||
}
|
||||
// 监控项目列表-所有
|
||||
export function monitor_project_list_all(params?: type_monitor_project_query) {
|
||||
return request.get<type_monitor_project[]>({
|
||||
url: '/monitor_project/listAll',
|
||||
params: clearEmpty(params)
|
||||
})
|
||||
}
|
||||
|
||||
// 监控项目详情
|
||||
export function monitor_project_detail(Id: number | string) {
|
||||
return request.get<type_monitor_project>({ url: '/monitor_project/detail', params: { Id } })
|
||||
}
|
||||
|
||||
// 监控项目新增
|
||||
export function monitor_project_add(data: type_monitor_project_edit) {
|
||||
return request.post<null>({ url: '/monitor_project/add', data })
|
||||
}
|
||||
|
||||
// 监控项目编辑
|
||||
export function monitor_project_edit(data: type_monitor_project_edit) {
|
||||
return request.post<null>({ url: '/monitor_project/edit', data })
|
||||
}
|
||||
|
||||
// 监控项目删除
|
||||
export function monitor_project_delete(Id: number | string) {
|
||||
return request.post<null>({ url: '/monitor_project/del', data: { Id } })
|
||||
}
|
||||
// 监控项目删除-批量
|
||||
export function monitor_project_delete_batch(data: { Ids: string }) {
|
||||
return request.post<null>({ url: '/monitor_project/delBatch', data })
|
||||
}
|
||||
|
||||
// 监控项目导入
|
||||
export const monitor_project_import_file = '/monitor_project/ImportFile'
|
||||
|
||||
// 监控项目导出
|
||||
export function monitor_project_export_file(params: any) {
|
||||
return (window.location.href =
|
||||
`${config.baseUrl}${config.urlPrefix}/monitor_project/ExportFile?token=${getToken()}&` +
|
||||
queryString.stringify(clearEmpty(params)))
|
||||
}
|
||||
@@ -1,86 +0,0 @@
|
||||
import request from '@/utils/request'
|
||||
import type { Pages } from '@/utils/request'
|
||||
|
||||
import config from '@/config'
|
||||
import queryString from 'query-string'
|
||||
import { getToken } from '@/utils/auth'
|
||||
|
||||
export type type_monitor_client = {
|
||||
id?: number;
|
||||
projectKey?: string;
|
||||
clientId?: string;
|
||||
userId?: string;
|
||||
os?: string;
|
||||
browser?: string;
|
||||
city?: string;
|
||||
width?: number;
|
||||
height?: number;
|
||||
ua?: string;
|
||||
createTime?: string;
|
||||
clientTime?: string;
|
||||
}
|
||||
// 查询
|
||||
export type type_monitor_client_query = {
|
||||
projectKey?: string;
|
||||
clientId?: string;
|
||||
userId?: string;
|
||||
os?: string;
|
||||
browser?: string;
|
||||
city?: string;
|
||||
width?: number;
|
||||
height?: number;
|
||||
ua?: string;
|
||||
createTimeStart?: string;
|
||||
createTimeEnd?: string;
|
||||
clientTimeStart?: string;
|
||||
clientTimeEnd?: string;
|
||||
}
|
||||
// 添加编辑
|
||||
export type type_monitor_client_edit = {
|
||||
clientId?: string;
|
||||
userId?: string;
|
||||
os?: string;
|
||||
browser?: string;
|
||||
city?: string;
|
||||
width?: number;
|
||||
height?: number;
|
||||
ua?: string;
|
||||
clientTime?: string;
|
||||
}
|
||||
|
||||
// 监控-客户端信息列表
|
||||
export function monitor_client_list(params?: type_monitor_client_query) {
|
||||
return request.get<Pages<type_monitor_client>>({ url: '/monitor_client/list', params })
|
||||
}
|
||||
// 监控-客户端信息列表-所有
|
||||
export function monitor_client_list_all(params?: type_monitor_client_query) {
|
||||
return request.get<Pages<type_monitor_client>>({ url: '/monitor_client/listAll', params })
|
||||
}
|
||||
|
||||
// 监控-客户端信息详情
|
||||
export function monitor_client_detail(id: number | string) {
|
||||
return request.get<type_monitor_client>({ url: '/monitor_client/detail', params: { id } })
|
||||
}
|
||||
|
||||
// 监控-客户端信息新增
|
||||
export function monitor_client_add(data: type_monitor_client_edit) {
|
||||
return request.post<null>({ url: '/monitor_client/add', data })
|
||||
}
|
||||
|
||||
// 监控-客户端信息编辑
|
||||
export function monitor_client_edit(data: type_monitor_client_edit) {
|
||||
return request.post<null>({ url: '/monitor_client/edit', data })
|
||||
}
|
||||
|
||||
// 监控-客户端信息删除
|
||||
export function monitor_client_delete(id: number | string) {
|
||||
return request.post<null>({ url: '/monitor_client/del', data: { id } })
|
||||
}
|
||||
|
||||
// 监控-客户端信息导入
|
||||
export const monitor_client_import_file = '/monitor_client/ImportFile'
|
||||
|
||||
// 监控-客户端信息导出
|
||||
export function monitor_client_export_file(params: any) {
|
||||
return (window.location.href =`${config.baseUrl}${config.urlPrefix}/monitor_client/ExportFile?token=${getToken()}&` + queryString.stringify(params))
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 错误项目列表
|
||||
export function monitor_project_list(params?: Record<string, any>) {
|
||||
return request.get({ url: '/monitor_project/list', params })
|
||||
}
|
||||
// 错误项目列表-所有
|
||||
export function monitor_project_list_all(params?: Record<string, any>) {
|
||||
return request.get({ url: '/monitor_project/listAll', params })
|
||||
}
|
||||
|
||||
// 错误项目详情
|
||||
export function monitor_project_detail(params: Record<string, any>) {
|
||||
return request.get({ url: '/monitor_project/detail', params })
|
||||
}
|
||||
|
||||
// 错误项目新增
|
||||
export function monitor_project_add(data: Record<string, any>) {
|
||||
return request.post({ url: '/monitor_project/add', data })
|
||||
}
|
||||
|
||||
// 错误项目编辑
|
||||
export function monitor_project_edit(data: Record<string, any>) {
|
||||
return request.post({ url: '/monitor_project/edit', data })
|
||||
}
|
||||
|
||||
// 错误项目删除
|
||||
export function monitor_project_delete(data: Record<string, any>) {
|
||||
return request.post({ url: '/monitor_project/del', data })
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
import request from '@/utils/request'
|
||||
import config from '@/config'
|
||||
import queryString from 'query-string'
|
||||
import { getToken } from '@/utils/auth'
|
||||
|
||||
// 错误收集error列表
|
||||
export function monitor_web_list(params?: Record<string, any>) {
|
||||
return request.get({ url: '/monitor_web/list', params })
|
||||
}
|
||||
// 错误收集error列表-所有
|
||||
export function monitor_web_list_all(params?: Record<string, any>) {
|
||||
return request.get({ url: '/monitor_web/listAll', params })
|
||||
}
|
||||
|
||||
// 错误收集error详情
|
||||
export function monitor_web_detail(params: Record<string, any>) {
|
||||
return request.get({ url: '/monitor_web/detail', params })
|
||||
}
|
||||
|
||||
// 错误收集error新增
|
||||
export function monitor_web_add(data: Record<string, any>) {
|
||||
return request.post({ url: '/monitor_web/add', data })
|
||||
}
|
||||
|
||||
// 错误收集error编辑
|
||||
export function monitor_web_edit(data: Record<string, any>) {
|
||||
return request.post({ url: '/monitor_web/edit', data })
|
||||
}
|
||||
|
||||
// 错误收集error删除
|
||||
export function monitor_web_delete(data: Record<string, any>) {
|
||||
return request.post({ url: '/monitor_web/del', data })
|
||||
}
|
||||
|
||||
// 错误收集error导入
|
||||
export const monitor_web_import_file = '/monitor_web/ImportFile'
|
||||
|
||||
// 错误收集error导出
|
||||
export function monitor_web_export_file(params: any) {
|
||||
return (window.location.href =
|
||||
`${config.baseUrl}${config.urlPrefix}/monitor_web/ExportFile?token=${getToken()}&` +
|
||||
queryString.stringify(params))
|
||||
}
|
||||
@@ -6,6 +6,10 @@ import config from '@/config'
|
||||
export function adminLists(params: any) {
|
||||
return request.get({ url: '/system/admin/list', params })
|
||||
}
|
||||
// 管理员列表
|
||||
export function adminListAll(params: any) {
|
||||
return request.get({ url: '/system/admin/listAll', params })
|
||||
}
|
||||
// 管理员详情
|
||||
export function adminDetail(params: any) {
|
||||
return request.get({ url: '/system/admin/detail', params })
|
||||
|
||||
84
admin/src/api/user/protocol.ts
Normal file
84
admin/src/api/user/protocol.ts
Normal file
@@ -0,0 +1,84 @@
|
||||
import request from '@/utils/request'
|
||||
import type { Pages } from '@/utils/request'
|
||||
|
||||
import config from '@/config'
|
||||
import queryString from 'query-string'
|
||||
import { getToken } from '@/utils/auth'
|
||||
import { clearEmpty } from '@/utils/util'
|
||||
|
||||
export type type_user_protocol = {
|
||||
Id?: number
|
||||
Title?: string
|
||||
Content?: string
|
||||
Sort?: number
|
||||
IsDelete?: number
|
||||
CreateTime?: string
|
||||
UpdateTime?: string
|
||||
DeleteTime?: string
|
||||
}
|
||||
// 查询
|
||||
export type type_user_protocol_query = {
|
||||
Title?: string
|
||||
Content?: string
|
||||
Sort?: number
|
||||
CreateTimeStart?: string
|
||||
CreateTimeEnd?: string
|
||||
UpdateTimeStart?: string
|
||||
UpdateTimeEnd?: string
|
||||
}
|
||||
// 添加编辑
|
||||
export type type_user_protocol_edit = {
|
||||
Id?: number
|
||||
Title?: string
|
||||
Content?: string
|
||||
Sort?: number
|
||||
}
|
||||
|
||||
// 用户协议列表
|
||||
export function user_protocol_list(params?: type_user_protocol_query) {
|
||||
return request.get<Pages<type_user_protocol>>({
|
||||
url: '/user_protocol/list',
|
||||
params: clearEmpty(params)
|
||||
})
|
||||
}
|
||||
// 用户协议列表-所有
|
||||
export function user_protocol_list_all(params?: type_user_protocol_query) {
|
||||
return request.get<type_user_protocol[]>({
|
||||
url: '/user_protocol/listAll',
|
||||
params: clearEmpty(params)
|
||||
})
|
||||
}
|
||||
|
||||
// 用户协议详情
|
||||
export function user_protocol_detail(Id: number | string) {
|
||||
return request.get<type_user_protocol>({ url: '/user_protocol/detail', params: { Id } })
|
||||
}
|
||||
|
||||
// 用户协议新增
|
||||
export function user_protocol_add(data: type_user_protocol_edit) {
|
||||
return request.post<null>({ url: '/user_protocol/add', data })
|
||||
}
|
||||
|
||||
// 用户协议编辑
|
||||
export function user_protocol_edit(data: type_user_protocol_edit) {
|
||||
return request.post<null>({ url: '/user_protocol/edit', data })
|
||||
}
|
||||
|
||||
// 用户协议删除
|
||||
export function user_protocol_delete(Id: number | string) {
|
||||
return request.post<null>({ url: '/user_protocol/del', data: { Id } })
|
||||
}
|
||||
// 用户协议删除-批量
|
||||
export function user_protocol_delete_batch(data: { Ids: string }) {
|
||||
return request.post<null>({ url: '/user_protocol/delBatch', data })
|
||||
}
|
||||
|
||||
// 用户协议导入
|
||||
export const user_protocol_import_file = '/user_protocol/ImportFile'
|
||||
|
||||
// 用户协议导出
|
||||
export function user_protocol_export_file(params: any) {
|
||||
return (window.location.href =
|
||||
`${config.baseUrl}${config.urlPrefix}/user_protocol/ExportFile?token=${getToken()}&` +
|
||||
queryString.stringify(clearEmpty(params)))
|
||||
}
|
||||
@@ -5,6 +5,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed } from 'vue'
|
||||
/**
|
||||
* @description 兼容第三方页面的跳转
|
||||
*/
|
||||
|
||||
@@ -21,14 +21,7 @@ const color = defineModel({
|
||||
return props.defaultColor
|
||||
}
|
||||
})
|
||||
// const color = computed({
|
||||
// get() {
|
||||
// return props.modelValue
|
||||
// },
|
||||
// set(value) {
|
||||
// emit('update:modelValue', value)
|
||||
// }
|
||||
// })
|
||||
|
||||
const predefineColors = ['#409EFF', '#28C76F', '#EA5455', '#FF9F43', '#01CFE8', '#4A5DFF']
|
||||
const reset = () => {
|
||||
color.value = props.defaultColor
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, watch } from 'vue'
|
||||
/* Props S */
|
||||
const props = defineProps({
|
||||
startTime: {
|
||||
@@ -44,20 +45,4 @@ watch([() => props.startTime, () => props.endTime], () => {
|
||||
console.log('watch', props)
|
||||
content.value = [props.startTime, props.endTime]
|
||||
})
|
||||
// const content = computed<any>({
|
||||
// get: () => {
|
||||
// return [props.startTime, props.endTime]
|
||||
// },
|
||||
// set: (value: Event | any) => {
|
||||
// console.log('change', value)
|
||||
|
||||
// if (value === null) {
|
||||
// emit('update:startTime', '')
|
||||
// emit('update:endTime', '')
|
||||
// } else {
|
||||
// emit('update:startTime', value[0])
|
||||
// emit('update:endTime', value[1])
|
||||
// }
|
||||
// }
|
||||
// })
|
||||
</script>
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue'
|
||||
export default defineComponent({
|
||||
props: {
|
||||
showClose: {
|
||||
|
||||
@@ -1,18 +1,29 @@
|
||||
<template>
|
||||
<div>
|
||||
<template v-for="(item, index) in getOptions" :key="index">
|
||||
<span :style="{ color: item.color }">{{ index != 0 ? '、' : '' }}{{ item.name }}</span>
|
||||
<span :style="{ color: item.color }"
|
||||
>{{ index != 0 ? '、' : '' }}{{ item[props.labelKey] }}</span
|
||||
>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { computed, withDefaults } from 'vue'
|
||||
defineOptions({
|
||||
name: 'dict-value'
|
||||
})
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
options: any[]
|
||||
value: any
|
||||
labelKey?: string
|
||||
valueKey?: string
|
||||
}>(),
|
||||
{
|
||||
options: () => []
|
||||
options: () => [],
|
||||
value: null,
|
||||
labelKey: 'name',
|
||||
valueKey: 'value'
|
||||
}
|
||||
)
|
||||
|
||||
@@ -25,6 +36,6 @@ const values = computed(() => {
|
||||
})
|
||||
|
||||
const getOptions = computed(() => {
|
||||
return props.options.filter((item) => values.value.includes(item.value))
|
||||
return props.options.filter((item) => values.value.includes(item[props.valueKey]))
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
:mode="mode"
|
||||
/>
|
||||
<w-editor
|
||||
class="overflow-y-auto flex-1"
|
||||
class="overflow-y-auto flex-1 border-solid border rounded-s"
|
||||
v-model="valueHtml"
|
||||
:defaultConfig="editorConfig"
|
||||
:mode="mode"
|
||||
@@ -28,6 +28,8 @@ import { Editor as WEditor, Toolbar } from '@wangeditor/editor-for-vue'
|
||||
import type { IEditorConfig, IToolbarConfig } from '@wangeditor/editor'
|
||||
import MaterialPicker from '@/components/material/picker.vue'
|
||||
import { addUnit } from '@/utils/util'
|
||||
|
||||
import { withDefaults, computed, shallowRef, ref, onBeforeUnmount } from 'vue'
|
||||
import type { CSSProperties } from 'vue'
|
||||
|
||||
const props = withDefaults(
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
style="height: 100vh"
|
||||
class="flow-config-dialog"
|
||||
>
|
||||
<template #header="{ close }">
|
||||
<template #header>
|
||||
<header class="page__header">
|
||||
<div class="page-actions">
|
||||
{{ title }}
|
||||
@@ -30,7 +30,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<el-button class="publish-btn" @click="close">关闭</el-button>
|
||||
<el-button class="publish-btn" @click="exit">关闭</el-button>
|
||||
<el-button class="publish-btn" type="primary" @click="publish">发布</el-button>
|
||||
</header>
|
||||
</template>
|
||||
@@ -48,168 +48,151 @@
|
||||
v-show="activeStep === 'formDesign'"
|
||||
tabName="formDesign"
|
||||
/>
|
||||
<Diagram
|
||||
ref="processDesign"
|
||||
v-show="activeStep === 'processDesign'"
|
||||
tabName="processDesign"
|
||||
<FlowEdit
|
||||
ref="flowEdit"
|
||||
v-show="activeStep === 'flowEdit'"
|
||||
tabName="flowEdit"
|
||||
:fieldList="fieldList"
|
||||
:conf="mockData.flowProcessData"
|
||||
></Diagram>
|
||||
></FlowEdit>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { defineComponent } from 'vue'
|
||||
<script setup lang="ts">
|
||||
import { ref, shallowRef, watch } from 'vue'
|
||||
import XForm from './XForm/index.vue'
|
||||
import Diagram from './flowEdit/Diagram.vue'
|
||||
|
||||
import FlowEdit from './flowEdit/index.vue'
|
||||
import BasicSetting from './BasicSetting/index.vue'
|
||||
|
||||
import feedback from '@/utils/feedback'
|
||||
|
||||
const beforeUnload = function (e) {
|
||||
const confirmationMessage = '离开网站可能会丢失您编辑得内容'
|
||||
;(e || window.event).returnValue = confirmationMessage // Gecko and Trident
|
||||
return confirmationMessage // Gecko and WebKit
|
||||
e.preventDefault()
|
||||
|
||||
e.returnValue = '离开网站可能会丢失您编辑得内容' // Gecko and Trident
|
||||
return false // Gecko and WebKit
|
||||
}
|
||||
export default defineComponent({
|
||||
name: 'Approver',
|
||||
components: {
|
||||
// Process,
|
||||
Diagram,
|
||||
// DynamicForm,
|
||||
XForm,
|
||||
BasicSetting
|
||||
defineOptions({
|
||||
name: 'Approver'
|
||||
})
|
||||
const props = defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
default: '流程配置'
|
||||
},
|
||||
props: {
|
||||
title: {
|
||||
type: String,
|
||||
default: '流程配置'
|
||||
},
|
||||
save: {
|
||||
type: Function,
|
||||
default: () => {}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
dialogVisible: false,
|
||||
save: {
|
||||
type: Function,
|
||||
default: () => {}
|
||||
}
|
||||
})
|
||||
|
||||
activeStep: 'basicSetting', // 激活的步骤面板
|
||||
mockData: {
|
||||
id: '',
|
||||
basicSetting: {},
|
||||
flowFormData: {},
|
||||
flowProcessData: {}
|
||||
},
|
||||
fieldList: [],
|
||||
steps: [
|
||||
{ label: '基础设置', key: 'basicSetting' },
|
||||
{ label: '表单设计', key: 'formDesign' },
|
||||
{ label: '流程设计', key: 'processDesign' }
|
||||
]
|
||||
}
|
||||
},
|
||||
beforeRouteEnter(to, from, next) {
|
||||
window.addEventListener('beforeunload', beforeUnload)
|
||||
next()
|
||||
},
|
||||
beforeRouteLeave(to, from, next) {
|
||||
window.removeEventListener('beforeunload', beforeUnload)
|
||||
next()
|
||||
},
|
||||
|
||||
mounted() {},
|
||||
methods: {
|
||||
reset() {
|
||||
this.mockData = {
|
||||
id: '',
|
||||
basicSetting: {},
|
||||
flowFormData: {},
|
||||
flowProcessData: {}
|
||||
}
|
||||
this.activeStep = 'basicSetting'
|
||||
this.fieldList = []
|
||||
},
|
||||
open(data) {
|
||||
this.reset()
|
||||
console.log('data', data)
|
||||
if (data) {
|
||||
this.mockData = { ...data }
|
||||
} else {
|
||||
this.mockData = {
|
||||
id: '',
|
||||
basicSetting: {},
|
||||
flowFormData: {},
|
||||
flowProcessData: {}
|
||||
}
|
||||
}
|
||||
|
||||
this.dialogVisible = true
|
||||
},
|
||||
async changeSteps(item) {
|
||||
const fieldList = this.$refs?.formDesign?.getFieldWidgets()
|
||||
|
||||
this.fieldList = fieldList
|
||||
|
||||
this.activeStep = item.key
|
||||
},
|
||||
// 发布
|
||||
publish() {
|
||||
const getCmpData = (name) => {
|
||||
return this.$refs[name]?.getData()
|
||||
}
|
||||
// basicSetting formDesign processDesign 返回的是Promise 因为要做校验
|
||||
|
||||
const p1 = getCmpData('basicSetting')
|
||||
const p2 = getCmpData('formDesign')
|
||||
const p3 = getCmpData('processDesign')
|
||||
Promise.all([p1, p2, p3])
|
||||
.then((res) => {
|
||||
console.log('res', res)
|
||||
const param = {
|
||||
id: this?.mockData?.id,
|
||||
basicSetting: res[0].formData,
|
||||
flowFormData: res[1].formData,
|
||||
flowProcessData: res[2].formData,
|
||||
flowProcessDataList: res[2].treeToList
|
||||
}
|
||||
console.log(param)
|
||||
this.sendToServer(param)
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error(err)
|
||||
err.target && (this.activeStep = err.target)
|
||||
err.message && this.$message.error(err.message)
|
||||
})
|
||||
},
|
||||
|
||||
sendToServer(param) {
|
||||
this.$notify({
|
||||
title: '数据已整合完成',
|
||||
message: '请在控制台中查看数据输出',
|
||||
position: 'bottom-right'
|
||||
})
|
||||
this.save(param)
|
||||
.then(() => {
|
||||
this.dialogVisible = false
|
||||
})
|
||||
.catch((err) => {
|
||||
err.message && this.$message.error(err.message)
|
||||
})
|
||||
console.log('配置数据', param)
|
||||
},
|
||||
exit() {
|
||||
this.$confirm('离开此页面您得修改将会丢失, 是否继续?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
})
|
||||
.then(() => {
|
||||
window.history.back()
|
||||
})
|
||||
.catch(() => {})
|
||||
const basicSetting = shallowRef<InstanceType<typeof BasicSetting>>()
|
||||
const formDesign = shallowRef<InstanceType<typeof XForm>>()
|
||||
const flowEdit = shallowRef<InstanceType<typeof FlowEdit>>()
|
||||
const dialogVisible = ref(false)
|
||||
const activeStep = ref('basicSetting')
|
||||
const mockData = ref({
|
||||
id: '',
|
||||
basicSetting: {},
|
||||
flowFormData: {},
|
||||
flowProcessData: {}
|
||||
})
|
||||
const fieldList = ref([])
|
||||
const steps = [
|
||||
{ label: '基础设置', key: 'basicSetting' },
|
||||
{ label: '表单设计', key: 'formDesign' },
|
||||
{ label: '流程设计', key: 'flowEdit' }
|
||||
]
|
||||
watch(
|
||||
() => dialogVisible.value,
|
||||
(val) => {
|
||||
if (!val) {
|
||||
window.removeEventListener('beforeunload', beforeUnload)
|
||||
} else {
|
||||
window.addEventListener('beforeunload', beforeUnload)
|
||||
}
|
||||
}
|
||||
)
|
||||
function reset() {
|
||||
mockData.value = {
|
||||
id: '',
|
||||
basicSetting: {},
|
||||
flowFormData: {},
|
||||
flowProcessData: {}
|
||||
}
|
||||
activeStep.value = 'basicSetting'
|
||||
fieldList.value = []
|
||||
}
|
||||
function open(data) {
|
||||
reset()
|
||||
console.log('data', data)
|
||||
if (data) {
|
||||
mockData.value = { ...data }
|
||||
} else {
|
||||
mockData.value = {
|
||||
id: '',
|
||||
basicSetting: {},
|
||||
flowFormData: {},
|
||||
flowProcessData: {}
|
||||
}
|
||||
}
|
||||
|
||||
dialogVisible.value = true
|
||||
}
|
||||
function changeSteps(item) {
|
||||
fieldList.value = formDesign.value.getFieldWidgets()
|
||||
console.log('fieldList', fieldList.value)
|
||||
|
||||
activeStep.value = item.key
|
||||
}
|
||||
// 发布
|
||||
function publish() {
|
||||
const p1 = basicSetting.value.getData()
|
||||
const p2 = formDesign.value.getData()
|
||||
const p3 = flowEdit.value.getData()
|
||||
Promise.all([p1, p2, p3])
|
||||
.then((res) => {
|
||||
console.log('res', res)
|
||||
const param = {
|
||||
id: mockData.value?.id,
|
||||
basicSetting: res[0].formData,
|
||||
flowFormData: res[1].formData,
|
||||
flowProcessData: res[2].formData,
|
||||
flowProcessDataList: res[2].treeToList
|
||||
}
|
||||
console.log(param)
|
||||
sendToServer(param)
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error(err)
|
||||
err.target && (activeStep.value = err.target)
|
||||
err.message && feedback.msgError(err.message)
|
||||
})
|
||||
}
|
||||
|
||||
function sendToServer(param) {
|
||||
feedback.notify('数据已整合完成')
|
||||
props
|
||||
.save(param)
|
||||
.then(() => {
|
||||
dialogVisible.value = false
|
||||
})
|
||||
.catch((err) => {
|
||||
err.message && feedback.msgError(err.message)
|
||||
})
|
||||
console.log('配置数据', param)
|
||||
}
|
||||
function exit() {
|
||||
feedback
|
||||
.confirm('离开此页面您得修改将会丢失, 是否继续?')
|
||||
.then(() => {
|
||||
dialogVisible.value = false
|
||||
})
|
||||
.catch(() => {})
|
||||
}
|
||||
defineExpose({
|
||||
open
|
||||
})
|
||||
</script>
|
||||
<style>
|
||||
|
||||
@@ -88,10 +88,13 @@ onMounted(() => {
|
||||
})
|
||||
const elFormRef = shallowRef<FormInstance>()
|
||||
function getData() {
|
||||
return new Promise((resolve, reject) => {
|
||||
return new Promise<{
|
||||
formData: any
|
||||
target: string
|
||||
}>((resolve, reject) => {
|
||||
elFormRef.value.validate((valid) => {
|
||||
if (!valid) {
|
||||
reject({ target: this.tabName })
|
||||
reject({ target: props.tabName })
|
||||
return
|
||||
}
|
||||
// this.formData.flowImg = this.activeIcon
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import { ref, onMounted } from 'vue'
|
||||
import 'vform3-builds/dist/designer.style.css' //引入VForm3样式
|
||||
const designerRef = ref(null)
|
||||
function setData(json) {
|
||||
@@ -16,7 +16,9 @@ function getFieldWidgets() {
|
||||
return fieldList
|
||||
}
|
||||
function getData() {
|
||||
return new Promise((resolve, reject) => {
|
||||
return new Promise<{
|
||||
formData: any
|
||||
}>((resolve, reject) => {
|
||||
try {
|
||||
const jsonData = designerRef.value.getFormJson()
|
||||
console.log('jsonData', jsonData)
|
||||
|
||||
@@ -1,332 +0,0 @@
|
||||
<template>
|
||||
<div class="diagram">
|
||||
<diagram-toolbar
|
||||
v-if="lf"
|
||||
class="diagram-toolbar"
|
||||
:lf="lf"
|
||||
:active-edges="activeEdges"
|
||||
@saveGraph="$_saveGraph"
|
||||
@importData="importData"
|
||||
/>
|
||||
<div class="diagram-main">
|
||||
<diagram-sidebar class="diagram-sidebar" @dragInNode="$_dragInNode" />
|
||||
<div ref="container" class="diagram-container">
|
||||
<div class="diagram-wrapper">
|
||||
<div ref="diagram" class="lf-diagram"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 右侧属性面板 -->
|
||||
<PropertyPanel ref="panelRef" @setProperties="$setProperties" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import LogicFlow from '@logicflow/core'
|
||||
import { SelectionSelect, Menu, BpmnElement } from '@logicflow/extension'
|
||||
|
||||
import '@logicflow/core/dist/style/index.css'
|
||||
import '@logicflow/extension/lib/style/index.css'
|
||||
import DiagramToolbar from './DiagramToolbar.vue'
|
||||
import DiagramSidebar from './DiagramSidebar.vue'
|
||||
import PropertyPanel from './PropertyPanel.vue'
|
||||
import { registerCustomElement } from './node'
|
||||
|
||||
// import { Control } from "@logicflow/extension";
|
||||
|
||||
export default {
|
||||
name: 'Diagram',
|
||||
components: {
|
||||
DiagramToolbar,
|
||||
DiagramSidebar,
|
||||
PropertyPanel
|
||||
},
|
||||
props: {
|
||||
fieldList: {
|
||||
type: Array,
|
||||
default: () => {
|
||||
return []
|
||||
}
|
||||
},
|
||||
conf: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
return {}
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
sidebarWidth: 200,
|
||||
diagramWidth: 0,
|
||||
diagramHeight: 0,
|
||||
lf: null,
|
||||
filename: '',
|
||||
activeEdges: []
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
// const data = ''
|
||||
|
||||
this.filename = 'export.json'
|
||||
// const d = window.sessionStorage.getItem(this.filename)
|
||||
// if (d) {
|
||||
// data = JSON.parse(d)
|
||||
// }
|
||||
|
||||
this.initLogicFlow(this.conf)
|
||||
},
|
||||
methods: {
|
||||
initLogicFlow(data) {
|
||||
// 引入框选插件
|
||||
LogicFlow.use(SelectionSelect)
|
||||
LogicFlow.use(Menu)
|
||||
LogicFlow.use(BpmnElement)
|
||||
|
||||
const lf = new LogicFlow({
|
||||
container: this.$refs.diagram,
|
||||
overlapMode: 1,
|
||||
autoWrap: true,
|
||||
metaKeyMultipleSelected: true,
|
||||
keyboard: {
|
||||
enabled: true
|
||||
},
|
||||
grid: {
|
||||
size: 10,
|
||||
type: 'dot'
|
||||
}
|
||||
})
|
||||
lf.setTheme({
|
||||
baseEdge: { strokeWidth: 1 },
|
||||
baseNode: { strokeWidth: 1 },
|
||||
nodeText: { overflowMode: 'autoWrap', lineHeight: 1.5 },
|
||||
edgeText: { overflowMode: 'autoWrap', lineHeight: 1.5 }
|
||||
})
|
||||
// 注册自定义元素
|
||||
registerCustomElement(lf)
|
||||
lf.setDefaultEdgeType('pro-polyline')
|
||||
lf.render(data)
|
||||
this.lf = lf
|
||||
|
||||
this.lf.on('node:click', (e) => {
|
||||
console.log('点击节点', e.data)
|
||||
this.$refs.panelRef.open(e.data, this.fieldList)
|
||||
})
|
||||
|
||||
// lf.renderRawData( )
|
||||
},
|
||||
|
||||
$_dragInNode(type, text = '') {
|
||||
this.lf.dnd.startDrag({
|
||||
type,
|
||||
text
|
||||
})
|
||||
},
|
||||
// 获取可以进行设置的属性
|
||||
$_getProperty() {
|
||||
// this.lf.getProperties(node.id)
|
||||
},
|
||||
$setProperties(node, item) {
|
||||
this.lf.setProperties(node.id, item)
|
||||
},
|
||||
$_setZIndex(node, type) {
|
||||
this.lf.setElementZIndex(node.id, type)
|
||||
},
|
||||
importData(text) {
|
||||
this.lf.renderRawData(text)
|
||||
},
|
||||
$_saveGraph() {
|
||||
const data = this.lf.getGraphData()
|
||||
this.download(this.filename, JSON.stringify(data))
|
||||
},
|
||||
download(filename, text) {
|
||||
window.sessionStorage.setItem(filename, text)
|
||||
const element = document.createElement('a')
|
||||
element.setAttribute(
|
||||
'href',
|
||||
'data:text/plain;charset=utf-8,' + encodeURIComponent(text)
|
||||
)
|
||||
element.setAttribute('download', filename)
|
||||
element.style.display = 'none'
|
||||
document.body.appendChild(element)
|
||||
element.click()
|
||||
document.body.removeChild(element)
|
||||
},
|
||||
getData() {
|
||||
/**
|
||||
* 校验目标
|
||||
* 1. 必须存在开始节点和结束节点
|
||||
* 2. 连线方向正确
|
||||
* 3. 多余的节点(不重要)
|
||||
* 4. 所有分支必须结束节点
|
||||
* 5. 检查审批节点设置情况
|
||||
* 6. 一个节点可以有多个子网关,子网关只能通过一个,不能有多个普通子节点
|
||||
*
|
||||
*/
|
||||
return new Promise((resolve, reject) => {
|
||||
const data = this.lf.getGraphData()
|
||||
|
||||
const nodes = data.nodes
|
||||
const edges = data.edges
|
||||
|
||||
let haveMoreChildNode = false
|
||||
const sourceNodeIdSum = {} //节点id->[子节点id]
|
||||
|
||||
edges.forEach((edge) => {
|
||||
const targetNode = nodes.find((item) => item.id == edge.targetNodeId)
|
||||
if (sourceNodeIdSum[edge.sourceNodeId]) {
|
||||
sourceNodeIdSum[edge.sourceNodeId].push(targetNode)
|
||||
|
||||
for (const n of sourceNodeIdSum[edge.sourceNodeId]) {
|
||||
if (n.type != 'bpmn:exclusiveGateway') {
|
||||
haveMoreChildNode = true
|
||||
break
|
||||
}
|
||||
}
|
||||
} else {
|
||||
sourceNodeIdSum[edge.sourceNodeId] = [targetNode]
|
||||
}
|
||||
})
|
||||
console.log('sourceNodeIdSum', sourceNodeIdSum)
|
||||
if (haveMoreChildNode) {
|
||||
// 如果都是网关就可以,等优化
|
||||
return reject({
|
||||
message: '流程设计-一个节点只能有一个子节点,可以有多个网关'
|
||||
})
|
||||
}
|
||||
|
||||
// if (data.nodes.length != data.edges.length + 1) {
|
||||
// return reject({
|
||||
// message: "流程设计-节点之间必须连线,可以清理多余的节点",//不是很重要
|
||||
// });
|
||||
// }
|
||||
// 检查开始节点和结束节点是否存在
|
||||
const findStartNode = nodes.filter((item) => item.type == 'bpmn:startEvent')
|
||||
const findEndNode = nodes.filter((item) => item.type == 'bpmn:endEvent')
|
||||
if (findStartNode.length != 1 || findEndNode.length != 1) {
|
||||
return reject({
|
||||
message: '流程设计-流程必须有且只有一个开始节点和结束节点'
|
||||
})
|
||||
}
|
||||
|
||||
function handel(arr, pid) {
|
||||
const newArr = []
|
||||
arr.forEach((node) => {
|
||||
// console.log('sourceNodeIdSum', sourceNodeIdSum, node.id)
|
||||
const newNode = {
|
||||
id: node.id,
|
||||
pid: pid,
|
||||
label: node?.text?.value,
|
||||
type: node.type,
|
||||
fieldAuth: node?.properties?.fieldAuth,
|
||||
gateway: node?.properties?.gateway,
|
||||
|
||||
userType: node?.properties?.userType || 0,
|
||||
userId: node?.properties?.userId || 0,
|
||||
deptId: node?.properties?.deptId || 0,
|
||||
postId: node?.properties?.postId || 0
|
||||
}
|
||||
if (sourceNodeIdSum[node.id]) {
|
||||
newNode.children = handel(sourceNodeIdSum[node.id], node.id)
|
||||
}
|
||||
newArr.push(newNode)
|
||||
})
|
||||
return newArr
|
||||
}
|
||||
const TreeNode = handel(findStartNode, 0)
|
||||
|
||||
// tree转list
|
||||
function treeToList(tree) {
|
||||
const arr = []
|
||||
tree.forEach((item) => {
|
||||
arr.push(item)
|
||||
if (item.children) {
|
||||
arr.push(...treeToList(item.children))
|
||||
}
|
||||
})
|
||||
return arr
|
||||
}
|
||||
|
||||
console.log('TreeNode', TreeNode)
|
||||
console.log('treeToList', treeToList(TreeNode))
|
||||
// 检查连线方向是否正确;
|
||||
resolve({ formData: data, treeToList: treeToList(TreeNode) })
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.diagram {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.diagram-toolbar {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 20px;
|
||||
height: 40px;
|
||||
padding: 0 10px;
|
||||
/* width: 310px; */
|
||||
display: flex;
|
||||
align-items: center;
|
||||
/* border-bottom: 1px solid #e5e5e5; */
|
||||
z-index: 10;
|
||||
background: #fff;
|
||||
box-shadow: 0px 0px 4px rgba($color: #000000, $alpha: 0.5);
|
||||
}
|
||||
.diagram-main {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
|
||||
.diagram-sidebar {
|
||||
position: absolute;
|
||||
left: 20px;
|
||||
z-index: 10;
|
||||
top: 50px;
|
||||
width: 60px;
|
||||
background: #fff;
|
||||
box-shadow: 0px 0px 4px rgba($color: #000000, $alpha: 0.5);
|
||||
}
|
||||
.diagram-container {
|
||||
height: 100%;
|
||||
.diagram-wrapper {
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
.lf-diagram {
|
||||
// box-shadow: 0px 0px 4px #838284;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* 由于背景图和gird不对齐,需要css处理一下 */
|
||||
.diagram-container :v-deep .lf-background {
|
||||
left: -9px;
|
||||
}
|
||||
}
|
||||
|
||||
::-webkit-scrollbar {
|
||||
width: 9px;
|
||||
height: 9px;
|
||||
background: white;
|
||||
border-left: 1px solid #e8e8e8;
|
||||
}
|
||||
::-webkit-scrollbar-thumb {
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
border-color: #fff;
|
||||
border-radius: 6px;
|
||||
background: #c9c9c9;
|
||||
}
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
background: #b5b5b5;
|
||||
}
|
||||
</style>
|
||||
@@ -1,133 +0,0 @@
|
||||
<template>
|
||||
<el-drawer
|
||||
v-model="drawerVisible"
|
||||
size="600px"
|
||||
:title="'节点:' + node?.text?.value"
|
||||
@close="close"
|
||||
>
|
||||
<!-- fieldList:{{ fieldList }}
|
||||
<div>properties:{{ properties }}</div> -->
|
||||
|
||||
<!-- 开始节点 -->
|
||||
<!-- {{ node }} -->
|
||||
|
||||
<div v-if="node.type == 'bpmn:startEvent'">
|
||||
开始节点
|
||||
<FieldAuth :node="node" :properties="properties" :fieldList="fieldList"></FieldAuth>
|
||||
</div>
|
||||
<div v-if="node.type == 'bpmn:userTask'">
|
||||
<UserTask :node="node" :properties="properties" :fieldList="fieldList"></UserTask>
|
||||
<FieldAuth :node="node" :properties="properties" :fieldList="fieldList"></FieldAuth>
|
||||
</div>
|
||||
|
||||
<div v-if="node.type == 'bpmn:serviceTask'">
|
||||
<div>系统任务</div>
|
||||
<div>抄送</div>
|
||||
<div>发送邮件</div>
|
||||
<div>发送短信</div>
|
||||
<div>发送站内消息</div>
|
||||
<div>数据入库</div>
|
||||
</div>
|
||||
<div v-if="node.type == 'bpmn:exclusiveGateway'">
|
||||
<Gateway :node="node" :properties="properties" :fieldList="fieldList"></Gateway>
|
||||
</div>
|
||||
|
||||
<div v-if="node.type == 'bpmn:endEvent'">结束</div>
|
||||
</el-drawer>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import UserTask from './PropertyPanel/UserTask.vue'
|
||||
import FieldAuth from './PropertyPanel/FieldAuth.vue'
|
||||
import Gateway from './PropertyPanel/Gateway.vue'
|
||||
|
||||
export default {
|
||||
name: 'PropertyPanel',
|
||||
props: {},
|
||||
components: {
|
||||
UserTask,
|
||||
FieldAuth,
|
||||
Gateway
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
drawerVisible: false,
|
||||
|
||||
node: {},
|
||||
properties: {
|
||||
userType: '',
|
||||
userId: '', //审批人id
|
||||
deptId: '', //审批部门id
|
||||
postId: '', //岗位id
|
||||
|
||||
fieldAuth: {}, // 字段权限
|
||||
gateway: [] //网关条件列表
|
||||
},
|
||||
/**
|
||||
* 表单列表
|
||||
* [{
|
||||
* id: 1,
|
||||
* label: '表单1',
|
||||
* auth: 1,
|
||||
* }]
|
||||
*/
|
||||
fieldList: []
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
open(node, fieldList) {
|
||||
this.node = node
|
||||
|
||||
this.properties.userType = node?.properties?.userType || ''
|
||||
this.properties.userId = node?.properties?.userId || ''
|
||||
this.properties.deptId = node?.properties?.deptId || ''
|
||||
this.properties.postId = node?.properties?.postId || ''
|
||||
|
||||
this.properties.gateway = node?.properties?.gateway || []
|
||||
|
||||
this.properties.fieldAuth = node?.properties?.fieldAuth
|
||||
? { ...node?.properties?.fieldAuth }
|
||||
: {}
|
||||
|
||||
this.fieldList = fieldList.map((item) => {
|
||||
let auth = 1
|
||||
const formId = item?.field?.id
|
||||
if (node?.properties?.fieldAuth?.[formId]) {
|
||||
auth = node.properties.fieldAuth[formId]
|
||||
}
|
||||
return {
|
||||
id: formId,
|
||||
label: item?.field?.options?.label,
|
||||
auth: auth
|
||||
}
|
||||
})
|
||||
this.drawerVisible = true
|
||||
},
|
||||
close() {
|
||||
const fieldAuth = {}
|
||||
this.fieldList.forEach((item) => {
|
||||
fieldAuth[item.id] = item.auth
|
||||
})
|
||||
this.$emit('setProperties', this.node, { ...this.properties })
|
||||
|
||||
// this.setProperties('fieldAuth', {
|
||||
// ...fieldAuth
|
||||
// })
|
||||
// this.setProperties('userType', this.properties.userType)
|
||||
// this.setProperties('userId', this.properties.userId)
|
||||
// this.setProperties('deptId', this.properties.deptId)
|
||||
// this.setProperties('postId', this.properties.postId)
|
||||
// this.setProperties('gateway', this.properties.gateway)
|
||||
},
|
||||
|
||||
setProperties(key, val) {
|
||||
this.$emit('setProperties', this.node, {
|
||||
[key]: val
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
@@ -1,11 +1,10 @@
|
||||
<template>
|
||||
<div style="padding-bottom: 10px">
|
||||
<el-card header="条件编辑">
|
||||
<el-alert title="同一父级的网关只能有一个通过" type="warning" />
|
||||
<el-alert title="同一父级的网关只能有一个通过" type="warning" :closable="false" />
|
||||
|
||||
<!-- 设置优先级 -->
|
||||
<div style="padding: 40px 0 20px">
|
||||
<el-select v-model="selectGateway" placeholder="请选择">
|
||||
<div style="padding: 20px 0 20px" class="flex">
|
||||
<el-select class="flex-1" v-model="selectGateway" placeholder="请选择">
|
||||
<el-option
|
||||
v-for="item in fieldList"
|
||||
:key="item.id"
|
||||
@@ -24,7 +23,7 @@
|
||||
{{ getLabel(row.id) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="权限">
|
||||
<el-table-column label="判断方式">
|
||||
<template #default="{ row }">
|
||||
<el-select v-model="row.condition" placeholder="请选择判断符">
|
||||
<el-option
|
||||
@@ -53,27 +52,16 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import type { PropType } from 'vue'
|
||||
// import type { PropType } from 'vue'
|
||||
import { Close } from '@element-plus/icons-vue'
|
||||
const props = defineProps({
|
||||
node: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
},
|
||||
fieldList: {
|
||||
type: Array as PropType<
|
||||
{
|
||||
id: string
|
||||
label: string
|
||||
}[]
|
||||
>,
|
||||
default: () => []
|
||||
},
|
||||
properties: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
}
|
||||
})
|
||||
|
||||
import type { NodeType, PropertiesType, FieldListType } from './property.type'
|
||||
|
||||
const props = defineProps<{
|
||||
node?: NodeType
|
||||
fieldList?: FieldListType[]
|
||||
properties?: PropertiesType
|
||||
}>()
|
||||
const conditionList = [
|
||||
{
|
||||
value: '==',
|
||||
@@ -100,7 +88,7 @@ const selectGateway = ref('')
|
||||
function getLabel(id) {
|
||||
return props.fieldList.find((item) => {
|
||||
if (item.id === id) {
|
||||
return item.label
|
||||
return true
|
||||
}
|
||||
})?.label
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="指定部门" v-if="props.properties.userType == 1">
|
||||
<el-select
|
||||
<!-- <el-select
|
||||
v-model="props.properties.deptId"
|
||||
placeholder="请选择审批部门"
|
||||
style="width: 100%"
|
||||
@@ -25,14 +25,18 @@
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-select> -->
|
||||
<el-tree-select
|
||||
v-model="props.properties.deptId"
|
||||
:data="deptList"
|
||||
:check-strictly="true"
|
||||
default-expand-all
|
||||
:render-after-expand="false"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="岗位" v-if="[1].includes(props.properties.userType)">
|
||||
<el-select
|
||||
v-model="props.properties.postId"
|
||||
placeholder="请选择岗位"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-select v-model="props.properties.postId" placeholder="请选择岗位">
|
||||
<el-option
|
||||
v-for="item in postList"
|
||||
:key="item.value"
|
||||
@@ -63,48 +67,44 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
import { adminLists } from '@/api/perms/admin'
|
||||
import { deptLists } from '@/api/org/department'
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { adminListAll } from '@/api/perms/admin'
|
||||
import { deptAll } from '@/api/org/department'
|
||||
import { postAll } from '@/api/org/post'
|
||||
const props = defineProps({
|
||||
node: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
},
|
||||
properties: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
},
|
||||
fieldList: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
}
|
||||
})
|
||||
import { arrayToTree } from '@/utils/util'
|
||||
import type { NodeType, PropertiesType, FieldListType } from './property.type'
|
||||
|
||||
const props = defineProps<{
|
||||
node?: NodeType
|
||||
fieldList?: FieldListType[]
|
||||
properties?: PropertiesType
|
||||
}>()
|
||||
|
||||
const adminUserList = ref([])
|
||||
const deptList = ref([])
|
||||
const postList = ref([])
|
||||
|
||||
function getAdminList() {
|
||||
adminLists().then((res) => {
|
||||
adminUserList.value = res.lists.map((item) => {
|
||||
adminListAll({}).then((res) => {
|
||||
adminUserList.value = res.map((item) => {
|
||||
return {
|
||||
value: item.id,
|
||||
label: item.nickname
|
||||
label: item.nickname + ' (' + item.username + ')'
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
function getDeptList() {
|
||||
deptLists().then((res) => {
|
||||
deptList.value = res.map((item) => {
|
||||
deptAll().then((res) => {
|
||||
const list = res.map((item) => {
|
||||
return {
|
||||
value: item.id,
|
||||
label: item.name
|
||||
label: item.name,
|
||||
...item
|
||||
}
|
||||
})
|
||||
deptList.value = arrayToTree(list, '')
|
||||
})
|
||||
}
|
||||
function getPostList() {
|
||||
|
||||
97
admin/src/components/flow/flowEdit/PropertyPanel/index.vue
Normal file
97
admin/src/components/flow/flowEdit/PropertyPanel/index.vue
Normal file
@@ -0,0 +1,97 @@
|
||||
<template>
|
||||
<el-drawer
|
||||
v-model="drawerVisible"
|
||||
size="600px"
|
||||
:title="'节点:' + node?.text?.value"
|
||||
@close="close"
|
||||
>
|
||||
<div v-if="node.type == 'bpmn:startEvent'">
|
||||
<FieldAuth :node="node" :properties="properties" :fieldList="fieldList"></FieldAuth>
|
||||
</div>
|
||||
<div v-if="node.type == 'bpmn:userTask'">
|
||||
<UserTask :node="node" :properties="properties" :fieldList="fieldList"></UserTask>
|
||||
<FieldAuth :node="node" :properties="properties" :fieldList="fieldList"></FieldAuth>
|
||||
</div>
|
||||
|
||||
<div v-if="node.type == 'bpmn:serviceTask'">
|
||||
<div>(都还不支持)系统任务</div>
|
||||
<div>(都还不支持)抄送</div>
|
||||
<div>(都还不支持)发送邮件</div>
|
||||
<div>(都还不支持)发送短信</div>
|
||||
<div>(都还不支持)发送站内消息</div>
|
||||
<div>(都还不支持)数据入库</div>
|
||||
</div>
|
||||
<div v-if="node.type == 'bpmn:exclusiveGateway'">
|
||||
<Gateway :node="node" :properties="properties" :fieldList="fieldList"></Gateway>
|
||||
</div>
|
||||
|
||||
<div v-if="node.type == 'bpmn:endEvent'">结束</div>
|
||||
</el-drawer>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref, toRaw, reactive } from 'vue'
|
||||
import UserTask from './UserTask.vue'
|
||||
import FieldAuth from './FieldAuth.vue'
|
||||
import Gateway from './Gateway.vue'
|
||||
import type { NodeType, PropertiesType, FormFieldListType, FieldListType } from './property.type'
|
||||
defineOptions({
|
||||
name: 'PropertyPanel'
|
||||
})
|
||||
const emit = defineEmits(['setProperties'])
|
||||
|
||||
const drawerVisible = ref(false)
|
||||
|
||||
const node = ref<NodeType>({})
|
||||
const properties = reactive<PropertiesType>({
|
||||
userType: null,
|
||||
userId: null,
|
||||
deptId: null,
|
||||
postId: null,
|
||||
fieldAuth: {},
|
||||
gateway: []
|
||||
})
|
||||
|
||||
const fieldList = ref<FieldListType[]>([])
|
||||
|
||||
const open = (newNode: NodeType, newFieldList: FormFieldListType[]) => {
|
||||
if (newNode.type == 'bpmn:endEvent') {
|
||||
return
|
||||
}
|
||||
node.value = newNode
|
||||
|
||||
properties.userType = newNode?.properties?.userType || null
|
||||
properties.userId = newNode?.properties?.userId || null
|
||||
properties.deptId = newNode?.properties?.deptId || null
|
||||
properties.postId = newNode?.properties?.postId || null
|
||||
properties.gateway = newNode?.properties?.gateway || []
|
||||
|
||||
properties.fieldAuth = newNode?.properties?.fieldAuth
|
||||
? { ...newNode?.properties?.fieldAuth }
|
||||
: {}
|
||||
|
||||
fieldList.value = newFieldList.map((item) => {
|
||||
return {
|
||||
id: item?.field?.id,
|
||||
label: item?.field?.options?.label,
|
||||
auth: newNode?.properties?.fieldAuth?.[item?.field?.id] || 1
|
||||
}
|
||||
})
|
||||
drawerVisible.value = true
|
||||
}
|
||||
|
||||
const close = () => {
|
||||
const fieldAuth = {}
|
||||
fieldList.value.forEach((item) => {
|
||||
fieldAuth[item.id] = item.auth
|
||||
})
|
||||
properties.fieldAuth = fieldAuth
|
||||
emit('setProperties', toRaw(node.value), { ...toRaw(properties) })
|
||||
drawerVisible.value = false
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
open
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
@@ -0,0 +1,52 @@
|
||||
export type PropertiesType = {
|
||||
userType?: number
|
||||
userId?: string | number
|
||||
deptId?: string | number
|
||||
postId?: string | number
|
||||
fieldAuth?: {
|
||||
[key: string]: number
|
||||
}
|
||||
gateway?: {
|
||||
id: string
|
||||
value: string
|
||||
condition: string
|
||||
}[]
|
||||
}
|
||||
export type NodeType = {
|
||||
id?: string
|
||||
type?:
|
||||
| 'bpmn:startEvent'
|
||||
| 'bpmn:userTask'
|
||||
| 'bpmn:serviceTask'
|
||||
| 'bpmn:exclusiveGateway'
|
||||
| 'bpmn:endEvent'
|
||||
text?: {
|
||||
value?: string
|
||||
x?: number
|
||||
y?: number
|
||||
}
|
||||
properties?: PropertiesType
|
||||
x?: number
|
||||
y?: number
|
||||
}
|
||||
// Form读取读取德列表结构
|
||||
export type FormFieldListType = {
|
||||
name?: string
|
||||
type?: string
|
||||
field?: {
|
||||
id: string
|
||||
|
||||
options?: {
|
||||
name: string
|
||||
label: string
|
||||
defaultValue: ''
|
||||
}
|
||||
type?: string //'textarea'
|
||||
}
|
||||
}
|
||||
|
||||
export type FieldListType = {
|
||||
id?: string
|
||||
label?: string
|
||||
auth?: number
|
||||
}
|
||||
342
admin/src/components/flow/flowEdit/index.vue
Normal file
342
admin/src/components/flow/flowEdit/index.vue
Normal file
@@ -0,0 +1,342 @@
|
||||
<template>
|
||||
<div class="diagram">
|
||||
<diagram-toolbar
|
||||
v-if="lf"
|
||||
class="diagram-toolbar"
|
||||
:lf="lf"
|
||||
:active-edges="activeEdges"
|
||||
@saveGraph="saveGraph"
|
||||
@importData="importData"
|
||||
/>
|
||||
<div class="diagram-main">
|
||||
<diagram-sidebar class="diagram-sidebar" @dragInNode="dragInNode" />
|
||||
<div ref="container" class="diagram-container">
|
||||
<div class="diagram-wrapper">
|
||||
<div ref="diagramRef" class="lf-diagram"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Right-side property panel -->
|
||||
<PropertyPanel ref="PropertyPanelRef" @setProperties="setProperties" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
// Importing necessary functions and components
|
||||
import { ref, onMounted } from 'vue'
|
||||
import LogicFlow from '@logicflow/core'
|
||||
import { SelectionSelect, Menu, BpmnElement, MiniMap } from '@logicflow/extension'
|
||||
|
||||
// import '@logicflow/core/dist/style/index.css'
|
||||
// import '@logicflow/extension/lib/style/index.css'
|
||||
import '@logicflow/core/lib/style/index.css'
|
||||
import '@logicflow/extension/lib/style/index.css'
|
||||
|
||||
import DiagramToolbar from './DiagramToolbar.vue'
|
||||
import DiagramSidebar from './DiagramSidebar.vue'
|
||||
import PropertyPanel from './PropertyPanel/index.vue'
|
||||
import { registerCustomElement } from './node'
|
||||
|
||||
defineOptions({
|
||||
name: 'flowEdit'
|
||||
})
|
||||
// Define component props
|
||||
const props = defineProps({
|
||||
tabName: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
fieldList: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
conf: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
}
|
||||
})
|
||||
|
||||
// Define refs for reactive data and component references
|
||||
const lf = ref(null) // Reference to LogicFlow instance
|
||||
const activeEdges = ref([]) // Reactive array for active edges
|
||||
const diagramRef = ref(null) // Reference to the diagram container
|
||||
const PropertyPanelRef = ref(null) // Reference to the PropertyPanel component
|
||||
|
||||
// Lifecycle hook to initialize LogicFlow when the component is mounted
|
||||
onMounted(() => {
|
||||
initLogicFlow(props.conf)
|
||||
})
|
||||
|
||||
// Function to initialize LogicFlow
|
||||
function initLogicFlow(data) {
|
||||
// 引入框选插件
|
||||
LogicFlow.use(SelectionSelect)
|
||||
LogicFlow.use(Menu)
|
||||
LogicFlow.use(BpmnElement)
|
||||
LogicFlow.use(MiniMap)
|
||||
// Creating a new LogicFlow instance
|
||||
const logicFlowInstance = new LogicFlow({
|
||||
container: diagramRef.value, // Setting the container where LogicFlow will be rendered
|
||||
overlapMode: 1,
|
||||
// allowResize: true,
|
||||
autoWrap: true,
|
||||
adjustEdge: true,
|
||||
adjustEdgeStartAndEnd: true,
|
||||
metaKeyMultipleSelected: true,
|
||||
keyboard: {
|
||||
enabled: true
|
||||
},
|
||||
grid: {
|
||||
size: 10,
|
||||
type: 'dot'
|
||||
}
|
||||
})
|
||||
|
||||
// Setting theme for LogicFlow
|
||||
logicFlowInstance.setTheme({
|
||||
baseEdge: { strokeWidth: 1 },
|
||||
baseNode: { strokeWidth: 1 },
|
||||
nodeText: { overflowMode: 'autoWrap', lineHeight: 1.5 },
|
||||
edgeText: { overflowMode: 'autoWrap', lineHeight: 1.5 }
|
||||
})
|
||||
|
||||
// Registering custom elements for LogicFlow
|
||||
registerCustomElement(logicFlowInstance)
|
||||
|
||||
// Setting default edge type and rendering initial data
|
||||
logicFlowInstance.setDefaultEdgeType('pro-polyline')
|
||||
logicFlowInstance.extension.menu.addMenuConfig({
|
||||
nodeMenu: [
|
||||
{
|
||||
text: '属性配置',
|
||||
callback(node) {
|
||||
// alert('分享成功!')
|
||||
PropertyPanelRef.value.open(node, props.fieldList)
|
||||
}
|
||||
}
|
||||
]
|
||||
})
|
||||
logicFlowInstance.render(data)
|
||||
logicFlowInstance.extension.miniMap.show()
|
||||
// Assigning the LogicFlow instance to the 'lf' ref
|
||||
lf.value = logicFlowInstance
|
||||
|
||||
// Event listener for node clicks
|
||||
lf.value.on('node:dbclick', (e) => {
|
||||
console.log('dbclick on node', e.data, props.fieldList)
|
||||
PropertyPanelRef.value.open(e.data, props.fieldList)
|
||||
})
|
||||
}
|
||||
|
||||
// Function to handle dragging nodes into the diagram
|
||||
function dragInNode(type, text = '') {
|
||||
lf.value.dnd.startDrag({
|
||||
type,
|
||||
text
|
||||
})
|
||||
}
|
||||
|
||||
// Function to set properties of a node
|
||||
function setProperties(node, item) {
|
||||
console.log('setProperties', node, item)
|
||||
|
||||
lf.value.setProperties(node.id, item)
|
||||
}
|
||||
// function setZIndex(node, type) {
|
||||
// lf.value.setElementZIndex(node.id, type)
|
||||
// }
|
||||
// Function to import data into the LogicFlow instance
|
||||
function importData(text) {
|
||||
lf.value.renderRawData(text)
|
||||
}
|
||||
|
||||
// Function to save the graph data
|
||||
function saveGraph() {
|
||||
const data = lf.value.getGraphData()
|
||||
download('export.json', JSON.stringify(data))
|
||||
}
|
||||
|
||||
// Function to download the graph data as a file
|
||||
function download(filename, text) {
|
||||
window.sessionStorage.setItem(filename, text)
|
||||
const element = document.createElement('a')
|
||||
element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(text))
|
||||
element.setAttribute('download', filename)
|
||||
element.style.display = 'none'
|
||||
document.body.appendChild(element)
|
||||
element.click()
|
||||
document.body.removeChild(element)
|
||||
}
|
||||
async function getData() {
|
||||
/**
|
||||
* 校验目标
|
||||
* 1. 必须存在开始节点和结束节点
|
||||
* 2. 连线方向正确
|
||||
* 3. 多余的节点(不重要)
|
||||
* 4. 所有分支必须结束节点
|
||||
* 5. 检查审批节点设置情况
|
||||
* 6. 一个节点可以有多个子网关,子网关只能通过一个,不能有多个普通子节点
|
||||
*
|
||||
*/
|
||||
return new Promise<{
|
||||
formData: any
|
||||
treeToList: any
|
||||
}>((resolve, reject) => {
|
||||
const data = lf.value.getGraphData()
|
||||
const nodes = data.nodes
|
||||
const edges = data.edges
|
||||
|
||||
let haveMoreChildNode = false
|
||||
const sourceNodeIdSum = {} // Node ID -> child nodes mapping
|
||||
|
||||
edges.forEach((edge) => {
|
||||
const targetNode = nodes.find((item) => item.id === edge.targetNodeId)
|
||||
if (sourceNodeIdSum[edge.sourceNodeId]) {
|
||||
sourceNodeIdSum[edge.sourceNodeId].push(targetNode)
|
||||
for (const n of sourceNodeIdSum[edge.sourceNodeId]) {
|
||||
if (n.type !== 'bpmn:exclusiveGateway') {
|
||||
haveMoreChildNode = true
|
||||
break
|
||||
}
|
||||
}
|
||||
} else {
|
||||
sourceNodeIdSum[edge.sourceNodeId] = [targetNode]
|
||||
}
|
||||
})
|
||||
|
||||
if (haveMoreChildNode) {
|
||||
return reject({
|
||||
target: props.tabName,
|
||||
message: '流程设计-一个节点只能有一个子节点,可以有多个网关'
|
||||
})
|
||||
}
|
||||
// 检查开始节点和结束节点是否存在
|
||||
const findStartNode = nodes.filter((item) => item.type === 'bpmn:startEvent')
|
||||
const findEndNode = nodes.filter((item) => item.type === 'bpmn:endEvent')
|
||||
if (findStartNode.length !== 1 || findEndNode.length !== 1) {
|
||||
return reject({
|
||||
target: props.tabName,
|
||||
message: '流程设计-流程必须有且只有一个开始节点和结束节点'
|
||||
})
|
||||
}
|
||||
|
||||
const TreeNode = handel(nodes, 0)
|
||||
|
||||
function handel(arr, pid) {
|
||||
const newArr = []
|
||||
arr.forEach((node) => {
|
||||
const newNode = {
|
||||
id: node.id,
|
||||
pid: pid,
|
||||
label: node?.text?.value,
|
||||
type: node.type,
|
||||
fieldAuth: node?.properties?.fieldAuth,
|
||||
gateway: node?.properties?.gateway,
|
||||
|
||||
userType: node?.properties?.userType || 0,
|
||||
userId: node?.properties?.userId || 0,
|
||||
deptId: node?.properties?.deptId || 0,
|
||||
postId: node?.properties?.postId || 0,
|
||||
children: null
|
||||
}
|
||||
if (sourceNodeIdSum[node.id]) {
|
||||
newNode.children = handel(sourceNodeIdSum[node.id], node.id)
|
||||
}
|
||||
newArr.push(newNode)
|
||||
})
|
||||
return newArr
|
||||
}
|
||||
|
||||
function treeToList(tree) {
|
||||
const arr = []
|
||||
tree.forEach((item) => {
|
||||
arr.push(item)
|
||||
if (item.children) {
|
||||
arr.push(...treeToList(item.children))
|
||||
}
|
||||
})
|
||||
return arr
|
||||
}
|
||||
// 检查连线方向是否正确;
|
||||
resolve({ formData: data, treeToList: treeToList(TreeNode) })
|
||||
})
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
getData
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.diagram {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.diagram-toolbar {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 20px;
|
||||
height: 40px;
|
||||
padding: 0 10px;
|
||||
/* width: 310px; */
|
||||
display: flex;
|
||||
align-items: center;
|
||||
/* border-bottom: 1px solid #e5e5e5; */
|
||||
z-index: 10;
|
||||
background: #fff;
|
||||
box-shadow: 0px 0px 4px rgba($color: #000000, $alpha: 0.5);
|
||||
}
|
||||
.diagram-main {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
|
||||
.diagram-sidebar {
|
||||
position: absolute;
|
||||
left: 20px;
|
||||
z-index: 10;
|
||||
top: 50px;
|
||||
width: 60px;
|
||||
background: #fff;
|
||||
box-shadow: 0px 0px 4px rgba($color: #000000, $alpha: 0.5);
|
||||
}
|
||||
.diagram-container {
|
||||
height: 100%;
|
||||
.diagram-wrapper {
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
.lf-diagram {
|
||||
// box-shadow: 0px 0px 4px #838284;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* 由于背景图和gird不对齐,需要css处理一下 */
|
||||
.diagram-container :v-deep .lf-background {
|
||||
left: -9px;
|
||||
}
|
||||
}
|
||||
|
||||
::-webkit-scrollbar {
|
||||
width: 9px;
|
||||
height: 9px;
|
||||
background: white;
|
||||
border-left: 1px solid #e8e8e8;
|
||||
}
|
||||
::-webkit-scrollbar-thumb {
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
border-color: #fff;
|
||||
border-radius: 6px;
|
||||
background: #c9c9c9;
|
||||
}
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
background: #b5b5b5;
|
||||
}
|
||||
</style>
|
||||
@@ -13,8 +13,8 @@
|
||||
<script>
|
||||
import LogicFlow from '@logicflow/core'
|
||||
import { BpmnElement } from '@logicflow/extension'
|
||||
// import { SelectionSelect, Menu } from "@logicflow/extension";
|
||||
import '@logicflow/core/dist/style/index.css'
|
||||
|
||||
import '@logicflow/core/lib/style/index.css'
|
||||
import '@logicflow/extension/lib/style/index.css'
|
||||
|
||||
import { registerCustomElement } from './node'
|
||||
@@ -27,36 +27,14 @@ export default {
|
||||
lf: null,
|
||||
activeNodes: [],
|
||||
activeEdges: [],
|
||||
properties: {},
|
||||
|
||||
timer: null,
|
||||
time: 60000
|
||||
properties: {}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
// appStore: {
|
||||
// handler() {
|
||||
// if (this.lf) {
|
||||
// // this.lf.graphModel.resize();
|
||||
// // this.lf.fitView();
|
||||
// // 侧栏有动画,所以要加延时
|
||||
// setTimeout(() => {
|
||||
// this.lf.graphModel.resize();
|
||||
// this.lf.fitView();
|
||||
// }, 500);
|
||||
// }
|
||||
// },
|
||||
// deep: true,
|
||||
// },
|
||||
},
|
||||
|
||||
mounted() {
|
||||
// this.initLogicFlow(exportInfo);
|
||||
},
|
||||
beforeUnmount() {
|
||||
if (this.timer) {
|
||||
clearInterval(this.timer)
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
initLogicFlow(data) {
|
||||
// 引入框选插件
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { computed, defineComponent } from 'vue'
|
||||
// import { ElIcon } from 'element-plus'
|
||||
import { EL_ICON_PREFIX, LOCAL_ICON_PREFIX } from './index'
|
||||
import ISvgIcon from './svg-icon.vue'
|
||||
|
||||
@@ -77,6 +77,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, withDefaults } from 'vue'
|
||||
import { computed, nextTick, onMounted, reactive, shallowRef, watch } from 'vue'
|
||||
import { useEventListener } from '@vueuse/core'
|
||||
import { ElInput } from 'element-plus'
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { computed, defineComponent } from 'vue'
|
||||
import { addUnit } from '@/utils/util'
|
||||
import type { CSSProperties } from 'vue'
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, ref, watch } from 'vue'
|
||||
import type { PropType } from 'vue'
|
||||
import { LinkTypeEnum, type Link } from '.'
|
||||
import ShopPages from './shop-pages.vue'
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, shallowRef, ref, watch } from 'vue'
|
||||
import { LinkTypeEnum, type Link } from '.'
|
||||
import LinkContent from './index.vue'
|
||||
import Popup from '@/components/popup/index.vue'
|
||||
|
||||
@@ -18,8 +18,9 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref } from 'vue'
|
||||
import type { PropType } from 'vue'
|
||||
import { LinkTypeEnum, type Link } from '.'
|
||||
import { LinkTypeEnum, type Link } from './index'
|
||||
|
||||
defineProps({
|
||||
modelValue: {
|
||||
|
||||
@@ -49,7 +49,11 @@ export default defineComponent({
|
||||
position: relative;
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
@apply bg-br-extra-light border border-br-extra-light;
|
||||
|
||||
background-color: var(--el-border-color-extra-light);
|
||||
border-width: 1px;
|
||||
border-color: var(--el-border-color-extra-light);
|
||||
|
||||
.image,
|
||||
.video {
|
||||
display: block;
|
||||
|
||||
@@ -11,7 +11,8 @@ import {
|
||||
import { usePaging } from '@/hooks/usePaging'
|
||||
import feedback from '@/utils/feedback'
|
||||
import { ElMessage, ElTree, type CheckboxValueType } from 'element-plus'
|
||||
import { shallowRef, type Ref } from 'vue'
|
||||
import { shallowRef, ref, reactive } from 'vue'
|
||||
import type { Ref } from 'vue'
|
||||
|
||||
// 左侧分组的钩子函数
|
||||
export function useCate(type: number) {
|
||||
|
||||
@@ -273,6 +273,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, onMounted, toRefs, ref, watch } from 'vue'
|
||||
import { useCate, useFile } from './hook'
|
||||
import FileItem from './file.vue'
|
||||
import Preview from './preview.vue'
|
||||
|
||||
@@ -80,6 +80,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" name="material-picker">
|
||||
import { defineComponent, ref, computed, toRefs, watch, nextTick, provide } from 'vue'
|
||||
import Draggable from 'vuedraggable'
|
||||
import Popup from '@/components/popup/index.vue'
|
||||
import FileItem from './file.vue'
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, shallowRef, watch, nextTick } from 'vue'
|
||||
const props = defineProps({
|
||||
modelValue: {
|
||||
type: Boolean,
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<div
|
||||
ref="textRef"
|
||||
class="overflow-text truncate"
|
||||
:style="{ textOverflow: overfloType }"
|
||||
:style="{ textOverflow: overflowType }"
|
||||
>
|
||||
{{ content }}
|
||||
</div>
|
||||
@@ -13,6 +13,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, shallowRef } from 'vue'
|
||||
import { useEventListener } from '@vueuse/core'
|
||||
import { useTooltipContentProps, type Placement } from 'element-plus'
|
||||
import type { PropType } from 'vue'
|
||||
@@ -27,7 +28,7 @@ const props = defineProps({
|
||||
type: String as PropType<Placement>,
|
||||
default: 'top'
|
||||
},
|
||||
overfloType: {
|
||||
overflowType: {
|
||||
type: String as PropType<'ellipsis' | 'unset' | 'clip'>,
|
||||
default: 'ellipsis'
|
||||
}
|
||||
|
||||
@@ -32,14 +32,6 @@ const emit = defineEmits<{
|
||||
// (event: 'update:modelValue', value: any): void
|
||||
}>()
|
||||
const pager = defineModel<Record<string, any>>({})
|
||||
// const pager = computed({
|
||||
// get() {
|
||||
// return props.modelValue
|
||||
// },
|
||||
// set(value) {
|
||||
// emit('update:modelValue', value)
|
||||
// }
|
||||
// })
|
||||
const sizeChange = () => {
|
||||
pager.value.page = 1
|
||||
emit('change')
|
||||
|
||||
@@ -53,6 +53,7 @@
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { useEventListener } from '@vueuse/core'
|
||||
import { ref, watch } from 'vue'
|
||||
import type { PropType } from 'vue'
|
||||
|
||||
const props = defineProps({
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
:width="width"
|
||||
draggable
|
||||
:close-on-click-modal="clickModalClose"
|
||||
top="0"
|
||||
@closed="close"
|
||||
>
|
||||
<!-- 弹窗内容 -->
|
||||
@@ -39,7 +40,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { ref, provide } from 'vue'
|
||||
import { ref, provide, defineComponent, nextTick } from 'vue'
|
||||
export default defineComponent({
|
||||
props: {
|
||||
title: {
|
||||
@@ -127,8 +128,14 @@ export default defineComponent({
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.dialog-body {
|
||||
white-space: pre-line;
|
||||
<style lang="scss">
|
||||
.dialog {
|
||||
.dialog-body {
|
||||
white-space: pre-line;
|
||||
}
|
||||
.el-dialog__body {
|
||||
// max-height: calc(100vh - 200px);
|
||||
overflow: auto;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { computed, defineComponent, ref, shallowRef } from 'vue'
|
||||
import { computed, defineComponent, ref, toRaw, shallowRef } from 'vue'
|
||||
import useUserStore from '@/stores/modules/user'
|
||||
import config from '@/config'
|
||||
import feedback from '@/utils/feedback'
|
||||
|
||||
@@ -149,7 +149,7 @@ const secretKey = ref(''), //后端返回的ase加密秘钥
|
||||
blockBackImgBase = ref(''), //验证滑块的背景图片
|
||||
backToken = ref(''), //后端返回的唯一token值
|
||||
startMoveTime = ref(), //移动开始的时间
|
||||
endMovetime = ref(), //移动结束的时间
|
||||
endMoveTime = ref(), //移动结束的时间
|
||||
tipWords = ref(''),
|
||||
text = ref(''),
|
||||
finishText = ref(''),
|
||||
@@ -257,7 +257,7 @@ function move(e) {
|
||||
|
||||
//鼠标松开
|
||||
function end() {
|
||||
endMovetime.value = +new Date()
|
||||
endMoveTime.value = +new Date()
|
||||
//判断是否重合
|
||||
if (status.value && isEnd.value == false) {
|
||||
let moveLeftDistance = parseInt((moveBlockLeft.value || '').replace('px', ''))
|
||||
@@ -284,7 +284,7 @@ function end() {
|
||||
}, 1500)
|
||||
}
|
||||
passFlag.value = true
|
||||
tipWords.value = `${((endMovetime.value - startMoveTime.value) / 1000).toFixed(
|
||||
tipWords.value = `${((endMoveTime.value - startMoveTime.value) / 1000).toFixed(
|
||||
2
|
||||
)}s验证成功`
|
||||
setTimeout(() => {
|
||||
|
||||
@@ -5,8 +5,8 @@ import CryptoJS from 'crypto-js'
|
||||
* */
|
||||
export function aesEncrypt(word, keyWord = 'XwKsGlMcdPMEhR1B') {
|
||||
const key = CryptoJS.enc.Utf8.parse(keyWord)
|
||||
const srcs = CryptoJS.enc.Utf8.parse(word)
|
||||
const encrypted = CryptoJS.AES.encrypt(srcs, key, {
|
||||
const src = CryptoJS.enc.Utf8.parse(word)
|
||||
const encrypted = CryptoJS.AES.encrypt(src, key, {
|
||||
mode: CryptoJS.mode.ECB,
|
||||
padding: CryptoJS.pad.Pkcs7
|
||||
})
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import request from '@/utils/request'
|
||||
import { dictDataAll } from '@/api/setting/dict'
|
||||
import { reactive, toRaw } from 'vue'
|
||||
|
||||
@@ -38,6 +39,18 @@ export function useDictOptions<T = any>(options: Options) {
|
||||
}
|
||||
}
|
||||
|
||||
export type type_dict = {
|
||||
color?: string
|
||||
createTime?: string
|
||||
id?: number
|
||||
name?: string
|
||||
remark?: string
|
||||
sort?: number
|
||||
status?: number
|
||||
typeId?: number
|
||||
updateTime?: string
|
||||
value?: string
|
||||
}
|
||||
export function useDictData<T = any>(dict: string[]) {
|
||||
const options: Options = {}
|
||||
for (const type of dict) {
|
||||
@@ -54,4 +67,24 @@ export function useDictData<T = any>(dict: string[]) {
|
||||
}
|
||||
}
|
||||
|
||||
// export function useAllList<T = any>(options: Options) {}
|
||||
export function useListAllData<T = any>(paths: Record<string, string>) {
|
||||
const options: Options = {}
|
||||
for (const key in paths) {
|
||||
options[key] = {
|
||||
api: () => request.get({ url: paths[key], params: {} }),
|
||||
transformData: (data: any) => {
|
||||
console.log('data', data)
|
||||
|
||||
return data
|
||||
}
|
||||
|
||||
// params: {
|
||||
// dictType: path
|
||||
// }
|
||||
}
|
||||
}
|
||||
const { optionsData } = useDictOptions<T>(options)
|
||||
return {
|
||||
listAllData: optionsData
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import useTabsStore from '@/stores/modules/multipleTabs'
|
||||
import useSettingStore from '@/stores/modules/setting'
|
||||
import { computed } from 'vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
|
||||
export default function useMultipleTabs() {
|
||||
const router = useRouter()
|
||||
|
||||
@@ -9,6 +9,17 @@ interface Options {
|
||||
firstLoading?: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {object} options
|
||||
* @param {number} options.page 页码
|
||||
* @param {number} options.size 每页条数
|
||||
* @param {function} options.fetchFun 分页接口函数
|
||||
* @param {object} options.params 分页参数
|
||||
* @param {boolean} options.firstLoading 是否首次加载
|
||||
*
|
||||
*
|
||||
*/
|
||||
export function usePaging<T>(options: Options) {
|
||||
const { page = 1, size = 15, fetchFun, params = {}, firstLoading = false } = options
|
||||
// 记录分页初始参数
|
||||
@@ -51,7 +62,8 @@ export function usePaging<T>(options: Options) {
|
||||
Object.keys(paramsInit).forEach((item) => {
|
||||
params[item] = paramsInit[item]
|
||||
})
|
||||
getLists()
|
||||
|
||||
resetPage()
|
||||
}
|
||||
return {
|
||||
pager,
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { useRoute } from 'vue-router'
|
||||
import { watch } from 'vue'
|
||||
import type { RouteLocationNormalizedLoaded } from 'vue-router'
|
||||
|
||||
export function useWatchRoute(callback: (route: RouteLocationNormalizedLoaded) => void) {
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import { RouterView } from 'vue-router'
|
||||
import useAppStore from '@/stores/modules/app'
|
||||
import useTabsStore from '@/stores/modules/multipleTabs'
|
||||
import useSettingStore from '@/stores/modules/setting'
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import useAppStore from '@/stores/modules/app'
|
||||
|
||||
const appStore = useAppStore()
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
</el-breadcrumb>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import { useWatchRoute } from '@/hooks/useWatchRoute'
|
||||
import type { RouteLocationMatched, RouteLocationNormalizedLoaded } from 'vue-router'
|
||||
const breadcrumbs = ref<RouteLocationMatched[]>([])
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import useAppStore from '@/stores/modules/app'
|
||||
const appStore = useAppStore()
|
||||
const isCollapsed = computed(() => appStore.isCollapsed)
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import useAppStore from '@/stores/modules/app'
|
||||
import Fold from './fold.vue'
|
||||
import Refresh from './refresh.vue'
|
||||
@@ -50,9 +51,17 @@ const settingStore = useSettingStore()
|
||||
<style lang="scss">
|
||||
.navbar {
|
||||
height: var(--navbar-height);
|
||||
@apply flex px-2 bg-body;
|
||||
|
||||
display: flex;
|
||||
padding-left: 8px;
|
||||
padding-right: 8px;
|
||||
background-color: var(--el-bg-color);
|
||||
.navbar-item {
|
||||
@apply h-full flex justify-center items-center hover:bg-page;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
background-color: var(--el-bg-color-page);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useRouter } from 'vue-router'
|
||||
import useMultipleTabs from '@/hooks/useMultipleTabs'
|
||||
import { useWatchRoute } from '@/hooks/useWatchRoute'
|
||||
import useTabsStore, { getRouteParams } from '@/stores/modules/multipleTabs'
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import useUserStore from '@/stores/modules/user'
|
||||
import feedback from '@/utils/feedback'
|
||||
const userStore = useUserStore()
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import { RouterView } from 'vue-router'
|
||||
import useAppStore from '@/stores/modules/app'
|
||||
import useTabsStore from '@/stores/modules/multipleTabs'
|
||||
import useSettingStore from '@/stores/modules/setting'
|
||||
|
||||
@@ -83,6 +83,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, ref } from 'vue'
|
||||
import useSettingStore from '@/stores/modules/setting'
|
||||
import { useDark, useToggle } from '@vueuse/core'
|
||||
import theme_light from '@/assets/images/theme_white.png'
|
||||
@@ -214,7 +215,10 @@ const resetTheme = () => {
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.icon-select {
|
||||
@apply absolute left-1/2 top-1/2;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<el-drawer
|
||||
v-model="showMenuDrawer"
|
||||
direction="ltr"
|
||||
:size="drawderSize"
|
||||
:size="drawerSize"
|
||||
title="主题设置"
|
||||
:with-header="false"
|
||||
>
|
||||
@@ -14,6 +14,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import Side from './side.vue'
|
||||
import useAppStore from '@/stores/modules/app'
|
||||
import useSettingStore from '@/stores/modules/setting'
|
||||
@@ -32,7 +33,7 @@ const showMenuDrawer = computed({
|
||||
}
|
||||
})
|
||||
|
||||
const drawderSize = computed(() => {
|
||||
const drawerSize = computed(() => {
|
||||
return `${settingStore.sideWidth + 1}px`
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
<template>
|
||||
<div class="logo">
|
||||
<image-contain :width="szie" :height="szie" :src="config.webLogo" />
|
||||
<image-contain :width="size" :height="size" :src="config.webLogo" />
|
||||
<transition name="title-width">
|
||||
<div
|
||||
v-show="showTitle"
|
||||
class="logo-title overflow-hidden whitespace-nowrap"
|
||||
:class="{ 'text-white': theme == ThemeEnum.DARK }"
|
||||
:style="{ left: `${szie + 16}px` }"
|
||||
:style="{ left: `${size + 16}px` }"
|
||||
>
|
||||
<overflow-tooltip
|
||||
:content="title || config.webName"
|
||||
:teleported="true"
|
||||
placement="bottom"
|
||||
overflo-type="unset"
|
||||
overflow-type="unset"
|
||||
>
|
||||
</overflow-tooltip>
|
||||
</div>
|
||||
@@ -21,13 +21,14 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import useAppStore from '@/stores/modules/app'
|
||||
import { ThemeEnum } from '@/enums/appEnums'
|
||||
defineOptions({
|
||||
name: 'SideLogo'
|
||||
})
|
||||
defineProps({
|
||||
szie: { type: Number, default: 34 },
|
||||
size: { type: Number, default: 34 },
|
||||
title: { type: String },
|
||||
theme: { type: String },
|
||||
showTitle: { type: Boolean, default: true }
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed } from 'vue'
|
||||
import { getNormalPath, objectToQuery } from '@/utils/util'
|
||||
import { isExternal } from '@/utils/validate'
|
||||
import type { RouteRecordRaw } from 'vue-router'
|
||||
|
||||
@@ -27,6 +27,8 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import type { PropType } from 'vue'
|
||||
import { computed } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
import MenuItem from './menu-item.vue'
|
||||
import type { RouteRecordRaw } from 'vue-router'
|
||||
defineOptions({
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import type { RouteRecordRaw } from 'vue-router'
|
||||
import useAppStore from '@/stores/modules/app'
|
||||
import useSettingStore from '@/stores/modules/setting'
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { getConfig } from '@/api/app'
|
||||
import { defineStore } from 'pinia'
|
||||
import { nextTick } from 'vue'
|
||||
interface AppSate {
|
||||
config: Record<string, any>
|
||||
isMobile: boolean
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { unref } from 'vue'
|
||||
import { defineStore } from 'pinia'
|
||||
import { isExternal } from '@/utils/validate'
|
||||
import type {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { defineStore } from 'pinia'
|
||||
import defaultSetting from '@/config/setting'
|
||||
import cache from '@/utils/cache'
|
||||
import { isObject } from '@vue/shared'
|
||||
import { isObject } from '@/utils/util'
|
||||
import { setTheme } from '@/utils/theme'
|
||||
import { SETTING_KEY } from '@/enums/cacheEnums'
|
||||
const storageSetting = cache.get(SETTING_KEY)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
.x-loading {
|
||||
background-color: #17607d;
|
||||
background-color: #6676fe;
|
||||
|
||||
position: fixed;
|
||||
height: 100%;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { isObject } from '@vue/shared'
|
||||
// import { isObject } from '@vue/shared'
|
||||
import { cloneDeep } from 'lodash-es'
|
||||
// import { md5 } from 'js-md5'
|
||||
import MD5 from 'crypto-js/md5'
|
||||
@@ -21,14 +21,19 @@ export const addUnit = (value: string | number, unit = 'px') => {
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 添加单位
|
||||
* @param {unknown} value
|
||||
* @description 是否为空
|
||||
* @param {any} value
|
||||
* @return {Boolean}
|
||||
*/
|
||||
export const isEmpty = (value: unknown) => {
|
||||
return value == null && typeof value == 'undefined'
|
||||
export const isEmpty = (value: any) => {
|
||||
return value === '' || value === null || value === undefined
|
||||
}
|
||||
/**
|
||||
* 判读是否为对象
|
||||
*/
|
||||
export const isObject = (val: any): boolean => {
|
||||
return val !== null && typeof val === 'object'
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 树转数组,队列实现广度优先遍历
|
||||
* @param {Array} data 数据
|
||||
@@ -134,3 +139,15 @@ export const getNonDuplicateID = (length = 8) => {
|
||||
export const firstToUpperCase = (str = '') => {
|
||||
return str.toLowerCase().replace(/( |^)[a-z]/g, ($1) => $1.toUpperCase())
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 清空对象空值属性
|
||||
*/
|
||||
export const clearEmpty = (obj: Record<string, any>) => {
|
||||
for (const key of Object.keys(obj)) {
|
||||
if (isEmpty(obj[key])) {
|
||||
delete obj[key]
|
||||
}
|
||||
}
|
||||
return obj
|
||||
}
|
||||
|
||||
@@ -103,6 +103,7 @@
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, onMounted, reactive, shallowRef } from 'vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import type { InputInstance, FormInstance } from 'element-plus'
|
||||
import LayoutFooter from '@/layout/components/footer.vue'
|
||||
import useAppStore from '@/stores/modules/app'
|
||||
@@ -113,7 +114,7 @@ import { PageEnum } from '@/enums/pageEnum'
|
||||
import { useLockFn } from '@/hooks/useLockFn'
|
||||
import { encryptPassword } from '@/utils/util'
|
||||
import Verify from '@/components/verify/Verify.vue'
|
||||
|
||||
import ImageContain from '@/components/image-contain/index.vue'
|
||||
// const verifyRef = ref(null)
|
||||
const verifyRef = shallowRef<InstanceType<typeof Verify>>()
|
||||
const onShowCaptcha = () => {
|
||||
@@ -190,7 +191,8 @@ onMounted(() => {
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.login {
|
||||
background-image: url('./images/login_bg.png');
|
||||
// background-image: url('./images/login_bg.png');
|
||||
background-color: #f8f8f8;
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
height: 100vh;
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { ref, computed, shallowRef, reactive } from 'vue'
|
||||
import type { FormInstance } from 'element-plus'
|
||||
import { articleCateEdit, articleCateAdd, articleCateDetail } from '@/api/article'
|
||||
import Popup from '@/components/popup/index.vue'
|
||||
|
||||
@@ -66,6 +66,7 @@
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { ref, shallowRef, nextTick } from 'vue'
|
||||
import { articleCateDelete, articleCateLists, articleCateStatus } from '@/api/article'
|
||||
import { usePaging } from '@/hooks/usePaging'
|
||||
import feedback from '@/utils/feedback'
|
||||
|
||||
@@ -112,6 +112,8 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { reactive, shallowRef } from 'vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import type { FormInstance } from 'element-plus'
|
||||
import feedback from '@/utils/feedback'
|
||||
import { useDictOptions } from '@/hooks/useDictOptions'
|
||||
|
||||
@@ -87,6 +87,7 @@
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup name="articleLists">
|
||||
import { reactive, onActivated } from 'vue'
|
||||
import { articleLists, articleDelete, articleStatus, articleCateAll } from '@/api/article'
|
||||
import { useDictOptions } from '@/hooks/useDictOptions'
|
||||
import { usePaging } from '@/hooks/usePaging'
|
||||
|
||||
@@ -29,6 +29,7 @@ import {
|
||||
} from '@/api/article_collect'
|
||||
import Popup from '@/components/popup/index.vue'
|
||||
import feedback from '@/utils/feedback'
|
||||
import { computed, reactive, ref, shallowRef } from 'vue'
|
||||
import type { PropType } from 'vue'
|
||||
defineProps({
|
||||
dictData: {
|
||||
|
||||
@@ -61,6 +61,7 @@
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { shallowRef, ref, reactive, nextTick } from 'vue'
|
||||
import { article_collect_delete, article_collect_lists } from '@/api/article_collect'
|
||||
import { usePaging } from '@/hooks/usePaging'
|
||||
import feedback from '@/utils/feedback'
|
||||
|
||||
@@ -84,6 +84,8 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { useRoute } from 'vue-router'
|
||||
import { shallowRef, reactive } from 'vue'
|
||||
import type { FormInstance } from 'element-plus'
|
||||
import { getUserDetail, userEdit } from '@/api/consumer'
|
||||
import feedback from '@/utils/feedback'
|
||||
|
||||
@@ -54,6 +54,7 @@
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { reactive, onActivated } from 'vue'
|
||||
import { usePaging } from '@/hooks/usePaging'
|
||||
|
||||
import { getUserList } from '@/api/consumer'
|
||||
|
||||
@@ -66,14 +66,14 @@
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="字段管理" name="column">
|
||||
<el-table :data="formData.column">
|
||||
<el-table-column label="字段列名" prop="columnName" />
|
||||
<el-table-column label="字段列名" prop="columnName" min-width="120" />
|
||||
<el-table-column label="字段描述" prop="columnComment" min-width="120">
|
||||
<template v-slot="{ row }">
|
||||
<el-input v-model="row.columnComment"></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="sql类型" prop="columnType" min-width="100" />
|
||||
<el-table-column label="go类型" min-width="100">
|
||||
<el-table-column label="go类型" min-width="140">
|
||||
<template v-slot="{ row }">
|
||||
<el-select v-model="row.goType">
|
||||
<el-option label="int" value="int" />
|
||||
@@ -82,7 +82,7 @@
|
||||
<el-option label="float64" value="float64" />
|
||||
<el-option label="rune" value="rune" />
|
||||
<el-option label="bool" value="bool" />
|
||||
<el-option label="TsTime" value="core.TsTime" />
|
||||
<el-option label="NullTime" value="core.NullTime" />
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
@@ -136,7 +136,7 @@
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="查询方式">
|
||||
<el-table-column label="查询方式" min-width="140">
|
||||
<template v-slot="{ row }">
|
||||
<el-select v-model="row.queryType">
|
||||
<el-option label="=" value="EQ" />
|
||||
@@ -150,7 +150,7 @@
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="显示类型" min-width="120">
|
||||
<el-table-column label="显示类型" min-width="140">
|
||||
<template v-slot="{ row }">
|
||||
<el-select v-model="row.htmlType">
|
||||
<el-option label="文本框" value="input" />
|
||||
@@ -165,19 +165,19 @@
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="字典类型" min-width="120">
|
||||
<el-table-column label="字典类型" min-width="140">
|
||||
<template v-slot="{ row }">
|
||||
<el-select
|
||||
v-model="row.dictType"
|
||||
clearable
|
||||
:disabled="
|
||||
!(
|
||||
row.htmlType == 'select' ||
|
||||
v-if="
|
||||
(row.htmlType == 'select' ||
|
||||
row.htmlType == 'radio' ||
|
||||
row.htmlType == 'checkbox'
|
||||
)
|
||||
row.htmlType == 'checkbox') &&
|
||||
!row.listAllApi
|
||||
"
|
||||
placeholder="字典类型"
|
||||
@change="row.listAllApi = null"
|
||||
>
|
||||
<el-option
|
||||
v-for="(item, index) in optionsData.dictType"
|
||||
@@ -189,6 +189,31 @@
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="数据来源(字典类型优先)" min-width="280">
|
||||
<template v-slot="{ row }">
|
||||
<el-select
|
||||
v-model="row.listAllApi"
|
||||
clearable
|
||||
filterable
|
||||
v-if="
|
||||
(row.htmlType == 'select' ||
|
||||
row.htmlType == 'radio' ||
|
||||
row.htmlType == 'checkbox') &&
|
||||
!row.dictType
|
||||
"
|
||||
placeholder="字典类型"
|
||||
@change="row.dictType = null"
|
||||
>
|
||||
<el-option
|
||||
v-for="(item, index) in optionsData.ApiList"
|
||||
:key="index"
|
||||
:label="item"
|
||||
:value="item"
|
||||
/>
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="生成配置" name="config">
|
||||
@@ -265,11 +290,15 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { ref, reactive, shallowRef } from 'vue'
|
||||
|
||||
import { generateEdit, tableDetail } from '@/api/tools/code'
|
||||
import { dictTypeAll } from '@/api/setting/dict'
|
||||
import type { FormInstance } from 'element-plus'
|
||||
import feedback from '@/utils/feedback'
|
||||
import { menuLists } from '@/api/perms/menu'
|
||||
import { getApiList } from '@/api/setting/website'
|
||||
import { useDictOptions } from '@/hooks/useDictOptions'
|
||||
import useMultipleTabs from '@/hooks/useMultipleTabs'
|
||||
enum GenTpl {
|
||||
@@ -332,6 +361,7 @@ const getDetails = async () => {
|
||||
const { optionsData } = useDictOptions<{
|
||||
dictType: any[]
|
||||
menu: any[]
|
||||
ApiList: string[]
|
||||
}>({
|
||||
dictType: {
|
||||
api: dictTypeAll
|
||||
@@ -343,6 +373,14 @@ const { optionsData } = useDictOptions<{
|
||||
menu.children = data
|
||||
return menu
|
||||
}
|
||||
},
|
||||
ApiList: {
|
||||
api: getApiList,
|
||||
transformData(data: any) {
|
||||
return data.filter((item: any) => {
|
||||
return item.endsWith('listAll')
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@@ -144,6 +144,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, reactive, onActivated } from 'vue'
|
||||
import {
|
||||
generateTable,
|
||||
syncColumn,
|
||||
|
||||
@@ -1,7 +1,13 @@
|
||||
<template>
|
||||
<div class="code-preview">
|
||||
<el-dialog v-model="show" width="95%" title="代码预览">
|
||||
<el-container style="height: 75vh">
|
||||
<el-dialog
|
||||
v-model="show"
|
||||
width="98%"
|
||||
:title="'代码预览【' + showItem.label + '】'"
|
||||
top="0px"
|
||||
draggable
|
||||
>
|
||||
<el-container style="max-height: calc(100vh - 200px)">
|
||||
<el-aside
|
||||
width="400px"
|
||||
style="padding: 10px 0; margin-right: 20px; border: 1px solid #dcdfe6"
|
||||
@@ -15,7 +21,7 @@
|
||||
</el-aside>
|
||||
<el-main style="padding: 0; border: 1px solid #dcdfe6">
|
||||
<div class="flex flex-col h-[100%]">
|
||||
<div class="flex">
|
||||
<!-- <div class="flex">
|
||||
<div class="flex-1 p-4">{{ showItem.label }}</div>
|
||||
<div>
|
||||
<el-button @click="handleCopy(showItem.value)" type="primary" link>
|
||||
@@ -25,19 +31,38 @@
|
||||
复制
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div> -->
|
||||
|
||||
<div class="flex-1 overflow-auto">
|
||||
<highlightjs autodetect :code="showItem.value" language="javascript" />
|
||||
<div style="height: calc(100vh - 200px)">
|
||||
<highlightjs
|
||||
autodetect
|
||||
:code="showItem.value"
|
||||
language="javascript"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-main>
|
||||
</el-container>
|
||||
<template v-slot:footer>
|
||||
<div>
|
||||
<!-- {{ showItem.label }} -->
|
||||
<el-button
|
||||
icon="el-icon-CopyDocument"
|
||||
type="primary"
|
||||
@click="handleCopy(showItem.value)"
|
||||
>复制</el-button
|
||||
>
|
||||
<el-button @click="show = false">关闭</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, ref, computed } from 'vue'
|
||||
import feedback from '@/utils/feedback'
|
||||
import useClipboard from 'vue-clipboard3'
|
||||
|
||||
@@ -110,3 +135,9 @@ const show = computed<boolean>({
|
||||
}
|
||||
})
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.code-preview .el-dialog__body {
|
||||
// max-height: calc(100vh - 200px);
|
||||
overflow: auto;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -44,6 +44,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { shallowRef, reactive, watch, ref } from 'vue'
|
||||
import Popup from '@/components/popup/index.vue'
|
||||
import Pagination from '@/components/pagination/index.vue'
|
||||
import { usePaging } from '@/hooks/usePaging'
|
||||
|
||||
@@ -25,7 +25,11 @@
|
||||
<!-- {{ historyList }} -->
|
||||
<template #footer>
|
||||
<el-button @click="dialogVisible = false">关闭</el-button>
|
||||
<el-button v-if="applyDetail.status == 1" type="primary" @click="onSubmit">
|
||||
<el-button
|
||||
v-if="applyDetail.status == 1 || applyDetail.status == 4"
|
||||
type="primary"
|
||||
@click="onSubmit"
|
||||
>
|
||||
确定
|
||||
</el-button>
|
||||
</template>
|
||||
@@ -33,7 +37,7 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
import { ref, reactive } from 'vue'
|
||||
import 'vform3-builds/dist/designer.style.css' //引入VForm3样式
|
||||
|
||||
import { flow_history_list_all } from '@/api/flow/flow_history'
|
||||
|
||||
@@ -48,13 +48,13 @@
|
||||
|
||||
<template #footer>
|
||||
<el-button @click="dialogVisible = false">关闭</el-button>
|
||||
<el-button type="primary" @click="submit"> 通过 </el-button>
|
||||
<el-button type="primary" @click="submit"> 确定 </el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import { ref, reactive, computed } from 'vue'
|
||||
import feedback from '@/utils/feedback'
|
||||
import {
|
||||
flow_history_next_node,
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
import type { FormInstance } from 'element-plus'
|
||||
import { flow_apply_edit, flow_apply_add, flow_apply_detail } from '@/api/flow/flow_apply'
|
||||
import { flow_template_lists_all } from '@/api/flow/flow_template'
|
||||
import type { type_flow_template } from '@/api/flow/flow_template'
|
||||
|
||||
import Popup from '@/components/popup/index.vue'
|
||||
import feedback from '@/utils/feedback'
|
||||
@@ -143,7 +144,7 @@ const formRules = {
|
||||
}
|
||||
]
|
||||
}
|
||||
const flow_template = ref([])
|
||||
const flow_template = ref<type_flow_template[]>([])
|
||||
const get_flow_template = async () => {
|
||||
flow_template.value = await flow_template_lists_all()
|
||||
}
|
||||
|
||||
@@ -101,12 +101,14 @@
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { shallowRef, reactive } from 'vue'
|
||||
import {
|
||||
flow_apply_delete,
|
||||
flow_apply_lists,
|
||||
flow_apply_edit,
|
||||
flow_apply_detail
|
||||
} from '@/api/flow/flow_apply'
|
||||
import type { type_flow_apply } from '@/api/flow/flow_apply'
|
||||
|
||||
import { useDictData } from '@/hooks/useDictOptions'
|
||||
import { usePaging } from '@/hooks/usePaging'
|
||||
@@ -131,7 +133,7 @@ const queryParams = reactive({
|
||||
status: '3'
|
||||
})
|
||||
|
||||
const { pager, getLists, resetPage, resetParams } = usePaging({
|
||||
const { pager, getLists, resetPage, resetParams } = usePaging<type_flow_apply>({
|
||||
fetchFun: flow_apply_lists,
|
||||
params: queryParams
|
||||
})
|
||||
@@ -142,7 +144,7 @@ const { dictData } = useDictData<{
|
||||
|
||||
const handleDelete = async (id: number) => {
|
||||
await feedback.confirm('确定要删除?')
|
||||
await flow_apply_delete({ id })
|
||||
await flow_apply_delete(id)
|
||||
feedback.msgSuccess('删除成功')
|
||||
getLists()
|
||||
}
|
||||
|
||||
@@ -84,10 +84,10 @@
|
||||
link
|
||||
@click="OpenViewForm(row)"
|
||||
>
|
||||
{{ row.status == 1 ? '编辑' : '预览' }}
|
||||
{{ row.status == 1 || row.status == 4 ? '编辑' : '预览' }}
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="row.status == 1 && row.formValue"
|
||||
v-if="(row.status == 1 || row.status == 4) && row.formValue"
|
||||
v-perms="['admin:flow:flow_apply:edit']"
|
||||
type="primary"
|
||||
link
|
||||
@@ -136,6 +136,7 @@
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { ref, reactive, shallowRef, nextTick } from 'vue'
|
||||
import {
|
||||
flow_apply_delete,
|
||||
flow_apply_lists,
|
||||
@@ -143,7 +144,10 @@ import {
|
||||
flow_apply_detail
|
||||
} from '@/api/flow/flow_apply'
|
||||
|
||||
import type { type_flow_apply } from '@/api/flow/flow_apply'
|
||||
|
||||
import { useDictData } from '@/hooks/useDictOptions'
|
||||
import type { type_dict } from '@/hooks/useDictOptions'
|
||||
import { usePaging } from '@/hooks/usePaging'
|
||||
import feedback from '@/utils/feedback'
|
||||
import EditPopup from './edit.vue'
|
||||
@@ -174,13 +178,13 @@ const queryParams = reactive({
|
||||
status: ''
|
||||
})
|
||||
|
||||
const { pager, getLists, resetPage, resetParams } = usePaging({
|
||||
const { pager, getLists, resetPage, resetParams } = usePaging<type_flow_apply>({
|
||||
fetchFun: flow_apply_lists,
|
||||
params: queryParams
|
||||
})
|
||||
const { dictData } = useDictData<{
|
||||
flow_apply_status: any[]
|
||||
flow_group: any[]
|
||||
flow_apply_status: type_dict[]
|
||||
flow_group: type_dict[]
|
||||
}>(['flow_apply_status', 'flow_group'])
|
||||
|
||||
const handleAdd = async () => {
|
||||
@@ -198,7 +202,7 @@ const handleAdd = async () => {
|
||||
|
||||
const handleDelete = async (id: number) => {
|
||||
await feedback.confirm('确定要删除?')
|
||||
await flow_apply_delete({ id })
|
||||
await flow_apply_delete(id)
|
||||
feedback.msgSuccess('删除成功')
|
||||
getLists()
|
||||
}
|
||||
|
||||
@@ -63,6 +63,8 @@ const props = defineProps({
|
||||
default: true
|
||||
}
|
||||
})
|
||||
const emit = defineEmits(['close'])
|
||||
|
||||
const dialogVisible = ref(false)
|
||||
// const props = defineProps({
|
||||
// save: {
|
||||
@@ -105,6 +107,7 @@ function open(applyId) {
|
||||
}
|
||||
function BeforeClose() {
|
||||
dialogVisible.value = false
|
||||
emit('close')
|
||||
}
|
||||
function submit() {
|
||||
flow_history_back(formData).then(() => {
|
||||
|
||||
@@ -99,7 +99,8 @@ function onSubmit() {
|
||||
defineExpose({
|
||||
open,
|
||||
disableWidgets,
|
||||
hideWidgets
|
||||
hideWidgets,
|
||||
closeFn
|
||||
})
|
||||
</script>
|
||||
|
||||
|
||||
151
admin/src/views/flow/flow_history/components/apply_submit.vue
Normal file
151
admin/src/views/flow/flow_history/components/apply_submit.vue
Normal file
@@ -0,0 +1,151 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
v-model="dialogVisible"
|
||||
:fullscreen="false"
|
||||
:close-on-click-modal="false"
|
||||
:close-on-press-escape="false"
|
||||
:destroy-on-close="true"
|
||||
:title="title"
|
||||
top="1px"
|
||||
>
|
||||
<el-form
|
||||
ref="formRef"
|
||||
:model="formData"
|
||||
label-position="top"
|
||||
label-width="110px"
|
||||
:rules="formRules"
|
||||
>
|
||||
<!-- {{ userTask }} -->
|
||||
<el-form-item v-if="userTask" :label="`${userTask?.label}节点审批人`" prop="templateId">
|
||||
<el-select
|
||||
style="width: 100%"
|
||||
v-if="approverUserList.length"
|
||||
v-model="formData.applyUserId"
|
||||
placeholder="请选择审批人"
|
||||
>
|
||||
<el-option
|
||||
v-for="(item, index) in approverUserList"
|
||||
:key="index"
|
||||
:label="item.nickname"
|
||||
:value="item.id"
|
||||
clearable
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="审批意见" prop="passRemark" v-if="props.showRemark">
|
||||
<el-input
|
||||
v-model="formData.passRemark"
|
||||
:rows="2"
|
||||
type="textarea"
|
||||
placeholder="请输入审批意见"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<!-- <el-steps direction="horizontal" :active="next_nodes.length">
|
||||
<el-step :title="node.label" v-for="node of next_nodes" :key="node.id" />
|
||||
</el-steps> -->
|
||||
|
||||
<template #footer>
|
||||
<el-button @click="dialogVisible = false">关闭</el-button>
|
||||
<el-button type="primary" @click="submit"> 通过 </el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, computed } from 'vue'
|
||||
import feedback from '@/utils/feedback'
|
||||
import {
|
||||
flow_history_next_node,
|
||||
flow_history_get_approver,
|
||||
flow_history_pass
|
||||
} from '@/api/flow/flow_history'
|
||||
const props = defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
showRemark: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
})
|
||||
const dialogVisible = ref(false)
|
||||
// const props = defineProps({
|
||||
// save: {
|
||||
// type: Function,
|
||||
// default: () => {}
|
||||
// }
|
||||
// })
|
||||
|
||||
class formDataState {
|
||||
id = ''
|
||||
passRemark = ''
|
||||
applyUserId = ''
|
||||
}
|
||||
const formData = reactive(new formDataState())
|
||||
const next_nodes = ref([])
|
||||
const userTask = computed(() => {
|
||||
return next_nodes.value.find((item) => item.type == 'bpmn:userTask')
|
||||
})
|
||||
const approverUserList = ref([])
|
||||
const formRules = {
|
||||
applyUserId: [
|
||||
{
|
||||
required: true,
|
||||
message: '请选择',
|
||||
trigger: ['blur']
|
||||
}
|
||||
]
|
||||
}
|
||||
function open(applyId) {
|
||||
console.log('open')
|
||||
Object.assign(formData, new formDataState())
|
||||
formData.id = applyId
|
||||
dialogVisible.value = true
|
||||
|
||||
flow_history_next_node({
|
||||
applyId: applyId
|
||||
}).then((res) => {
|
||||
console.log('res', res)
|
||||
next_nodes.value = res
|
||||
})
|
||||
flow_history_get_approver({ applyId: applyId }).then((user) => {
|
||||
console.log('user', user)
|
||||
approverUserList.value = user
|
||||
if (user && user.length == 1) {
|
||||
formData.applyUserId = user[0].id
|
||||
}
|
||||
})
|
||||
}
|
||||
function BeforeClose() {
|
||||
dialogVisible.value = false
|
||||
|
||||
// formData = {}
|
||||
}
|
||||
function submit() {
|
||||
console.log('submit', next_nodes)
|
||||
|
||||
if (userTask.value && !formData.applyUserId) {
|
||||
feedback.msgWarning('请选择审批人')
|
||||
return
|
||||
}
|
||||
flow_history_pass({
|
||||
applyId: formData.id,
|
||||
nextNodeAdminId: formData.applyUserId || 0,
|
||||
passRemark: formData.passRemark
|
||||
}).then(() => {
|
||||
BeforeClose()
|
||||
})
|
||||
}
|
||||
defineExpose({
|
||||
open
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
// body {
|
||||
// margin: 0; /* 如果页面出现垂直滚动条,则加入此行CSS以消除之 */
|
||||
// }
|
||||
</style>
|
||||
@@ -64,15 +64,15 @@
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<!-- <Approve ref="ApproveRef"></Approve> -->
|
||||
|
||||
<ViewForm ref="viewFormRef"></ViewForm>
|
||||
<!-- <ApplySubmit ref="ApplySubmitRef" title="审批" @close="getLists"></ApplySubmit> -->
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { shallowRef, reactive } from 'vue'
|
||||
import { flow_apply_detail } from '@/api/flow/flow_apply'
|
||||
import { flow_history_list } from '@/api/flow/flow_history'
|
||||
import type { type_flow_apply } from '@/api/flow/flow_apply'
|
||||
|
||||
import { useDictData } from '@/hooks/useDictOptions'
|
||||
import { usePaging } from '@/hooks/usePaging'
|
||||
import useUserStore from '@/stores/modules/user'
|
||||
@@ -82,7 +82,7 @@ import ViewForm from './components/ViewForm.vue'
|
||||
const userStore = useUserStore()
|
||||
|
||||
defineOptions({
|
||||
name: 'todo'
|
||||
name: 'done'
|
||||
})
|
||||
const ApproveRef = shallowRef<InstanceType<typeof ApproveRef>>()
|
||||
const viewFormRef = shallowRef<InstanceType<typeof ViewForm>>()
|
||||
@@ -95,7 +95,7 @@ const queryParams = reactive({
|
||||
passStatus: 2
|
||||
})
|
||||
|
||||
const { pager, getLists, resetPage, resetParams } = usePaging({
|
||||
const { pager, getLists, resetPage, resetParams } = usePaging<type_flow_apply>({
|
||||
fetchFun: flow_history_list,
|
||||
params: queryParams
|
||||
})
|
||||
|
||||
@@ -63,19 +63,21 @@
|
||||
|
||||
<ViewForm ref="viewFormRef" :save="SaveViewForm" @back="OpenBack"></ViewForm>
|
||||
|
||||
<Back ref="backRef"></Back>
|
||||
<Back ref="backRef" @close="closeBack"></Back>
|
||||
|
||||
<ApplySubmit ref="ApplySubmitRef" title="审批" @close="getLists"></ApplySubmit>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { shallowRef, reactive, defineOptions } from 'vue'
|
||||
import { flow_apply_detail } from '@/api/flow/flow_apply'
|
||||
import { flow_history_list, flow_history_edit } from '@/api/flow/flow_history'
|
||||
import type { type_flow_history } from '@/api/flow/flow_history'
|
||||
import { useDictData } from '@/hooks/useDictOptions'
|
||||
import { usePaging } from '@/hooks/usePaging'
|
||||
import feedback from '@/utils/feedback'
|
||||
import useUserStore from '@/stores/modules/user'
|
||||
import ApplySubmit from '@/views/flow/flow_apply/components/apply_submit.vue'
|
||||
import ApplySubmit from './components/apply_submit.vue'
|
||||
import ViewForm from './components/ViewForm.vue'
|
||||
import Back from './components/Back.vue'
|
||||
const userStore = useUserStore()
|
||||
@@ -94,7 +96,7 @@ const queryParams = reactive({
|
||||
passStatus: 1
|
||||
})
|
||||
|
||||
const { pager, getLists, resetPage, resetParams } = usePaging({
|
||||
const { pager, getLists, resetPage, resetParams } = usePaging<type_flow_history>({
|
||||
fetchFun: flow_history_list,
|
||||
params: queryParams
|
||||
})
|
||||
@@ -134,7 +136,7 @@ const SaveViewForm = (historyId, form_data) => {
|
||||
feedback.msgSuccess('保存成功')
|
||||
await getLists()
|
||||
|
||||
const row = pager.lists.find((item) => item.id === historyId)
|
||||
const row = pager.lists.find((item: any) => item.id === historyId)
|
||||
|
||||
OpenApplySubmit(row)
|
||||
resolve(true)
|
||||
@@ -155,6 +157,11 @@ const OpenBack = async (row: any) => {
|
||||
|
||||
backRef.value?.open(row.applyId)
|
||||
}
|
||||
const closeBack = () => {
|
||||
console.log('closeBack')
|
||||
|
||||
viewFormRef.value?.closeFn()
|
||||
}
|
||||
|
||||
getLists()
|
||||
</script>
|
||||
|
||||
@@ -48,6 +48,7 @@ import {
|
||||
} from '@/api/flow/flow_template'
|
||||
import Popup from '@/components/popup/index.vue'
|
||||
import feedback from '@/utils/feedback'
|
||||
import { computed, ref, reactive, shallowRef } from 'vue'
|
||||
import type { PropType } from 'vue'
|
||||
defineProps({
|
||||
dictData: {
|
||||
@@ -134,9 +135,7 @@ const setFormData = async (data: Record<string, any>) => {
|
||||
}
|
||||
|
||||
const getDetail = async (row: Record<string, any>) => {
|
||||
const data = await flow_template_detail({
|
||||
id: row.id
|
||||
})
|
||||
const data = await flow_template_detail(row.id)
|
||||
setFormData(data)
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user