!195 发布 5.3.1-BETA_2.3.0-BETA 公测版本

Merge pull request !195 from 疯狂的狮子Li/dev
This commit is contained in:
疯狂的狮子Li 2025-03-13 05:30:32 +00:00 committed by Gitee
commit b23b123613
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
98 changed files with 576 additions and 484 deletions

View File

@ -1,46 +1,25 @@
{
"globals": {
"ComponentInternalInstance": true,
"TransferKey": true,
"ElFormRules": true,
"CheckboxValueType": true,
"PropType": true,
"DateModelType": true,
"UploadFile": true,
"ElFormInstance": true,
"ElTableInstance": true,
"ElTreeInstance": true,
"ElTreeSelectInstance": true,
"ElSelectInstance": true,
"ElUploadInstance": true,
"ElCardInstance": true,
"ElDialogInstance": true,
"ElInputInstance": true,
"ElInputNumberInstance": true,
"ElRadioInstance": true,
"ElRadioGroupInstance": true,
"ElRadioButtonInstance": true,
"ElCheckboxInstance": true,
"ElCheckboxGroupInstance": true,
"ElSwitchInstance": true,
"ElDatePickerInstance": true,
"ElTimePickerInstance": true,
"ElTimeSelectInstance": true,
"ElScrollbarInstance": true,
"ElCascaderInstance": true,
"ElColorPickerInstance": true,
"ElRateInstance": true,
"ElSliderInstance": true,
"useRouter": true,
"useRoute": true,
"Component": true,
"ComponentPublicInstance": true,
"ComputedRef": true,
"DirectiveBinding": true,
"EffectScope": true,
"ElTable": true,
"ElSelect": true,
"ElUpload": true,
"ElForm": true,
"ElTree": true,
"ElLoading": true,
"ElMessage": true,
"ElMessageBox": true,
"ElNotification": true,
"ExtractDefaultPropTypes": true,
"ExtractPropTypes": true,
"ExtractPublicPropTypes": true,
"InjectionKey": true,
"MaybeRef": true,
"MaybeRefOrGetter": true,
"PropType": true,
"Ref": true,
"VNode": true,
"WritableComputedRef": true,
"acceptHMRUpdate": true,
"asyncComputed": true,
"autoResetRef": true,
"computed": true,
@ -54,36 +33,50 @@
"createEventHook": true,
"createGlobalState": true,
"createInjectionState": true,
"createPinia": true,
"createReactiveFn": true,
"createReusableTemplate": true,
"createSharedComposable": true,
"createTemplatePromise": true,
"createUnrefFn": true,
"customRef": true,
"debouncedRef": true,
"debouncedWatch": true,
"defineAsyncComponent": true,
"defineComponent": true,
"defineStore": true,
"eagerComputed": true,
"effectScope": true,
"extendRef": true,
"getActivePinia": true,
"getCurrentInstance": true,
"getCurrentScope": true,
"h": true,
"ignorableWatch": true,
"inject": true,
"injectLocal": true,
"isDefined": true,
"isProxy": true,
"isReactive": true,
"isReadonly": true,
"isRef": true,
"makeDestructurable": true,
"mapActions": true,
"mapGetters": true,
"mapState": true,
"mapStores": true,
"mapWritableState": true,
"markRaw": true,
"nextTick": true,
"onActivated": true,
"onBeforeMount": true,
"onBeforeRouteLeave": true,
"onBeforeRouteUpdate": true,
"onBeforeUnmount": true,
"onBeforeUpdate": true,
"onClickOutside": true,
"onDeactivated": true,
"onElementRemoval": true,
"onErrorCaptured": true,
"onKeyStroke": true,
"onLongPress": true,
@ -95,8 +88,10 @@
"onStartTyping": true,
"onUnmounted": true,
"onUpdated": true,
"onWatcherCleanup": true,
"pausableWatch": true,
"provide": true,
"provideLocal": true,
"reactify": true,
"reactifyObject": true,
"reactive": true,
@ -111,12 +106,14 @@
"refThrottled": true,
"refWithControl": true,
"resolveComponent": true,
"resolveDirective": true,
"resolveRef": true,
"resolveUnref": true,
"setActivePinia": true,
"setMapStoreSuffix": true,
"shallowReactive": true,
"shallowReadonly": true,
"shallowRef": true,
"storeToRefs": true,
"syncRef": true,
"syncRefs": true,
"templateRef": true,
@ -126,6 +123,7 @@
"toReactive": true,
"toRef": true,
"toRefs": true,
"toValue": true,
"triggerRef": true,
"tryOnBeforeMount": true,
"tryOnBeforeUnmount": true,
@ -136,11 +134,14 @@
"unrefElement": true,
"until": true,
"useActiveElement": true,
"useAnimate": true,
"useArrayDifference": true,
"useArrayEvery": true,
"useArrayFilter": true,
"useArrayFind": true,
"useArrayFindIndex": true,
"useArrayFindLast": true,
"useArrayIncludes": true,
"useArrayJoin": true,
"useArrayMap": true,
"useArrayReduce": true,
@ -157,9 +158,11 @@
"useBrowserLocation": true,
"useCached": true,
"useClipboard": true,
"useClipboardItems": true,
"useCloned": true,
"useColorMode": true,
"useConfirmDialog": true,
"useCountdown": true,
"useCounter": true,
"useCssModule": true,
"useCssVar": true,
@ -198,6 +201,7 @@
"useFullscreen": true,
"useGamepad": true,
"useGeolocation": true,
"useId": true,
"useIdle": true,
"useImage": true,
"useInfiniteScroll": true,
@ -206,6 +210,7 @@
"useIntervalFn": true,
"useKeyModifier": true,
"useLastChanged": true,
"useLink": true,
"useLocalStorage": true,
"useMagicKeys": true,
"useManualRefHistory": true,
@ -213,6 +218,7 @@
"useMediaQuery": true,
"useMemoize": true,
"useMemory": true,
"useModel": true,
"useMounted": true,
"useMouse": true,
"useMouseInElement": true,
@ -226,6 +232,8 @@
"useOnline": true,
"usePageLeave": true,
"useParallax": true,
"useParentElement": true,
"usePerformanceObserver": true,
"usePermission": true,
"usePointer": true,
"usePointerLock": true,
@ -235,10 +243,14 @@
"usePreferredDark": true,
"usePreferredLanguages": true,
"usePreferredReducedMotion": true,
"usePreferredReducedTransparency": true,
"usePrevious": true,
"useRafFn": true,
"useRefHistory": true,
"useResizeObserver": true,
"useRoute": true,
"useRouter": true,
"useSSRWidth": true,
"useScreenOrientation": true,
"useScreenSafeArea": true,
"useScriptTag": true,
@ -256,6 +268,7 @@
"useStyleTag": true,
"useSupported": true,
"useSwipe": true,
"useTemplateRef": true,
"useTemplateRefsList": true,
"useTextDirection": true,
"useTextSelection": true,
@ -291,8 +304,10 @@
"watchArray": true,
"watchAtMost": true,
"watchDebounced": true,
"watchDeep": true,
"watchEffect": true,
"watchIgnorable": true,
"watchImmediate": true,
"watchOnce": true,
"watchPausable": true,
"watchPostEffect": true,
@ -300,13 +315,6 @@
"watchThrottled": true,
"watchTriggerable": true,
"watchWithFilter": true,
"whenever": true,
"ImportOption": true,
"TreeType": true,
"FieldOption": true,
"PageData": true,
"storeToRefs": true,
"DictDataOption": true,
"UploadOption": true
"whenever": true
}
}

View File

@ -1,86 +0,0 @@
import globals from 'globals';
import pluginJs from '@eslint/js';
import tseslint from 'typescript-eslint';
import pluginVue from 'eslint-plugin-vue';
import { readFile } from 'node:fs/promises';
import prettier from 'eslint-plugin-prettier';
/**
* https://blog.csdn.net/sayUonly/article/details/123482912
* 自动导入的配置
*/
const autoImportFile = new URL('./.eslintrc-auto-import.json', import.meta.url);
const autoImportGlobals = JSON.parse(await readFile(autoImportFile, 'utf8'));
/** @type {import('eslint').Linter.Config[]} */
export default [
{
/**
* 不需要.eslintignore文件 而是在这里配置
*/
ignores: [
'*.sh',
'node_modules',
'*.md',
'*.woff',
'*.ttf',
'.vscode',
'.idea',
'dist',
'/public',
'/docs',
'.husky',
'.local',
'/bin',
'.eslintrc.cjs',
'prettier.config.js',
'src/assets',
'tailwind.config.js'
]
},
{ files: ['**/*.{js,mjs,cjs,ts,vue}'] },
{
languageOptions: {
globals: globals.browser
}
},
pluginJs.configs.recommended,
...tseslint.configs.recommended,
...pluginVue.configs['flat/essential'],
{
files: ['**/*.vue'],
languageOptions: {
parserOptions: {
parser: tseslint.parser
}
}
},
{
languageOptions: {
globals: {
// 自动导入的配置 undef
...autoImportGlobals.globals,
DialogOption: 'readonly',
LayoutSetting: 'readonly'
}
},
plugins: { prettier },
rules: {
'@typescript-eslint/no-empty-function': 'off',
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/no-unused-vars': 'off',
'@typescript-eslint/no-this-alias': 'off',
// vue
'vue/multi-word-component-names': 'off',
'vue/valid-define-props': 'off',
'vue/no-v-model-argument': 'off',
'prefer-rest-params': 'off',
// prettier
'prettier/prettier': 'error',
// 允许使用空Object类型 {}
'@typescript-eslint/no-empty-object-type': 'off',
'@typescript-eslint/no-unused-expressions': 'off'
}
}
];

44
eslint.config.ts Normal file
View File

@ -0,0 +1,44 @@
import pluginVue from 'eslint-plugin-vue';
import globals from 'globals';
import prettier from 'eslint-plugin-prettier';
import { defineConfigWithVueTs, vueTsConfigs } from '@vue/eslint-config-typescript';
import skipFormatting from '@vue/eslint-config-prettier/skip-formatting';
export default defineConfigWithVueTs(
{
name: 'app/files-to-lint',
files: ['**/*.{js,cjs,ts,mts,tsx,vue}']
},
{
name: 'app/files-to-ignore',
ignores: ['**/dist/**', '**/dist-ssr/**', '**/coverage/**']
},
{
languageOptions: {
globals: globals.browser
}
},
pluginVue.configs['flat/essential'],
vueTsConfigs.recommended,
skipFormatting,
{
plugins: { prettier },
rules: {
'@typescript-eslint/no-empty-function': 'off',
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/no-unused-vars': 'off',
'@typescript-eslint/no-this-alias': 'off',
// vue
'vue/multi-word-component-names': 'off',
'vue/valid-define-props': 'off',
'vue/no-v-model-argument': 'off',
'prefer-rest-params': 'off',
// prettier
'prettier/prettier': 'error',
// 允许使用空Object类型 {}
'@typescript-eslint/no-empty-object-type': 'off',
'@typescript-eslint/no-unused-expressions': 'off'
}
}
);

View File

@ -1,7 +1,7 @@
{
"$schema": "https://json.schemastore.org/tsconfig",
"$schema": "https://json.schemastore.org/package",
"name": "ruoyi-vue-plus",
"version": "5.3.0",
"version": "5.3.1-BETA_2.3.0-BETA",
"description": "RuoYi-Vue-Plus多租户管理系统",
"author": "LionLi",
"license": "MIT",
@ -23,13 +23,11 @@
"@element-plus/icons-vue": "2.3.1",
"@highlightjs/vue-plugin": "2.1.0",
"@vueup/vue-quill": "1.2.0",
"@vueuse/core": "11.3.0",
"@vueuse/core": "12.7.0",
"animate.css": "4.1.1",
"await-to-js": "3.0.0",
"axios": "1.7.8",
"crypto-js": "4.2.0",
"diagram-js": "12.3.0",
"didi": "9.0.2",
"echarts": "5.5.0",
"element-plus": "2.8.8",
"file-saver": "2.0.5",
@ -50,38 +48,47 @@
"vxe-table": "4.5.22"
},
"devDependencies": {
"@eslint/js": "9.15.0",
"@iconify/json": "2.2.276",
"@types/crypto-js": "4.2.2",
"@types/file-saver": "2.0.7",
"@types/js-cookie": "3.0.6",
"@types/node": "18.18.2",
"@types/node": "^22.13.4",
"@types/nprogress": "0.2.3",
"@unocss/preset-attributify": "0.64.1",
"@unocss/preset-icons": "0.64.1",
"@unocss/preset-uno": "0.64.1",
"@vitejs/plugin-vue": "5.0.4",
"@unocss/preset-attributify": "66.0.0",
"@unocss/preset-icons": "66.0.0",
"@unocss/preset-uno": "66.0.0",
"@vitejs/plugin-vue": "5.2.1",
"@vue/compiler-sfc": "3.4.23",
"autoprefixer": "10.4.18",
"eslint": "9.15.0",
"eslint-plugin-prettier": "^5.2.1",
"eslint-plugin-vue": "9.31.0",
"fast-glob": "3.3.2",
"globals": "15.12.0",
"postcss": "8.4.36",
"prettier": "3.2.5",
"sass": "1.72.0",
"typescript": "5.7.2",
"typescript-eslint": "8.16.0",
"unocss": "0.64.1",
"@vue/eslint-config-prettier": "10.2.0",
"@vue/eslint-config-typescript": "14.4.0",
"autoprefixer": "10.4.20",
"eslint": "9.21.0",
"eslint-plugin-prettier": "5.2.3",
"eslint-plugin-vue": "9.32.0",
"globals": "16.0.0",
"prettier": "3.5.2",
"sass": "1.84.0",
"typescript": "~5.7.3",
"unocss": "66.0.0",
"unplugin-auto-import": "0.17.5",
"unplugin-icons": "0.18.5",
"unplugin-vue-components": "0.26.0",
"unplugin-vue-components": "28.0.0",
"unplugin-vue-setup-extend-plus": "1.0.1",
"vite": "5.4.11",
"vite-plugin-compression": "0.5.1",
"vite-plugin-svg-icons": "2.0.1",
"vitest": "1.5.0",
"vue-tsc": "2.0.13"
}
"vite-plugin-svg-icons-ng": "^1.2.2",
"vite-plugin-vue-devtools": "7.7.1",
"vitest": "3.0.5",
"vue-tsc": "^2.2.2"
},
"engines": {
"node": ">=18.18.0",
"npm": ">=8.9.0"
},
"browserslist": [
"Chrome >= 87",
"Edge >= 88",
"Safari >= 14",
"Firefox >= 78"
]
}

View File

@ -5,9 +5,9 @@
</template>
<script setup lang="ts">
import useSettingsStore from '@/store/modules/settings';
import { useSettingsStore } from '@/store/modules/settings';
import { handleThemeStyle } from '@/utils/theme';
import useAppStore from '@/store/modules/app';
import { useAppStore } from '@/store/modules/app';
const appStore = useAppStore();

View File

@ -19,6 +19,7 @@ export interface UserQuery extends PageQuery {
status?: string;
deptId?: string | number;
roleId?: string | number;
userIds?: string;
}
/**

View File

@ -6,7 +6,6 @@ export interface CategoryTreeVO {
children: CategoryTreeVO[];
}
export interface CategoryVO {
/**
* ID
*/
@ -39,7 +38,6 @@ export interface CategoryVO {
}
export interface CategoryForm extends BaseEntity {
/**
* ID
*/
@ -59,14 +57,11 @@ export interface CategoryForm extends BaseEntity {
*
*/
orderNum?: number;
}
export interface CategoryQuery {
/**
*
*/
categoryName?: string;
}

View File

@ -178,3 +178,16 @@ export const currentTaskAllUser = (taskId: string | number) => {
method: 'get'
});
};
/**
*
* @param data参数
* @returns
*/
export const getNextNodeList = (data: any): any => {
return request({
url: '/workflow/task/getNextNodeList',
method: 'post',
data: data
});
};

View File

@ -29,8 +29,14 @@ export interface FlowTaskVO {
nodeType: number;
nodeRatio: string | number;
version?: string;
applyNode?: boolean;
buttonList?: buttonList[];
}
export interface buttonList {
code: string;
show: boolean;
}
export interface VariableVo {
key: string;
value: string;

View File

@ -1 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1588670460195" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1314" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M230.4 307.712c13.824 0 25.088-11.264 25.088-25.088 0-100.352 81.92-182.272 182.272-182.272s182.272 81.408 182.272 182.272c0 13.824 11.264 25.088 25.088 25.088s25.088-11.264 24.576-25.088c0-127.488-103.936-231.936-231.936-231.936S205.824 154.624 205.824 282.624c-0.512 14.336 10.752 25.088 24.576 25.088z m564.736 234.496c-11.264 0-21.504 2.048-31.232 6.144 0-44.544-40.448-81.92-88.064-81.92-14.848 0-28.16 3.584-39.936 10.24-13.824-28.16-44.544-48.128-78.848-48.128-12.288 0-24.576 2.56-35.328 7.68V284.16c0-45.568-37.888-81.92-84.48-81.92s-84.48 36.864-84.48 81.92v348.672l-69.12-112.64c-18.432-28.16-58.368-36.864-91.136-19.968-26.624 14.336-46.592 47.104-30.208 88.064 3.072 8.192 76.8 205.312 171.52 311.296 0 0 28.16 24.576 43.008 58.88 4.096 9.728 13.312 15.36 22.528 15.36 3.072 0 6.656-0.512 9.728-2.048 12.288-5.12 18.432-19.968 12.8-32.256-19.456-44.544-53.76-74.752-53.76-74.752C281.6 768 209.408 573.44 208.384 570.88c-5.12-12.8-2.56-20.992 7.168-26.112 9.216-4.608 21.504-4.608 26.112 2.56l113.152 184.32c4.096 8.704 12.8 14.336 22.528 14.336 13.824 0 25.088-10.752 25.088-25.088V284.16c0-17.92 15.36-32.256 34.816-32.256s34.816 14.336 34.816 32.256v284.16c0 13.824 10.24 25.088 24.576 25.088 13.824 0 25.088-11.264 25.088-25.088v-57.344c0-17.92 15.36-32.768 34.816-32.768 19.968 0 37.376 15.36 37.376 32.768v95.232c0 7.168 3.072 13.312 7.68 17.92 4.608 4.608 10.752 7.168 17.92 7.168 13.824 0 24.576-11.264 24.576-25.088V547.84c0-18.432 13.824-32.256 32.256-32.256 20.48 0 38.912 15.36 38.912 32.256v95.232c0 13.824 11.264 25.088 25.088 25.088s24.576-11.264 25.088-25.088v-18.944c0-18.944 12.8-32.256 30.72-32.256 18.432 0 22.528 18.944 22.528 31.744 0 1.024-11.776 99.84-50.688 173.056-30.72 58.368-45.056 112.128-51.2 146.944-2.56 13.312 6.656 26.112 19.968 28.672 1.536 0 3.072 0.512 4.608 0.512 11.776 0 22.016-8.192 24.064-20.48 5.632-31.232 18.432-79.36 46.08-132.608 43.52-81.92 55.808-186.88 56.32-193.536-0.512-50.688-29.696-83.968-72.704-83.968z"></path></path></svg>
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1588670460195" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1314" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M230.4 307.712c13.824 0 25.088-11.264 25.088-25.088 0-100.352 81.92-182.272 182.272-182.272s182.272 81.408 182.272 182.272c0 13.824 11.264 25.088 25.088 25.088s25.088-11.264 24.576-25.088c0-127.488-103.936-231.936-231.936-231.936S205.824 154.624 205.824 282.624c-0.512 14.336 10.752 25.088 24.576 25.088z m564.736 234.496c-11.264 0-21.504 2.048-31.232 6.144 0-44.544-40.448-81.92-88.064-81.92-14.848 0-28.16 3.584-39.936 10.24-13.824-28.16-44.544-48.128-78.848-48.128-12.288 0-24.576 2.56-35.328 7.68V284.16c0-45.568-37.888-81.92-84.48-81.92s-84.48 36.864-84.48 81.92v348.672l-69.12-112.64c-18.432-28.16-58.368-36.864-91.136-19.968-26.624 14.336-46.592 47.104-30.208 88.064 3.072 8.192 76.8 205.312 171.52 311.296 0 0 28.16 24.576 43.008 58.88 4.096 9.728 13.312 15.36 22.528 15.36 3.072 0 6.656-0.512 9.728-2.048 12.288-5.12 18.432-19.968 12.8-32.256-19.456-44.544-53.76-74.752-53.76-74.752C281.6 768 209.408 573.44 208.384 570.88c-5.12-12.8-2.56-20.992 7.168-26.112 9.216-4.608 21.504-4.608 26.112 2.56l113.152 184.32c4.096 8.704 12.8 14.336 22.528 14.336 13.824 0 25.088-10.752 25.088-25.088V284.16c0-17.92 15.36-32.256 34.816-32.256s34.816 14.336 34.816 32.256v284.16c0 13.824 10.24 25.088 24.576 25.088 13.824 0 25.088-11.264 25.088-25.088v-57.344c0-17.92 15.36-32.768 34.816-32.768 19.968 0 37.376 15.36 37.376 32.768v95.232c0 7.168 3.072 13.312 7.68 17.92 4.608 4.608 10.752 7.168 17.92 7.168 13.824 0 24.576-11.264 24.576-25.088V547.84c0-18.432 13.824-32.256 32.256-32.256 20.48 0 38.912 15.36 38.912 32.256v95.232c0 13.824 11.264 25.088 25.088 25.088s24.576-11.264 25.088-25.088v-18.944c0-18.944 12.8-32.256 30.72-32.256 18.432 0 22.528 18.944 22.528 31.744 0 1.024-11.776 99.84-50.688 173.056-30.72 58.368-45.056 112.128-51.2 146.944-2.56 13.312 6.656 26.112 19.968 28.672 1.536 0 3.072 0.512 4.608 0.512 11.776 0 22.016-8.192 24.064-20.48 5.632-31.232 18.432-79.36 46.08-132.608 43.52-81.92 55.808-186.88 56.32-193.536-0.512-50.688-29.696-83.968-72.704-83.968z"></path></svg>

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@ -1,4 +1,4 @@
@import './variables.module.scss';
@use './variables.module.scss' as *;
@mixin colorBtn($color) {
background: $color;

View File

@ -1,12 +1,12 @@
@import './variables.module.scss';
@import './mixin.scss';
@import './transition.scss';
@import './element-ui.scss';
@import './sidebar.scss';
@import './btn.scss';
@import './ruoyi.scss';
@import 'animate.css';
@import 'element-plus/dist/index.css';
@use './variables.module.scss' as *;
@use './mixin.scss';
@use './transition.scss';
@use './element-ui.scss';
@use './sidebar.scss';
@use './btn.scss';
@use './ruoyi.scss';
@use 'animate.css';
@use 'element-plus/dist/index.css';
body {
height: 100%;
@ -162,10 +162,6 @@ aside {
position: relative;
}
.pagination-container {
margin-top: 30px;
}
.text-center {
text-align: center;
}

View File

@ -1,3 +1,5 @@
@use './variables.module.scss' as *;
/**
* 通用css样式布局处理
* Copyright (c) 2019 ruoyi
@ -114,10 +116,9 @@ h6 {
/** 表格布局 **/
.pagination-container {
// position: relative;
height: 25px;
margin-bottom: 10px;
margin-top: 15px;
display: flex;
justify-content: flex-end;
margin-top: 20px;
padding: 10px 20px !important;
}
@ -130,11 +131,6 @@ h6 {
width: 100%;
}
.pagination-container .el-pagination {
//right: 0;
//position: absolute;
}
@media (max-width: 768px) {
.pagination-container .el-pagination > .el-pagination__jump {
display: none !important;
@ -201,8 +197,6 @@ h6 {
}
.card-box {
padding-right: 15px;
padding-left: 15px;
margin-bottom: 10px;
}

View File

@ -1,3 +1,5 @@
@use './variables.module.scss' as *;
#app {
.main-container {
height: 100%;

View File

@ -11,7 +11,7 @@
<script setup lang="ts">
import { RouteLocationMatched } from 'vue-router';
import usePermissionStore from '@/store/modules/permission';
import { usePermissionStore } from '@/store/modules/permission';
const route = useRoute();
const router = useRouter();

View File

@ -87,7 +87,7 @@ const handleArray = (array: Array<string | number>) => {
};
</script>
<style scoped>
<style lang="scss" scoped>
.el-tag + .el-tag {
margin-left: 10px;
}

View File

@ -7,18 +7,20 @@
:before-upload="handleBeforeUpload"
:file-list="fileList"
:limit="limit"
:accept="fileAccept"
:on-error="handleUploadError"
:on-exceed="handleExceed"
:on-success="handleUploadSuccess"
:show-file-list="false"
:headers="headers"
class="upload-file-uploader"
v-if="!disabled"
>
<!-- 上传按钮 -->
<el-button type="primary">选取文件</el-button>
</el-upload>
<!-- 上传提示 -->
<div v-if="showTip" class="el-upload__tip">
<div v-if="showTip && !disabled" class="el-upload__tip">
请上传
<template v-if="fileSize">
大小不超过 <b style="color: #f56c6c">{{ fileSize }}MB</b>
@ -35,7 +37,7 @@
<span class="el-icon-document"> {{ getFileName(file.name) }} </span>
</el-link>
<div class="ele-upload-list__item-content-action">
<el-button type="danger" link @click="handleDelete(index)">删除</el-button>
<el-button type="danger" v-if="!disabled" link @click="handleDelete(index)">删除</el-button>
</div>
</li>
</transition-group>
@ -57,9 +59,11 @@ const props = defineProps({
// (MB)
fileSize: propTypes.number.def(5),
// , ['png', 'jpg', 'jpeg']
fileType: propTypes.array.def(['doc', 'xls', 'ppt', 'txt', 'pdf']),
fileType: propTypes.array.def(['doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'txt', 'pdf']),
//
isShowTip: propTypes.bool.def(true)
isShowTip: propTypes.bool.def(true),
//
disabled: propTypes.bool.def(false)
});
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
@ -76,6 +80,9 @@ const showTip = computed(() => props.isShowTip && (props.fileType || props.fileS
const fileUploadRef = ref<ElUploadInstance>();
// fileType fileAccept
const fileAccept = computed(() => props.fileType.map((type) => `.${type}`).join(','));
watch(
() => props.modelValue,
async (val) => {
@ -209,7 +216,7 @@ const listToString = (list: any[], separator?: string) => {
};
</script>
<style scoped lang="scss">
<style lang="scss" scoped>
.upload-file-uploader {
margin-bottom: 5px;
}

View File

@ -21,7 +21,7 @@
import Fuse from 'fuse.js';
import { getNormalPath } from '@/utils/ruoyi';
import { isHttp } from '@/utils/validate';
import usePermissionStore from '@/store/modules/permission';
import { usePermissionStore } from '@/store/modules/permission';
import { RouteRecordRaw } from 'vue-router';
type Router = Array<{
@ -36,7 +36,7 @@ const show = ref(false);
const fuse = ref();
const headerSearchSelectRef = ref<ElSelectInstance>();
const router = useRouter();
const routes = computed(() => usePermissionStore().getRoutes());
const routes = computed(() => usePermissionStore().getDefaultRoutes());
const click = () => {
show.value = !show.value;

View File

@ -65,7 +65,7 @@ const selectedIcon = (iconName: string) => {
};
</script>
<style scoped lang="scss">
<style lang="scss" scoped>
.el-scrollbar {
max-height: calc(50vh - 100px) !important;
overflow-y: auto;

View File

@ -1,13 +1,14 @@
<template>
<div class="component-upload-image">
<el-upload
ref="imageUpload"
ref="imageUploadRef"
multiple
:action="uploadImgUrl"
list-type="picture-card"
:on-success="handleUploadSuccess"
:before-upload="handleBeforeUpload"
:limit="limit"
:accept="fileAccept"
:on-error="handleUploadError"
:on-exceed="handleExceed"
:before-remove="handleDelete"
@ -87,6 +88,9 @@ const showTip = computed(() => props.isShowTip && (props.fileType || props.fileS
const imageUploadRef = ref<ElUploadInstance>();
// fileType fileAccept
const fileAccept = computed(() => props.fileType.map((type) => `.${type}`).join(','));
watch(
() => props.modelValue,
async (val: string) => {
@ -230,7 +234,7 @@ const listToString = (list: any[], separator?: string) => {
};
</script>
<style scoped lang="scss">
<style lang="scss" scoped>
// .el-upload--picture-card
:deep(.hide .el-upload--picture-card) {
display: none;

View File

@ -14,13 +14,7 @@
</div>
</template>
<script lang="ts">
export default {
name: 'Pagination'
};
</script>
<script setup lang="ts">
<script setup name="Pagination" lang="ts">
import { scrollTo } from '@/utils/scroll-to';
import { propTypes } from '@/utils/propTypes';
@ -28,10 +22,7 @@ const props = defineProps({
total: propTypes.number,
page: propTypes.number.def(1),
limit: propTypes.number.def(20),
pageSizes: {
type: Array,
default: () => [10, 20, 30, 50]
},
pageSizes: { type: Array<number>, default: () => [10, 20, 30, 50] },
// 5
pagerCount: propTypes.number.def(document.body.clientWidth < 992 ? 5 : 7),
layout: propTypes.string.def('total, sizes, prev, pager, next, jumper'),
@ -77,7 +68,6 @@ function handleCurrentChange(val: number) {
<style lang="scss" scoped>
.pagination-container {
padding: 32px 16px;
.el-pagination {
float: v-bind(float);
}

View File

@ -72,7 +72,7 @@
</el-dialog>
</div>
</template>
<script lang="ts" setup>
<script setup lang="ts">
import { flowImage } from '@/api/workflow/instance';
import { propTypes } from '@/utils/propTypes';
import { listByIds } from '@/api/system/oss';

View File

@ -49,7 +49,7 @@
</el-dialog>
</el-dialog>
</template>
<script lang="ts" setup>
<script setup lang="ts">
import { propTypes } from '@/utils/propTypes';
import { FlowTaskVO, TaskOperationBo } from '@/api/workflow/task/types';
import UserSelect from '@/components/UserSelect';

View File

@ -11,12 +11,23 @@
<el-form-item v-if="task.flowStatus === 'waiting'" label="附件">
<fileUpload v-model="form.fileId" :file-type="['png', 'jpg', 'jpeg', 'doc', 'docx', 'xlsx', 'xls', 'ppt', 'txt', 'pdf']" :file-size="20" />
</el-form-item>
<el-form-item label="抄送">
<el-form-item label="抄送" v-if="task.flowStatus === 'waiting' && buttonObj.copy">
<el-button type="primary" icon="Plus" circle @click="openUserSelectCopy" />
<el-tag v-for="user in selectCopyUserList" :key="user.userId" closable style="margin: 2px" @close="handleCopyCloseTag(user)">
{{ user.nickName }}
</el-tag>
</el-form-item>
<el-form-item v-if="buttonObj.pop && nestNodeList && nestNodeList.length > 0" label="下一步审批人" prop="assigneeMap">
<div v-for="(item, index) in nestNodeList" :key="index" style="margin-bottom: 5px; width: 500px">
<span>{{ item.nodeName }}</span>
<el-input v-if="false" v-model="form.assigneeMap[item.nodeCode]" />
<el-input placeholder="请选择审批人" readonly v-model="nickName[item.nodeCode]">
<template v-slot:append>
<el-button @click="choosePeople(item)" icon="search">选择</el-button>
</template>
</el-input>
</div>
</el-form-item>
<el-form-item v-if="task.flowStatus === 'waiting'" label="审批意见">
<el-input v-model="form.message" type="textarea" resize="none" />
</el-form-item>
@ -24,10 +35,14 @@
<template #footer>
<span class="dialog-footer">
<el-button :disabled="buttonDisabled" type="primary" @click="handleCompleteTask"> 提交 </el-button>
<el-button v-if="task.flowStatus === 'waiting'" :disabled="buttonDisabled" type="primary" @click="openDelegateTask"> 委托 </el-button>
<el-button v-if="task.flowStatus === 'waiting'" :disabled="buttonDisabled" type="primary" @click="openTransferTask"> 转办 </el-button>
<el-button v-if="task.flowStatus === 'waiting' && buttonObj.trust" :disabled="buttonDisabled" type="primary" @click="openDelegateTask">
委托
</el-button>
<el-button v-if="task.flowStatus === 'waiting' && buttonObj.transfer" :disabled="buttonDisabled" type="primary" @click="openTransferTask">
转办
</el-button>
<el-button
v-if="task.flowStatus === 'waiting' && Number(task.nodeRatio) > 0"
v-if="task.flowStatus === 'waiting' && Number(task.nodeRatio) > 0 && buttonObj.addSign"
:disabled="buttonDisabled"
type="primary"
@click="openMultiInstanceUser"
@ -35,15 +50,24 @@
加签
</el-button>
<el-button
v-if="task.flowStatus === 'waiting' && Number(task.nodeRatio) > 0"
v-if="task.flowStatus === 'waiting' && Number(task.nodeRatio) > 0 && buttonObj.subSign"
:disabled="buttonDisabled"
type="primary"
@click="handleTaskUser"
>
减签
</el-button>
<el-button v-if="task.flowStatus === 'waiting'" :disabled="buttonDisabled" type="danger" @click="handleTerminationTask"> 终止 </el-button>
<el-button v-if="task.flowStatus === 'waiting'" :disabled="buttonDisabled" type="danger" @click="handleBackProcessOpen"> 退回 </el-button>
<el-button
v-if="task.flowStatus === 'waiting' && buttonObj.termination"
:disabled="buttonDisabled"
type="danger"
@click="handleTerminationTask"
>
终止
</el-button>
<el-button v-if="task.flowStatus === 'waiting' && buttonObj.back" :disabled="buttonDisabled" type="danger" @click="handleBackProcessOpen">
退回
</el-button>
<el-button :disabled="buttonDisabled" @click="cancel">取消</el-button>
</span>
</template>
@ -55,6 +79,8 @@
<UserSelect ref="delegateTaskRef" :multiple="false" @confirm-call-back="handleDelegateTask"></UserSelect>
<!-- 加签组件 -->
<UserSelect ref="multiInstanceUserRef" :multiple="true" @confirm-call-back="addMultiInstanceUser"></UserSelect>
<!-- 弹窗选人 -->
<UserSelect ref="porUserRef" :multiple="true" :userIds="popUserIds" @confirm-call-back="handlePopUser"></UserSelect>
<!-- 驳回开始 -->
<el-dialog v-model="backVisible" draggable title="驳回" width="40%" :close-on-click-modal="false">
@ -72,7 +98,11 @@
</el-checkbox-group>
</el-form-item>
<el-form-item v-if="task.flowStatus === 'waiting'" label="附件">
<fileUpload v-model="backForm.fileId" :file-type="['png', 'jpg', 'jpeg', 'doc', 'docx', 'xlsx', 'xls', 'ppt', 'txt', 'pdf']" :file-size="20" />
<fileUpload
v-model="backForm.fileId"
:file-type="['png', 'jpg', 'jpeg', 'doc', 'docx', 'xlsx', 'xls', 'ppt', 'txt', 'pdf']"
:file-size="20"
/>
</el-form-item>
<el-form-item label="审批意见">
<el-input v-model="backForm.message" type="textarea" resize="none" />
@ -102,11 +132,20 @@
</el-dialog>
</template>
<script lang="ts" setup>
<script setup lang="ts">
import { ref } from 'vue';
import { ComponentInternalInstance } from 'vue';
import { ElForm } from 'element-plus';
import { completeTask, backProcess, getTask, taskOperation, terminationTask, getBackTaskNode, currentTaskAllUser } from '@/api/workflow/task';
import {
completeTask,
backProcess,
getTask,
taskOperation,
terminationTask,
getBackTaskNode,
currentTaskAllUser,
getNextNodeList
} from '@/api/workflow/task';
import UserSelect from '@/components/UserSelect';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
@ -117,6 +156,7 @@ const userSelectCopyRef = ref<InstanceType<typeof UserSelect>>();
const transferTaskRef = ref<InstanceType<typeof UserSelect>>();
const delegateTaskRef = ref<InstanceType<typeof UserSelect>>();
const multiInstanceUserRef = ref<InstanceType<typeof UserSelect>>();
const porUserRef = ref<InstanceType<typeof UserSelect>>();
const props = defineProps({
taskVariables: {
@ -136,12 +176,28 @@ const selectCopyUserList = ref<UserVO[]>([]);
const selectCopyUserIds = ref<string>(undefined);
//
const deleteUserList = ref<any>([]);
//id
const popUserIds = ref<any>([]);
//
const backVisible = ref(false);
const backLoading = ref(true);
const backButtonDisabled = ref(true);
//
const taskNodeList = ref([]);
const nickName = ref({});
//
const nodeCode = ref<string>('');
const buttonObj = ref<any>({
pop: false,
trust: false,
transfer: false,
addSign: false,
subSign: false,
termination: false,
back: false
});
//
const nestNodeList = ref([]);
//
const task = ref<FlowTaskVO>({
id: undefined,
@ -159,7 +215,9 @@ const task = ref<FlowTaskVO>({
formCustom: undefined,
formPath: undefined,
nodeType: undefined,
nodeRatio: undefined
nodeRatio: undefined,
applyNode: false,
buttonList: []
});
const dialog = reactive<DialogOption>({
visible: false,
@ -170,6 +228,7 @@ const deleteSignatureVisible = ref(false);
const form = ref<Record<string, any>>({
taskId: undefined,
message: undefined,
assigneeMap: {},
variables: {},
messageType: ['1'],
flowCopyList: []
@ -181,8 +240,9 @@ const backForm = ref<Record<string, any>>({
variables: {},
messageType: ['1']
});
//
const openDialog = (id?: string) => {
const openDialog = async (id?: string) => {
selectCopyUserIds.value = undefined;
selectCopyUserList.value = [];
form.value.fileId = undefined;
@ -191,13 +251,20 @@ const openDialog = (id?: string) => {
dialog.visible = true;
loading.value = true;
buttonDisabled.value = true;
nextTick(() => {
getTask(taskId.value).then((response) => {
task.value = response.data;
loading.value = false;
buttonDisabled.value = false;
});
const response = await getTask(taskId.value);
task.value = response.data;
buttonObj.value = {};
task.value.buttonList.forEach((e) => {
buttonObj.value[e.code] = e.show;
});
buttonDisabled.value = false;
const data = {
taskId: taskId.value,
variables: props.taskVariables
};
const nextData = await getNextNodeList(data);
nestNodeList.value = nextData.data;
loading.value = false;
};
onMounted(() => {});
@ -207,10 +274,29 @@ const emits = defineEmits(['submitCallback', 'cancelCallback']);
const handleCompleteTask = async () => {
form.value.taskId = taskId.value;
form.value.taskVariables = props.taskVariables;
let verify = false;
if (buttonObj.value.pop && nestNodeList.value && nestNodeList.value.length > 0) {
nestNodeList.value.forEach((e) => {
if (
Object.keys(form.value.assigneeMap).length === 0 ||
form.value.assigneeMap[e.nodeCode] === '' ||
form.value.assigneeMap[e.nodeCode] === null ||
form.value.assigneeMap[e.nodeCode] === undefined
) {
verify = true;
}
});
if (verify) {
proxy?.$modal.msgWarning('请选择审批人!');
return false;
}
} else {
form.value.assigneeMap = {};
}
if (selectCopyUserList.value && selectCopyUserList.value.length > 0) {
let flowCopyList = [];
const flowCopyList = [];
selectCopyUserList.value.forEach((e) => {
let copyUser = {
const copyUser = {
userId: e.userId,
userName: e.nickName
};
@ -239,7 +325,7 @@ const handleBackProcessOpen = async () => {
backVisible.value = true;
backLoading.value = true;
backButtonDisabled.value = true;
let data = await getBackTaskNode(task.value.definitionId, task.value.nodeCode);
const data = await getBackTaskNode(task.value.definitionId, task.value.nodeCode);
taskNodeList.value = data.data;
backLoading.value = false;
backButtonDisabled.value = false;
@ -266,6 +352,8 @@ const handleBackProcess = async () => {
const cancel = async () => {
dialog.visible = false;
buttonDisabled.value = false;
nickName.value = {};
form.value.assigneeMap = {};
emits('cancelCallback');
};
//
@ -386,7 +474,7 @@ const handleDelegateTask = async (data) => {
};
//
const handleTerminationTask = async () => {
let params = {
const params = {
taskId: taskId.value,
comment: form.value.message
};
@ -402,7 +490,7 @@ const handleTerminationTask = async () => {
proxy?.$modal.msgSuccess('操作成功');
};
const handleTaskUser = async () => {
let data = await currentTaskAllUser(taskId.value);
const data = await currentTaskAllUser(taskId.value);
deleteUserList.value = data.data;
if (deleteUserList.value && deleteUserList.value.length > 0) {
deleteUserList.value.forEach((e) => {
@ -411,6 +499,26 @@ const handleTaskUser = async () => {
}
deleteSignatureVisible.value = true;
};
//
const choosePeople = async (data) => {
if (!data.permissionFlag) {
proxy?.$modal.msgError('没有可选择的人员,请联系管理员!');
}
popUserIds.value = data.permissionFlag;
nodeCode.value = data.nodeCode;
porUserRef.value.open();
};
//
const handlePopUser = async (userList) => {
const userIds = userList.map((item) => {
return item.userId;
});
const nickNames = userList.map((item) => {
return item.nickName;
});
form.value.assigneeMap[nodeCode.value] = userIds.join(',');
nickName.value[nodeCode.value] = nickNames.join(',');
};
/**
* 对外暴露子组件方法

View File

@ -16,7 +16,7 @@
:data="columns"
show-checkbox
node-key="key"
:props="{ label: 'label', children: 'children' }"
:props="{ label: 'label', children: 'children' } as any"
@check="columnChange"
></el-tree>
<template #reference>

View File

@ -4,7 +4,7 @@
</div>
</template>
<script setup>
<script setup lang="ts">
const url = ref('https://plus-doc.dromara.org/');
function goto() {

View File

@ -4,7 +4,7 @@
</div>
</template>
<script setup>
<script setup lang="ts">
const url = ref('https://gitee.com/dromara/RuoYi-Vue-Plus');
function goto() {

View File

@ -16,7 +16,7 @@
</template>
<script setup lang="ts">
import useAppStore from '@/store/modules/app';
import { useAppStore } from '@/store/modules/app';
const appStore = useAppStore();
const size = computed(() => appStore.size);

View File

@ -21,7 +21,7 @@ const svgClass = computed(() => {
});
</script>
<style scope lang="scss">
<style lang="scss" scoped>
.sub-el-icon,
.nav-icon {
display: inline-block;

View File

@ -22,9 +22,9 @@
<script setup lang="ts">
import { constantRoutes } from '@/router';
import { isHttp } from '@/utils/validate';
import useAppStore from '@/store/modules/app';
import useSettingsStore from '@/store/modules/settings';
import usePermissionStore from '@/store/modules/permission';
import { useAppStore } from '@/store/modules/app';
import { useSettingsStore } from '@/store/modules/settings';
import { usePermissionStore } from '@/store/modules/permission';
import { RouteRecordRaw } from 'vue-router';
//

View File

@ -6,7 +6,7 @@
style="width: 100%"
:filterable="true"
:clearable="true"
:filter-method="selectFilterData"
:filter-method="selectFilterData as any"
:placeholder="placeholder"
@clear="clearHandle"
>
@ -16,7 +16,7 @@
ref="selectTree"
:accordion="accordion"
:data="options"
:props="objMap"
:props="objMap as any"
:node-key="objMap.value"
:expand-on-click-node="false"
:default-expanded-keys="defaultExpandedKey"

View File

@ -11,7 +11,7 @@
class="mt-2"
node-key="id"
:data="deptOptions"
:props="{ label: 'label', children: 'children' }"
:props="{ label: 'label', children: 'children' } as any"
:expand-on-click-node="false"
:filter-node-method="filterNode"
highlight-current
@ -108,11 +108,13 @@ interface PropType {
modelValue?: UserVO[] | UserVO | undefined;
multiple?: boolean;
data?: string | number | (string | number)[] | undefined;
userIds?: string | number | (string | number)[] | undefined;
}
const prop = withDefaults(defineProps<PropType>(), {
multiple: true,
modelValue: undefined,
data: undefined
data: undefined,
userIds: undefined
});
const emit = defineEmits(['update:modelValue', 'confirmCallBack']);
@ -143,7 +145,8 @@ const queryParams = ref<UserQuery>({
phonenumber: '',
status: '',
deptId: '',
roleId: ''
roleId: '',
userIds: ''
});
const defaultSelectUserIds = computed(() => computedIds(prop.data));
@ -166,7 +169,7 @@ const confirm = () => {
const computedIds = (data) => {
if (data instanceof Array) {
return data.map(item => String(item));
return data.map((item) => String(item));
} else if (typeof data === 'string') {
return data.split(',');
} else if (typeof data === 'number') {
@ -192,6 +195,7 @@ const getTreeSelect = async () => {
/** 查询用户列表 */
const getList = async () => {
loading.value = true;
queryParams.value.userIds = prop.userIds;
const res = await api.listUser(proxy?.addDateRange(queryParams.value, dateRange.value));
loading.value = false;
userList.value = res.rows;
@ -302,5 +306,3 @@ defineExpose({
close: userDialog.closeDialog
});
</script>
<style lang="scss" scoped></style>

View File

@ -1,5 +1,5 @@
import { Directive, DirectiveBinding } from 'vue';
import useUserStore from '@/store/modules/user';
import { useUserStore } from '@/store/modules/user';
/**
*
*/

View File

@ -1,12 +1,12 @@
<template>
<section class="app-main">
<router-view v-slot="{ Component, route }">
<transition v-if="!route.meta.noCache" :enter-active-class="animante" mode="out-in">
<transition v-if="!route.meta.noCache" :enter-active-class="animate" mode="out-in">
<keep-alive v-if="!route.meta.noCache" :include="tagsViewStore.cachedViews">
<component :is="Component" v-if="!route.meta.link" :key="route.path" />
</keep-alive>
</transition>
<transition v-if="route.meta.noCache" :enter-active-class="animante" mode="out-in">
<transition v-if="route.meta.noCache" :enter-active-class="animate" mode="out-in">
<component :is="Component" v-if="!route.meta.link && route.meta.noCache" :key="route.path" />
</transition>
</router-view>
@ -15,8 +15,8 @@
</template>
<script setup name="AppMain" lang="ts">
import useSettingsStore from '@/store/modules/settings';
import useTagsViewStore from '@/store/modules/tagsView';
import { useSettingsStore } from '@/store/modules/settings';
import { useTagsViewStore } from '@/store/modules/tagsView';
import IframeToggle from './IframeToggle/index.vue';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
@ -24,16 +24,16 @@ const route = useRoute();
const tagsViewStore = useTagsViewStore();
//
const animante = ref<string>('');
const animate = ref<string>('');
const animationEnable = ref(useSettingsStore().animationEnable);
watch(
() => useSettingsStore().animationEnable,
(val: boolean) => {
animationEnable.value = val;
if (val) {
animante.value = proxy?.animate.animateList[Math.round(Math.random() * proxy?.animate.animateList.length)] as string;
animate.value = proxy?.animate.animateList[Math.round(Math.random() * proxy?.animate.animateList.length)] as string;
} else {
animante.value = proxy?.animate.defaultAnimate as string;
animate.value = proxy?.animate.defaultAnimate as string;
}
},
{ immediate: true }

View File

@ -11,7 +11,7 @@
<script setup lang="ts">
import InnerLink from '../InnerLink/index.vue';
import useTagsViewStore from '@/store/modules/tagsView';
import { useTagsViewStore } from '@/store/modules/tagsView';
const route = useRoute();
const tagsViewStore = useTagsViewStore();

View File

@ -90,15 +90,16 @@
<script setup lang="ts">
import SearchMenu from './TopBar/search.vue';
import useAppStore from '@/store/modules/app';
import useUserStore from '@/store/modules/user';
import useSettingsStore from '@/store/modules/settings';
import useNoticeStore from '@/store/modules/notice';
import { useAppStore } from '@/store/modules/app';
import { useUserStore } from '@/store/modules/user';
import { useSettingsStore } from '@/store/modules/settings';
import { useNoticeStore } from '@/store/modules/notice';
import { getTenantList } from '@/api/login';
import { dynamicClear, dynamicTenant } from '@/api/system/tenant';
import { TenantVO } from '@/api/types';
import notice from './notice/index.vue';
import router from '@/router';
import {ElMessageBoxOptions} from "element-plus/es/components/message-box/src/message-box.type";
const appStore = useAppStore();
const userStore = useUserStore();
@ -128,8 +129,8 @@ const dynamicTenantEvent = async (tenantId: string) => {
await dynamicTenant(tenantId);
dynamic.value = true;
await proxy?.$router.push('/');
await proxy?.proxy.$tab.closeAllPage();
await proxy?.proxy.$tab.refreshPage();
await proxy?.$tab.closeAllPage();
await proxy?.$tab.refreshPage();
}
};
@ -137,8 +138,8 @@ const dynamicClearEvent = async () => {
await dynamicClear();
dynamic.value = false;
await proxy?.$router.push('/');
await proxy?.proxy.$tab.closeAllPage();
await proxy?.proxy.$tab.refreshPage();
await proxy?.$tab.closeAllPage();
await proxy?.$tab.refreshPage();
};
/** 租户列表 */
@ -163,7 +164,7 @@ const logout = async () => {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
});
} as ElMessageBoxOptions);
userStore.logout().then(() => {
router.replace({
path: '/login',

View File

@ -89,9 +89,9 @@
<script setup lang="ts">
import { useDynamicTitle } from '@/utils/dynamicTitle';
import useAppStore from '@/store/modules/app';
import useSettingsStore from '@/store/modules/settings';
import usePermissionStore from '@/store/modules/permission';
import { useAppStore } from '@/store/modules/app';
import { useSettingsStore } from '@/store/modules/settings';
import { usePermissionStore } from '@/store/modules/permission';
import { handleThemeStyle } from '@/utils/theme';
import { SideThemeEnum } from '@/enums/SideThemeEnum';
import defaultSettings from '@/settings';

View File

@ -24,7 +24,7 @@
<script setup lang="ts">
import variables from '@/assets/styles/variables.module.scss';
import logo from '@/assets/logo/logo.png';
import useSettingsStore from '@/store/modules/settings';
import { useSettingsStore } from '@/store/modules/settings';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
defineProps({

View File

@ -24,9 +24,9 @@
import Logo from './Logo.vue';
import SidebarItem from './SidebarItem.vue';
import variables from '@/assets/styles/variables.module.scss';
import useAppStore from '@/store/modules/app';
import useSettingsStore from '@/store/modules/settings';
import usePermissionStore from '@/store/modules/permission';
import { useAppStore } from '@/store/modules/app';
import { useSettingsStore } from '@/store/modules/settings';
import { usePermissionStore } from '@/store/modules/permission';
import { RouteRecordRaw } from 'vue-router';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;

View File

@ -6,7 +6,7 @@
<script setup lang="ts">
import { RouteLocationNormalized } from 'vue-router';
import useTagsViewStore from '@/store/modules/tagsView';
import { useTagsViewStore } from '@/store/modules/tagsView';
const tagAndTagSpacing = ref(4);

View File

@ -32,9 +32,9 @@
<script setup lang="ts">
import ScrollPane from './ScrollPane.vue';
import { getNormalPath } from '@/utils/ruoyi';
import useSettingsStore from '@/store/modules/settings';
import usePermissionStore from '@/store/modules/permission';
import useTagsViewStore from '@/store/modules/tagsView';
import { useSettingsStore } from '@/store/modules/settings';
import { usePermissionStore } from '@/store/modules/permission';
import { useTagsViewStore } from '@/store/modules/tagsView';
import { RouteRecordRaw, RouteLocationNormalized } from 'vue-router';
const visible = ref(false);

View File

@ -28,7 +28,7 @@
<script setup lang="ts" name="layoutBreadcrumbSearch">
import { getNormalPath } from '@/utils/ruoyi';
import { isHttp } from '@/utils/validate';
import usePermissionStore from '@/store/modules/permission';
import { usePermissionStore } from '@/store/modules/permission';
import { RouteRecordRaw } from 'vue-router';
type Router = Array<{
path: string;
@ -130,7 +130,7 @@ defineExpose({
});
</script>
<style scoped lang="scss">
<style lang="scss" scoped>
.layout-search-dialog {
position: relative;
:deep(.el-dialog) {

View File

@ -25,7 +25,7 @@
<script setup lang="ts" name="layoutBreadcrumbUserNews">
import { storeToRefs } from 'pinia';
import useNoticeStore from '@/store/modules/notice';
import { useNoticeStore } from '@/store/modules/notice';
const noticeStore = storeToRefs(useNoticeStore());
const { readAll } = useNoticeStore();
@ -65,7 +65,7 @@ onMounted(() => {
});
</script>
<style scoped lang="scss">
<style lang="scss" scoped>
.layout-navbars-breadcrumb-user-news {
.head-box {
display: flex;

View File

@ -24,8 +24,8 @@
<script setup lang="ts">
import SideBar from './components/Sidebar/index.vue';
import { AppMain, Navbar, Settings, TagsView } from './components';
import useAppStore from '@/store/modules/app';
import useSettingsStore from '@/store/modules/settings';
import { useAppStore } from '@/store/modules/app';
import { useSettingsStore } from '@/store/modules/settings';
import { initWebSocket } from '@/utils/websocket';
import { initSSE } from '@/utils/sse';
@ -68,7 +68,7 @@ onMounted(() => {
});
onMounted(() => {
let protocol = window.location.protocol === 'https:' ? 'wss://' : 'ws://';
const protocol = window.location.protocol === 'https:' ? 'wss://' : 'ws://';
initWebSocket(protocol + window.location.host + import.meta.env.VITE_APP_BASE_API + '/resource/websocket');
});
@ -86,11 +86,11 @@ const setLayout = () => {
</script>
<style lang="scss" scoped>
@import '@/assets/styles/mixin.scss';
@import '@/assets/styles/variables.module.scss';
@use '@/assets/styles/mixin.scss';
@use '@/assets/styles/variables.module.scss' as *;
.app-wrapper {
@include clearfix;
@include mixin.clearfix;
position: relative;
height: 100%;
width: 100%;

View File

@ -5,9 +5,10 @@ import 'nprogress/nprogress.css';
import { getToken } from '@/utils/auth';
import { isHttp, isPathMatch } from '@/utils/validate';
import { isRelogin } from '@/utils/request';
import useUserStore from '@/store/modules/user';
import useSettingsStore from '@/store/modules/settings';
import usePermissionStore from '@/store/modules/permission';
import { useUserStore } from '@/store/modules/user';
import { useSettingsStore } from '@/store/modules/settings';
import { usePermissionStore } from '@/store/modules/permission';
import { ElMessage } from 'element-plus/es';
NProgress.configure({ showSpinner: false });
const whiteList = ['/login', '/register', '/social-callback', '/register*', '/register/*'];
@ -19,7 +20,7 @@ const isWhiteList = (path: string) => {
router.beforeEach(async (to, from, next) => {
NProgress.start();
if (getToken()) {
to.meta.title && useSettingsStore().setTitle(to.meta.title);
to.meta.title && useSettingsStore().setTitle(to.meta.title as string);
/* has token*/
if (to.path === '/login') {
next({ path: '/' });

View File

@ -1,4 +1,4 @@
import useUserStore from '@/store/modules/user';
import { useUserStore } from '@/store/modules/user';
const authPermission = (permission: string): boolean => {
const all_permission = '*:*:*';

View File

@ -1,6 +1,6 @@
import router from '@/router';
import { RouteLocationMatched, RouteLocationNormalized, RouteLocationRaw } from 'vue-router';
import useTagsViewStore from '@/store/modules/tagsView';
import { useTagsViewStore } from '@/store/modules/tagsView';
export default {
/**

View File

@ -50,13 +50,29 @@ const setting: DefaultSettings = {
*/
errorLog: 'production',
/**
*
*/
animationEnable: false,
/**
*
*/
dark: false,
/**
*
*/
language: LanguageEnum.zh_CN,
/**
*
*/
size: 'default',
/**
*
*/
layout: ''
};
export default setting;

View File

@ -1,3 +1,5 @@
import { createPinia } from "pinia";
const store = createPinia();
export default store;

View File

@ -1,5 +1,8 @@
import zhCN from 'element-plus/es/locale/lang/zh-cn';
import enUS from 'element-plus/es/locale/lang/en';
import { defineStore } from 'pinia';
import { useStorage } from '@vueuse/core';
import { ref, reactive, computed } from 'vue';
export const useAppStore = defineStore('app', () => {
const sidebarStatus = useStorage('sidebarStatus', '1');
@ -68,5 +71,3 @@ export const useAppStore = defineStore('app', () => {
toggleSideBarHide
};
});
export default useAppStore;

View File

@ -1,3 +1,5 @@
import { defineStore } from 'pinia';
export const useDictStore = defineStore('dict', () => {
const dict = ref<Map<string, DictDataOption[]>>(new Map());
@ -61,5 +63,3 @@ export const useDictStore = defineStore('dict', () => {
cleanDict
};
});
export default useDictStore;

View File

@ -1,4 +1,5 @@
import { defineStore } from 'pinia';
import { reactive } from 'vue';
interface NoticeItem {
title?: string;
@ -38,5 +39,3 @@ export const useNoticeStore = defineStore('notice', () => {
clearNotice
};
});
export default useNoticeStore;

View File

@ -4,11 +4,10 @@ import store from '@/store';
import { getRouters } from '@/api/menu';
import auth from '@/plugins/auth';
import { RouteRecordRaw } from 'vue-router';
import Layout from '@/layout/index.vue';
import ParentView from '@/components/ParentView/index.vue';
import InnerLink from '@/layout/components/InnerLink/index.vue';
import { ref } from 'vue';
import { createCustomNameComponent } from '@/utils/createCustomNameComponent';
// 匹配views里面所有的.vue文件
@ -23,6 +22,9 @@ export const usePermissionStore = defineStore('permission', () => {
const getRoutes = (): RouteRecordRaw[] => {
return routes.value as RouteRecordRaw[];
};
const getDefaultRoutes = (): RouteRecordRaw[] => {
return defaultRoutes.value as RouteRecordRaw[];
};
const getSidebarRoutes = (): RouteRecordRaw[] => {
return sidebarRouters.value as RouteRecordRaw[];
};
@ -97,29 +99,14 @@ export const usePermissionStore = defineStore('permission', () => {
};
const filterChildren = (childrenMap: RouteRecordRaw[], lastRouter?: RouteRecordRaw): RouteRecordRaw[] => {
let children: RouteRecordRaw[] = [];
childrenMap.forEach((el) => {
if (el.children && el.children.length) {
if (el.component?.toString() === 'ParentView' && !lastRouter) {
el.children.forEach((c) => {
c.path = el.path + '/' + c.path;
if (c.children && c.children.length) {
children = children.concat(filterChildren(c.children, c));
return;
}
children.push(c);
});
return;
}
childrenMap.forEach(el => {
el.path = lastRouter ? lastRouter.path + '/' + el.path : el.path;
if (el.children && el.children.length && el.component?.toString() === 'ParentView') {
children = children.concat(filterChildren(el.children, el));
} else {
children.push(el);
}
if (lastRouter) {
el.path = lastRouter.path + '/' + el.path;
if (el.children && el.children.length) {
children = children.concat(filterChildren(el.children, el));
return;
}
}
children = children.concat(el);
});
})
return children;
};
return {
@ -129,6 +116,7 @@ export const usePermissionStore = defineStore('permission', () => {
defaultRoutes,
getRoutes,
getDefaultRoutes,
getSidebarRoutes,
getTopbarRoutes,
@ -217,5 +205,3 @@ function duplicateRouteChecker(localRoutes: Route[], routes: Route[]) {
nameList.push(route.name.toString());
});
}
export default usePermissionStore;

View File

@ -1,8 +1,11 @@
import { defineStore } from 'pinia';
import defaultSettings from '@/settings';
import { useDynamicTitle } from '@/utils/dynamicTitle';
import { useStorage } from '@vueuse/core';
import { ref } from 'vue';
export const useSettingsStore = defineStore('setting', () => {
// @ts-ignore
const storageSetting = useStorage<LayoutSetting>('layout-setting', {
topNav: defaultSettings.topNav,
tagsView: defaultSettings.tagsView,
@ -43,5 +46,3 @@ export const useSettingsStore = defineStore('setting', () => {
setTitle
};
});
export default useSettingsStore;

View File

@ -1,4 +1,6 @@
import { RouteLocationNormalized } from 'vue-router';
import { defineStore } from 'pinia';
import { ref } from 'vue';
export const useTagsViewStore = defineStore('tagsView', () => {
const visitedViews = ref<RouteLocationNormalized[]>([]);
@ -230,4 +232,3 @@ export const useTagsViewStore = defineStore('tagsView', () => {
delIframeView
};
});
export default useTagsViewStore;

View File

@ -3,7 +3,8 @@ import { getToken, removeToken, setToken } from '@/utils/auth';
import { login as loginApi, logout as logoutApi, getInfo as getUserInfo } from '@/api/login';
import { LoginData } from '@/api/types';
import defAva from '@/assets/images/profile.jpg';
import store from '@/store';
import { defineStore } from 'pinia';
import { ref } from 'vue';
export const useUserStore = defineStore('user', () => {
const token = ref(getToken());
@ -83,9 +84,3 @@ export const useUserStore = defineStore('user', () => {
setAvatar
};
});
export default useUserStore;
// 非setup
export function useUserStoreHook() {
return useUserStore(store);
}

View File

@ -1,4 +1,4 @@
import useUserStore from '@/store/modules/user';
import { useUserStore } from '@/store/modules/user';
/**
*

View File

@ -167,39 +167,21 @@ export const handleTree = <T>(data: any[], id?: string, parentId?: string, child
};
const childrenListMap: any = {};
const nodeIds: any = {};
const tree: T[] = [];
for (const d of data) {
const parentId = d[config.parentId];
if (childrenListMap[parentId] == null) {
childrenListMap[parentId] = [];
}
nodeIds[d[config.id]] = d;
childrenListMap[parentId].push(d);
const id = d[config.id];
childrenListMap[id] = d;
}
for (const d of data) {
const parentId = d[config.parentId];
if (nodeIds[parentId] == null) {
const parentObj = childrenListMap[parentId]
if (!parentObj) {
tree.push(d);
} else {
parentObj[config.childrenList].push(d)
}
}
const adaptToChildrenList = (o: any) => {
if (childrenListMap[o[config.id]] !== null) {
o[config.childrenList] = childrenListMap[o[config.id]];
}
if (o[config.childrenList]) {
for (const c of o[config.childrenList]) {
adaptToChildrenList(c);
}
}
};
for (const t of tree) {
adaptToChildrenList(t);
}
return tree;
};

View File

@ -1,6 +1,6 @@
import { getToken } from '@/utils/auth';
import { ElNotification } from 'element-plus';
import useNoticeStore from '@/store/modules/notice';
import { useNoticeStore } from '@/store/modules/notice';
// 初始化
export const initSSE = (url: any) => {

View File

@ -1,6 +1,6 @@
import { getToken } from '@/utils/auth';
import { ElNotification } from 'element-plus';
import useNoticeStore from '@/store/modules/notice';
import { useNoticeStore } from '@/store/modules/notice';
// 初始化socket
export const initWebSocket = (url: any) => {

View File

@ -62,7 +62,7 @@
<el-tree-select
v-model="form.parentId"
:data="treeOptions"
:props="{ value: 'id', label: 'treeName', children: 'children' }"
:props="{ value: 'id', label: 'treeName', children: 'children' } as any"
value-key="id"
placeholder="请选择父id"
check-strictly

View File

@ -33,7 +33,7 @@
* 部署方式 Docker 容器编排 一键部署业务集群<br />
* 国际化 SpringMessage Spring标准国际化方案<br />
</p>
<p><b>当前版本:</b> <span>v5.3.0</span></p>
<p><b>当前版本:</b> <span>v5.3.1</span></p>
<p>
<el-tag type="danger">&yen;免费开源</el-tag>
</p>
@ -100,7 +100,7 @@ const goTarget = (url: string) => {
};
</script>
<style scoped lang="scss">
<style lang="scss" scoped>
.home {
blockquote {
padding: 10px 20px;

View File

@ -73,7 +73,7 @@
</el-form>
<!-- 底部 -->
<div class="el-login-footer">
<span>Copyright © 2018-2024 疯狂的狮子Li All Rights Reserved.</span>
<span>Copyright © 2018-2025 疯狂的狮子Li All Rights Reserved.</span>
</div>
</div>
</template>

View File

@ -1,6 +1,6 @@
<template>
<div class="p-2">
<el-row>
<el-row :gutter="10">
<el-col :span="24" class="card-box">
<el-card shadow="hover">
<template #header>

View File

@ -95,7 +95,7 @@ const typeFormat = (row: OperLogForm) => {
};
</script>
<style scoped>
<style lang="scss" scoped>
/**
label宽度固定
*/

View File

@ -2,7 +2,7 @@
<div></div>
</template>
<script setup>
<script setup lang="ts">
import { useRoute, useRouter } from 'vue-router';
const route = useRoute();

View File

@ -67,7 +67,7 @@
</el-form>
<!-- 底部 -->
<div class="el-register-footer">
<span>Copyright © 2018-2024 疯狂的狮子Li All Rights Reserved.</span>
<span>Copyright © 2018-2025 疯狂的狮子Li All Rights Reserved.</span>
</div>
</div>
</template>

View File

@ -2,7 +2,7 @@
<div class="p-2">
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
<div v-show="showSearch" class="search">
<el-form ref="queryFormRef" :model="queryParams" :inline="true">
<el-form ref="queryFormRef" :model="queryParams" :inline="true" label-width="85px">
<el-form-item label="客户端key" prop="clientKey">
<el-input v-model="queryParams.clientKey" placeholder="请输入客户端key" clearable @keyup.enter="handleQuery" />
</el-form-item>

View File

@ -82,7 +82,7 @@
<el-tree-select
v-model="form.parentId"
:data="deptOptions"
:props="{ value: 'deptId', label: 'deptName', children: 'children' }"
:props="{ value: 'deptId', label: 'deptName', children: 'children' } as any"
value-key="deptId"
placeholder="选择上级部门"
check-strictly

View File

@ -126,7 +126,7 @@
</template>
<script setup name="Data" lang="ts">
import useDictStore from '@/store/modules/dict';
import { useDictStore } from '@/store/modules/dict';
import { optionselect as getDictOptionselect, getType } from '@/api/system/dict/type';
import { listData, getData, delData, addData, updateData } from '@/api/system/dict/data';
import { DictTypeVO } from '@/api/system/dict/type/types';

View File

@ -108,7 +108,7 @@
</template>
<script setup name="Dict" lang="ts">
import useDictStore from '@/store/modules/dict';
import { useDictStore } from '@/store/modules/dict';
import { listType, getType, delType, addType, updateType, refreshCache } from '@/api/system/dict/type';
import { DictTypeForm, DictTypeQuery, DictTypeVO } from '@/api/system/dict/type/types';

View File

@ -85,7 +85,7 @@
<el-tree-select
v-model="form.parentId"
:data="menuOptions"
:props="{ value: 'menuId', label: 'menuName', children: 'children' }"
:props="{ value: 'menuId', label: 'menuName', children: 'children' } as any"
value-key="menuId"
placeholder="选择上级菜单"
check-strictly

View File

@ -10,7 +10,7 @@
class="mt-2"
node-key="id"
:data="deptOptions"
:props="{ label: 'label', children: 'children' }"
:props="{ label: 'label', children: 'children' } as any"
:expand-on-click-node="false"
:filter-node-method="filterNode"
highlight-current
@ -43,7 +43,7 @@
<el-tree-select
v-model="queryParams.deptId"
:data="deptOptions"
:props="{ value: 'id', label: 'label', children: 'children' }"
:props="{ value: 'id', label: 'label', children: 'children' } as any"
value-key="id"
placeholder="请选择部门"
check-strictly
@ -133,7 +133,7 @@
<el-tree-select
v-model="form.deptId"
:data="deptOptions"
:props="{ value: 'id', label: 'label', children: 'children' }"
:props="{ value: 'id', label: 'label', children: 'children' } as any"
value-key="id"
placeholder="请选择部门"
check-strictly

View File

@ -156,5 +156,3 @@ onMounted(() => {
getList();
});
</script>
<style lang="scss" scoped></style>

View File

@ -135,7 +135,7 @@
node-key="id"
:check-strictly="!form.menuCheckStrictly"
empty-text="加载中,请稍候"
:props="{ label: 'label', children: 'children' }"
:props="{ label: 'label', children: 'children' } as any"
></el-tree>
</el-form-item>
<el-form-item label="备注">
@ -177,7 +177,7 @@
node-key="id"
:check-strictly="!form.deptCheckStrictly"
empty-text="加载中,请稍候"
:props="{ label: 'label', children: 'children' }"
:props="{ label: 'label', children: 'children' } as any"
></el-tree>
</el-form-item>
</el-form>

View File

@ -128,5 +128,3 @@ defineExpose({
show
});
</script>
<style scoped></style>

View File

@ -155,7 +155,7 @@ import {
syncTenantDict
} from '@/api/system/tenant';
import { selectTenantPackage } from '@/api/system/tenantPackage';
import useUserStore from '@/store/modules/user';
import { useUserStore } from '@/store/modules/user';
import { TenantForm, TenantQuery, TenantVO } from '@/api/system/tenant/types';
import { TenantPkgVO } from '@/api/system/tenantPackage/types';

View File

@ -82,7 +82,7 @@
node-key="id"
:check-strictly="!form.menuCheckStrictly"
empty-text="加载中,请稍候"
:props="{ label: 'label', children: 'children' }"
:props="{ label: 'label', children: 'children' } as any"
></el-tree>
</el-form-item>
<el-form-item label="备注" prop="remark">

View File

@ -10,7 +10,7 @@
class="mt-2"
node-key="id"
:data="deptOptions"
:props="{ label: 'label', children: 'children' }"
:props="{ label: 'label', children: 'children' } as any"
:expand-on-click-node="false"
:filter-node-method="filterNode"
highlight-current
@ -81,8 +81,9 @@
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item icon="Download" @click="importTemplate">下载模板</el-dropdown-item>
<el-dropdown-item v-has-permi="['system:user:import']" icon="Top" @click="handleImport">导入数据</el-dropdown-item>
<el-dropdown-item v-has-permi="['system:user:export']" icon="Download" @click="handleExport">导出数据</el-dropdown-item>
<!-- 注意 由于el-dropdown-item标签是延迟加载的 所以v-has-permi自定义标签不生效 需要使用v-if调用方法执行 -->
<el-dropdown-item v-if="checkPermi(['system:user:import'])" icon="Top" @click="handleImport">导入数据</el-dropdown-item>
<el-dropdown-item v-if="checkPermi(['system:user:export'])" icon="Download" @click="handleExport">导出数据</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
@ -155,7 +156,7 @@
<el-tree-select
v-model="form.deptId"
:data="enabledDeptOptions"
:props="{ value: 'id', label: 'label', children: 'children' }"
:props="{ value: 'id', label: 'label', children: 'children' } as any"
value-key="id"
placeholder="请选择归属部门"
check-strictly
@ -287,13 +288,15 @@
<script setup name="User" lang="ts">
import api from '@/api/system/user';
import { UserForm, UserQuery, UserVO } from '@/api/system/user/types';
import {DeptTreeVO, DeptVO} from '@/api/system/dept/types';
import { DeptTreeVO, DeptVO } from '@/api/system/dept/types';
import { RoleVO } from '@/api/system/role/types';
import { PostQuery, PostVO } from '@/api/system/post/types';
import { treeselect } from '@/api/system/dept';
import { globalHeaders } from '@/utils/request';
import { to } from 'await-to-js';
import { optionselect } from '@/api/system/post';
import { hasPermi } from '@/directive/permission';
import { checkPermi } from '@/utils/permission';
const router = useRouter();
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
@ -450,7 +453,7 @@ const getDeptTree = async () => {
/** 过滤禁用的部门 */
const filterDisabledDept = (deptList: DeptTreeVO[]) => {
return deptList.filter(dept => {
return deptList.filter((dept) => {
if (dept.disabled) {
return false;
}
@ -660,5 +663,3 @@ async function handleDeptChange(value: number | string) {
form.value.postIds = [];
}
</script>
<style lang="scss" scoped></style>

View File

@ -26,7 +26,7 @@
</div>
</template>
<script name="Online" lang="ts" setup>
<script setup name="Online" lang="ts">
import { delOnline } from '@/api/monitor/online';
import { propTypes } from '@/utils/propTypes';

View File

@ -55,10 +55,10 @@
</div>
</template>
<script lang="ts" setup>
<script setup lang="ts">
import { authUnlock, authBinding } from '@/api/system/social/auth';
import { propTypes } from '@/utils/propTypes';
import useUserStore from '@/store/modules/user';
import { useUserStore } from '@/store/modules/user';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
@ -94,7 +94,7 @@ const authUrl = (source: string) => {
};
</script>
<style type="text/css">
<style lang="scss" scoped>
.user-bind .third-app {
display: -webkit-box;
display: -ms-flexbox;
@ -128,8 +128,9 @@ a {
}
.provider-desc {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol',
'Liberation Sans', 'PingFang SC', 'Microsoft YaHei', 'Hiragino Sans GB', 'Wenquanyi Micro Hei', 'WenQuanYi Zen Hei', 'ST Heiti', SimHei, SimSun,
font-family:
-apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Liberation Sans',
'PingFang SC', 'Microsoft YaHei', 'Hiragino Sans GB', 'Wenquanyi Micro Hei', 'WenQuanYi Zen Hei', 'ST Heiti', SimHei, SimSun,
'WenQuanYi Zen Hei Sharp', sans-serif;
font-size: 1.071rem;
}

View File

@ -59,7 +59,7 @@
import 'vue-cropper/dist/index.css';
import { VueCropper } from 'vue-cropper';
import { uploadAvatar } from '@/api/system/user';
import useUserStore from '@/store/modules/user';
import { useUserStore } from '@/store/modules/user';
import { UploadRawFile } from 'element-plus';
interface Options {

View File

@ -89,7 +89,7 @@
</el-table-column>
<el-table-column label="字典类型" min-width="12%">
<template #default="scope">
<el-select v-model="scope.row.dictType" clearable filterable placeholder="请选择">
<el-select v-model="scope.row.dictType" clearable filterable placeholder="请选择" value-on-clear="">
<el-option v-for="dict in dictOptions" :key="dict.dictType" :label="dict.dictName" :value="dict.dictType">
<span style="float: left">{{ dict.dictName }}</span>
<span style="float: right; color: #8492a6; font-size: 13px">{{ dict.dictType }}</span>

View File

@ -70,7 +70,7 @@
<el-tree-select
v-model="infoForm.parentMenuId"
:data="menuOptions"
:props="{ value: 'menuId', label: 'menuName', children: 'children' }"
:props="{ value: 'menuId', label: 'menuName', children: 'children' } as any"
value-key="menuId"
node-key="menuId"
placeholder="选择上级菜单"

View File

@ -58,7 +58,7 @@
<el-tree-select
v-model="form.parentId"
:data="categoryOptions"
:props="{ value: 'categoryId', label: 'categoryName', children: 'children' }"
:props="{ value: 'categoryId', label: 'categoryName', children: 'children' } as any"
value-key="categoryId"
placeholder="请选择上级分类"
check-strictly

View File

@ -111,6 +111,10 @@ const flowCodeOptions = [
{
value: 'leave5',
label: '请假申请-并行会签网关'
},
{
value: 'leave6',
label: '请假申请-排他并行会签'
}
];

View File

@ -10,7 +10,7 @@
class="mt-2"
node-key="id"
:data="categoryOptions"
:props="{ label: 'label', children: 'children' }"
:props="{ label: 'label', children: 'children' } as any"
:expand-on-click-node="false"
:filter-node-method="filterNode"
highlight-current
@ -131,7 +131,7 @@
<el-tree-select
v-model="selectCategory"
:data="categoryOptions"
:props="{ value: 'id', label: 'label', children: 'children' }"
:props="{ value: 'id', label: 'label', children: 'children' } as any"
filterable
value-key="id"
:render-after-expand="false"
@ -163,7 +163,7 @@
<el-tree-select
v-model="form.category"
:data="categoryOptions"
:props="{ value: 'id', label: 'label', children: 'children' }"
:props="{ value: 'id', label: 'label', children: 'children' } as any"
filterable
value-key="id"
:render-after-expand="false"
@ -177,7 +177,7 @@
<el-form-item label="流程名称" prop="flowName">
<el-input v-model="form.flowName" placeholder="请输入流程名称" maxlength="100" show-word-limit />
</el-form-item>
<el-form-item label="表单路径" prop="flowName">
<el-form-item label="表单路径" prop="formPath">
<el-input v-model="form.formPath" placeholder="请输入表单路径" maxlength="100" show-word-limit />
</el-form-item>
</el-form>
@ -190,12 +190,13 @@
</div>
</template>
<script lang="ts" setup name="processDefinition">
<script setup name="processDefinition" lang="ts">
import { listDefinition, deleteDefinition, active, importDef, unPublishList, publish, add, edit, getInfo, copy } from '@/api/workflow/definition';
import { categoryTree } from '@/api/workflow/category';
import { CategoryTreeVO } from '@/api/workflow/category/types';
import { FlowDefinitionQuery, FlowDefinitionVo, FlowDefinitionForm } from '@/api/workflow/definition/types';
import { UploadRequestOptions, TabsPaneContext } from 'element-plus';
import { ElMessageBoxOptions } from "element-plus/es/components/message-box/src/message-box.type";
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
@ -324,9 +325,9 @@ const handleSelectionChange = (selection: any) => {
};
//
const getPageList = async () => {
console.log(proxy.$route.query.activeName)
if (proxy.$route.query.activeName) {
activeName.value = proxy.$route.query.activeName;
let query = proxy.$route.query;
if (query.activeName) {
activeName.value = query.activeName;
}
if (activeName.value === '0') {
getList();
@ -370,7 +371,7 @@ const handlePublish = async (row?: FlowDefinitionVo) => {
loading.value = true;
await publish(row.id).finally(() => (loading.value = false));
processDefinitionDialog.visible = false;
activeName.value = "0"
activeName.value = '0';
await handleQuery();
proxy?.$modal.msgSuccess('发布成功');
};
@ -417,7 +418,7 @@ const handlerImportDefinition = (data: UploadRequestOptions): XMLHttpRequest =>
.then(() => {
uploadDialog.visible = false;
proxy?.$modal.msgSuccess('部署成功');
activeName.value = "1"
activeName.value = '1';
handleQuery();
})
.finally(() => {
@ -482,9 +483,9 @@ const handleSubmit = async () => {
if (valid) {
loading.value = true;
if (form.value.id) {
await edit(form.value).finally(() => loading.value = false);
await edit(form.value).finally(() => (loading.value = false));
} else {
await add(form.value).finally(() => loading.value = false);
await add(form.value).finally(() => (loading.value = false));
}
proxy?.$modal.msgSuccess('操作成功');
modelDialog.visible = false;
@ -498,15 +499,17 @@ const handleCopyDef = async (row: FlowDefinitionVo) => {
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
} as ElMessageBoxOptions).then(() => {
loading.value = true;
copy(row.id).then((resp) => {
if (resp.code === 200) {
proxy?.$modal.msgSuccess('操作成功');
activeName.value = "1"
handleQuery();
}
}).finally(() => loading.value = false);
copy(row.id)
.then((resp) => {
if (resp.code === 200) {
proxy?.$modal.msgSuccess('操作成功');
activeName.value = '1';
handleQuery();
}
})
.finally(() => (loading.value = false));
});
};

View File

@ -10,7 +10,7 @@
class="mt-2"
node-key="id"
:data="categoryOptions"
:props="{ label: 'label', children: 'children' }"
:props="{ label: 'label', children: 'children' } as any"
:expand-on-click-node="false"
:filter-node-method="filterNode"
highlight-current
@ -174,7 +174,7 @@
</div>
</template>
<script lang="ts" setup>
<script setup lang="ts">
import { pageByRunning, pageByFinish, deleteByInstanceIds, instanceVariable, invalid } from '@/api/workflow/instance';
import { categoryTree } from '@/api/workflow/category';
import { CategoryTreeVO } from '@/api/workflow/category/types';

View File

@ -97,14 +97,14 @@
</el-card>
<!-- 选人组件 -->
<UserSelect ref="userSelectRef" :multiple="false" @confirm-call-back="submitCallback"></UserSelect>
<!-- 选人组件 -->
<!-- 流程干预组件 -->
<processMeddle ref="processMeddleRef" @submitCallback="getWaitingList"></processMeddle>
<!-- 申请人 -->
<UserSelect ref="applyUserSelectRef" :multiple="true" :data="selectUserIds" @confirm-call-back="userSelectCallBack"></UserSelect>
</div>
</template>
<script lang="ts" setup>
<script setup lang="ts">
import { pageByAllTaskWait, pageByAllTaskFinish, updateAssignee } from '@/api/workflow/task';
import UserSelect from '@/components/UserSelect';
import { TaskQuery } from '@/api/workflow/task/types';

View File

@ -10,7 +10,7 @@
class="mt-2"
node-key="id"
:data="categoryOptions"
:props="{ label: 'label', children: 'children' }"
:props="{ label: 'label', children: 'children' } as any"
:expand-on-click-node="false"
:filter-node-method="filterNode"
highlight-current
@ -101,7 +101,7 @@
</div>
</template>
<script lang="ts" setup>
<script setup lang="ts">
import { pageByCurrent, deleteByInstanceIds, cancelProcessApply } from '@/api/workflow/instance';
import { categoryTree } from '@/api/workflow/category';
import { CategoryTreeVO } from '@/api/workflow/category/types';

View File

@ -59,7 +59,7 @@
</div>
</template>
<script lang="ts" setup>
<script setup lang="ts">
import { pageByTaskCopy } from '@/api/workflow/task';
import { TaskQuery } from '@/api/workflow/task/types';
import workflowCommon from '@/api/workflow/workflowCommon';

View File

@ -80,7 +80,7 @@
</div>
</template>
<script lang="ts" setup>
<script setup lang="ts">
import { pageByTaskFinish } from '@/api/workflow/task';
import { TaskQuery, FlowTaskVO } from '@/api/workflow/task/types';
import workflowCommon from '@/api/workflow/workflowCommon';

View File

@ -77,7 +77,7 @@
</div>
</template>
<script lang="ts" setup>
<script setup lang="ts">
import { pageByTaskWait } from '@/api/workflow/task';
import { TaskQuery, FlowTaskVO } from '@/api/workflow/task/types';
import workflowCommon from '@/api/workflow/workflowCommon';

View File

@ -1,31 +1,42 @@
{
"$schema": "https://json.schemastore.org/tsconfig",
"compilerOptions": {
"target": "esnext",
"module": "esnext",
// "useDefineForClassFields": true,
"moduleResolution": "bundler",
"baseUrl": ".",
// https://vite.dev/config/build-options.html#build-target
"target": "ES2020",
"module": "ESNext",
"moduleResolution": "Bundler",
"lib": ["ESNext", "DOM", "DOM.Iterable"],
"skipLibCheck": true,
// This setting lets you specify a file for storing incremental compilation information as a part of composite projects which enables faster building of larger TypeScript codebases.
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.tsbuildinfo",
"strict": true,
"allowJs": true,
"jsx": "preserve",
"strictNullChecks": false,
"sourceMap": true,
"resolveJsonModule": true,
"esModuleInterop": true,
"strictFunctionTypes": false,
"lib": ["esnext", "dom"],
"noImplicitAny": false,
"baseUrl": ".",
"allowJs": true,
"experimentalDecorators": true,
"noEmit": true,
"paths": {
"@/*": ["src/*"]
"@/*": ["./src/*"]
},
"types": ["vite/client"],
"skipLibCheck": true,
"removeComments": true,
//
"allowSyntheticDefaultImports": true,
"forceConsistentCasingInFileNames": true
"types": ["node", "vite/client"],
//
"noImplicitAny": false, // any
"removeComments": true, // ts
"experimentalDecorators": true, //
"strictFunctionTypes": false, //
"strictNullChecks": false, //
"allowSyntheticDefaultImports": true, //
"forceConsistentCasingInFileNames": true // 使
},
"include": ["src/**/*.ts", "src/**/*.vue", "src/types/**/*.d.ts", "vite.config.ts"],
"exclude": ["node_modules", "dist", "**/*.js", "**/*.md", "src/**/*.md"]
"include": [
"src/**/*.ts",
"src/**/*.vue",
"vite.config.ts",
"vitest.config.ts",
"eslint.config.ts",
"src/**/*.d.ts"
],
"exclude": ["node_modules", "dist", "src/**/__tests__/*"]
}

View File

@ -1,9 +1,9 @@
import { UserConfig, ConfigEnv, loadEnv, defineConfig } from 'vite';
import { defineConfig, loadEnv } from 'vite';
import createPlugins from './vite/plugins';
import autoprefixer from 'autoprefixer'; // css自动添加兼容性前缀
import path from 'path';
export default defineConfig(({ mode, command }: ConfigEnv): UserConfig => {
export default defineConfig(({ mode, command }) => {
const env = loadEnv(mode, process.cwd());
return {
// 部署生产环境和开发环境下的URL。
@ -12,7 +12,6 @@ export default defineConfig(({ mode, command }: ConfigEnv): UserConfig => {
base: env.VITE_APP_CONTEXT_PATH,
resolve: {
alias: {
'~': path.resolve(__dirname, './'),
'@': path.resolve(__dirname, './src')
},
extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.vue']
@ -35,18 +34,20 @@ export default defineConfig(({ mode, command }: ConfigEnv): UserConfig => {
css: {
preprocessorOptions: {
scss: {
javascriptEnabled: true
// additionalData: '@use "@/assets/styles/variables.module.scss as *";'
// javascriptEnabled: true
api: 'modern-compiler'
}
},
postcss: {
plugins: [
// 浏览器兼容性
autoprefixer(),
{
postcssPlugin: 'internal:charset-removal',
AtRule: {
charset: (atRule) => {
if (atRule.name === 'charset') {
atRule.remove();
}
atRule.remove();
}
}
}

View File

@ -1,22 +1,18 @@
import AutoImport from 'unplugin-auto-import/vite';
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers';
import IconsResolver from 'unplugin-icons/resolver';
export default (path: any) => {
return AutoImport({
// 自动导入 Vue 相关函数
imports: ['vue', 'vue-router', '@vueuse/core', 'pinia'],
eslintrc: {
enabled: false,
enabled: true,
filepath: './.eslintrc-auto-import.json',
globalsPropValue: true
},
resolvers: [
// 自动导入 Element Plus 相关函数ElMessage, ElMessageBox... (带样式)
ElementPlusResolver(),
IconsResolver({
prefix: 'Icon'
})
ElementPlusResolver()
],
vueTemplate: true, // 是否在 vue 模板中自动导入
dts: path.resolve(path.resolve(__dirname, '../../src'), 'types', 'auto-imports.d.ts')

View File

@ -1,4 +1,6 @@
import vue from '@vitejs/plugin-vue';
import vueDevTools from 'vite-plugin-vue-devtools';
import createUnoCss from './unocss';
import createAutoImport from './auto-import';
import createComponents from './components';
@ -11,12 +13,13 @@ import path from 'path';
export default (viteEnv: any, isBuild = false): [] => {
const vitePlugins: any = [];
vitePlugins.push(vue());
vitePlugins.push(vueDevTools());
vitePlugins.push(createUnoCss());
vitePlugins.push(createAutoImport(path));
vitePlugins.push(createComponents(path));
vitePlugins.push(createCompression(viteEnv));
vitePlugins.push(createIcons());
vitePlugins.push(createSvgIconsPlugin(path, isBuild));
vitePlugins.push(createSvgIconsPlugin(path));
vitePlugins.push(createSetupExtend());
return vitePlugins;
};

View File

@ -1,10 +1,10 @@
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons';
export default (path: any, isBuild: boolean) => {
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons-ng';
export default (path: any) => {
return createSvgIconsPlugin({
// 指定需要缓存的图标文件夹
iconDirs: [path.resolve(path.resolve(__dirname, '../../src'), 'assets/icons/svg')],
// 指定symbolId格式
symbolId: 'icon-[dir]-[name]',
svgoOptions: isBuild
symbolId: 'icon-[dir]-[name]'
});
};