!64 版本升级
* Merge branch 'dev' of gitee.com:JavaLionLi/plus-ui into ts
* 升级依赖
* !61 fix: 删除重复环境变量ElUploadInstance
* fix: 删除重复环境变量ElUploadInstance
| | |
| | | .eslintrc.js |
| | | prettier.config.js |
| | | src/assets |
| | | tailwind.config.js |
| | | tailwind.config.js |
| | |
| | | module.exports = { |
| | | env: { |
| | | browser: true, |
| | | es2021: true, |
| | | node: true |
| | | node: true, |
| | | es6: true |
| | | }, |
| | | parser: 'vue-eslint-parser', |
| | | extends: [ |
| | | 'eslint:recommended', |
| | | 'plugin:vue/vue3-essential', |
| | | 'plugin:@typescript-eslint/recommended', |
| | | 'plugin:vue/vue3-recommended', |
| | | './.eslintrc-auto-import.json', |
| | | 'plugin:prettier/recommended' |
| | | 'plugin:@typescript-eslint/recommended', |
| | | "prettier", |
| | | 'plugin:prettier/recommended', |
| | | ], |
| | | parserOptions: { |
| | | ecmaVersion: '2020', |
| | | sourceType: 'module', |
| | | project: "./tsconfig.*?.json", |
| | | parser: '@typescript-eslint/parser' |
| | | }, |
| | | plugins: ['vue', '@typescript-eslint'], |
| | | plugins: ['vue', '@typescript-eslint', 'import', 'promise', 'node', 'prettier'], |
| | | rules: { |
| | | 'vue/multi-word-component-names': 'off', |
| | | '@typescript-eslint/no-empty-function': 'off', |
| | | '@typescript-eslint/no-explicit-any': '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', |
| | | '@typescript-eslint/ban-types': [ |
| | | 'error', |
| | | { |
¶Ô±ÈÐÂÎļþ |
| | |
| | | { |
| | | "printWidth": 150, |
| | | "tabWidth": 2, |
| | | "useTabs": false, |
| | | "semi": true, |
| | | "singleQuote": true, |
| | | "quoteProps": "as-needed", |
| | | "jsxSingleQuote": false, |
| | | "bracketSameLine": false, |
| | | "trailingComma": "none", |
| | | "bracketSpacing": true, |
| | | "embeddedLanguageFormatting": "auto", |
| | | "arrowParens": "always", |
| | | "requirePragma": false, |
| | | "insertPragma": false, |
| | | "proseWrap": "preserve", |
| | | "htmlWhitespaceSensitivity": "css", |
| | | "vueIndentScriptAndStyle": false, |
| | | "endOfLine": "auto" |
| | | } |
| | |
| | | "license": "MIT", |
| | | "scripts": { |
| | | "dev": "vite serve --mode development", |
| | | "build:prod": "vite build --mode production &&vue-tsc --noEmit", |
| | | "build:prod": "vite build --mode production", |
| | | "build:dev": "vite build --mode development", |
| | | "preview": "vite preview", |
| | | "lint": "eslint src/**/*.{ts,js,vue} --fix", |
| | | "lint:eslint": "eslint --fix --ext .ts,.js,.vue ./src ", |
| | | "prepare": "husky install", |
| | | "prettier": "prettier --write ." |
| | | }, |
| | |
| | | "dependencies": { |
| | | "@element-plus/icons-vue": "2.1.0", |
| | | "@vueup/vue-quill": "1.2.0", |
| | | "@vueuse/core": "9.5.0", |
| | | "@vueuse/core": "10.7.0", |
| | | "animate.css": "4.1.1", |
| | | "await-to-js": "^3.0.0", |
| | | "axios": "^1.3.4", |
| | | "crypto-js": "^4.1.1", |
| | | "echarts": "5.4.0", |
| | | "element-plus": "2.2.27", |
| | | "element-plus": "2.4.3", |
| | | "file-saver": "2.0.5", |
| | | "fuse.js": "6.6.2", |
| | | "js-cookie": "3.0.1", |
| | | "jsencrypt": "3.3.1", |
| | | "crypto-js": "^4.1.1", |
| | | "nprogress": "0.2.0", |
| | | "path-browserify": "1.0.1", |
| | | "path-to-regexp": "6.2.0", |
| | | "pinia": "2.0.22", |
| | | "pinia": "2.1.7", |
| | | "screenfull": "6.0.0", |
| | | "vform3-builds": "3.0.8", |
| | | "vue": "3.2.45", |
| | | "vue": "3.3.11", |
| | | "vue-cropper": "1.0.3", |
| | | "vue-i18n": "9.2.2", |
| | | "vue-router": "4.1.4", |
| | | "vue-types": "^5.0.3" |
| | | "vue-router": "4.2.5", |
| | | "vue-types": "5.1.1" |
| | | }, |
| | | "devDependencies": { |
| | | "@iconify/json": "^2.2.40", |
| | |
| | | "@types/node": "18.14.2", |
| | | "@types/nprogress": "0.2.0", |
| | | "@types/path-browserify": "^1.0.0", |
| | | "@typescript-eslint/eslint-plugin": "5.56.0", |
| | | "@typescript-eslint/parser": "5.56.0", |
| | | "@unocss/preset-attributify": "^0.50.6", |
| | | "@unocss/preset-icons": "^0.50.6", |
| | | "@unocss/preset-uno": "^0.50.6", |
| | | "@vitejs/plugin-vue": "4.0.0", |
| | | "@typescript-eslint/eslint-plugin": "6.14.0", |
| | | "@typescript-eslint/parser": "6.14.0", |
| | | "@unocss/preset-attributify": "^0.58.0", |
| | | "@unocss/preset-icons": "^0.58.0", |
| | | "@unocss/preset-uno": "^0.58.0", |
| | | "@vue/compiler-sfc": "3.2.45", |
| | | "@vitejs/plugin-vue": "4.5.2", |
| | | "autoprefixer": "10.4.14", |
| | | "eslint": "8.36.0", |
| | | "eslint-config-prettier": "8.8.0", |
| | | "eslint-plugin-prettier": "4.2.1", |
| | | "eslint-plugin-vue": "9.9.0", |
| | | "eslint": "8.55.0", |
| | | "eslint-config-prettier": "9.1.0", |
| | | "eslint-define-config": "2.0.0", |
| | | "eslint-plugin-prettier": "5.0.1", |
| | | "eslint-plugin-promise": "6.1.1", |
| | | "eslint-plugin-node": "11.1.0", |
| | | "eslint-plugin-import": "2.29.0", |
| | | "eslint-plugin-vue": "9.19.2", |
| | | "fast-glob": "^3.2.11", |
| | | "husky": "7.0.4", |
| | | "postcss": "^8.4.21", |
| | | "prettier": "2.8.6", |
| | | "prettier": "3.1.1", |
| | | "sass": "1.56.1", |
| | | "typescript": "4.9.5", |
| | | "unocss": "^0.50.6", |
| | | "unplugin-auto-import": "0.13.0", |
| | | "unplugin-icons": "0.15.1", |
| | | "unplugin-vue-components": "0.23.0", |
| | | "vite": "4.3.1", |
| | | "typescript": "5.2.2", |
| | | "unocss": "^0.58.0", |
| | | "unplugin-auto-import": "0.17.2", |
| | | "unplugin-icons": "0.18.1", |
| | | "unplugin-vue-components": "0.26.0", |
| | | "unplugin-vue-setup-extend-plus": "0.4.9", |
| | | "vite-plugin-compression": "0.5.1", |
| | | "vite-plugin-svg-icons": "2.0.1", |
| | | "unplugin-vue-setup-extend-plus": "0.4.9", |
| | | "vitest": "^0.29.7", |
| | | "vue-eslint-parser": "9.1.0", |
| | | "vue-tsc": "0.35.0" |
| | | "vue-eslint-parser": "9.3.2", |
| | | "vue-tsc": "0.35.0", |
| | | "vite": "5.0.4" |
| | | } |
| | | } |
| | |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import useSettingsStore from '@/store/modules/settings' |
| | | import { handleThemeStyle } from '@/utils/theme' |
| | | import useSettingsStore from '@/store/modules/settings'; |
| | | import { handleThemeStyle } from '@/utils/theme'; |
| | | import useAppStore from '@/store/modules/app'; |
| | | |
| | | const appStore = useAppStore(); |
| | |
| | | onMounted(() => { |
| | | nextTick(() => { |
| | | // åå§å䏻颿 ·å¼ |
| | | handleThemeStyle(useSettingsStore().theme) |
| | | }) |
| | | }) |
| | | handleThemeStyle(useSettingsStore().theme); |
| | | }); |
| | | }); |
| | | </script> |
| | |
| | | }; |
| | | |
| | | // ä¿®æ¹ä»£ç çæä¿¡æ¯ |
| | | export const updateGenTable = (data: DbTableForm) => { |
| | | export const updateGenTable = (data: DbTableForm): AxiosPromise<GenTableVO> => { |
| | | return request({ |
| | | url: '/tool/gen', |
| | | method: 'put', |
| | |
| | | }; |
| | | |
| | | // 导å
¥è¡¨ |
| | | export const importTable = (data: { tables: string; dataName: string }) => { |
| | | export const importTable = (data: { tables: string; dataName: string }): AxiosPromise<GenTableVO> => { |
| | | return request({ |
| | | url: '/tool/gen/importTable', |
| | | method: 'post', |
| | |
| | | <el-breadcrumb class="app-breadcrumb" separator="/"> |
| | | <transition-group name="breadcrumb"> |
| | | <el-breadcrumb-item v-for="(item, index) in levelList" :key="item.path"> |
| | | <span v-if="item.redirect === 'noRedirect' || index == levelList.length - 1" class="no-redirect">{{ |
| | | item.meta?.title }}</span> |
| | | <span v-if="item.redirect === 'noRedirect' || index == levelList.length - 1" class="no-redirect">{{ item.meta?.title }}</span> |
| | | <a v-else @click.prevent="handleLink(item)">{{ item.meta?.title }}</a> |
| | | </el-breadcrumb-item> |
| | | </transition-group> |
| | |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import { RouteLocationMatched } from 'vue-router' |
| | | import { RouteLocationMatched } from 'vue-router'; |
| | | |
| | | const route = useRoute(); |
| | | const router = useRouter(); |
| | | const levelList = ref<RouteLocationMatched[]>([]) |
| | | const levelList = ref<RouteLocationMatched[]>([]); |
| | | |
| | | const getBreadcrumb = () => { |
| | | // only show routes with meta.title |
| | | let matched = route.matched.filter(item => item.meta && item.meta.title); |
| | | const first = matched[0] |
| | | let matched = route.matched.filter((item) => item.meta && item.meta.title); |
| | | const first = matched[0]; |
| | | // 夿æ¯å¦ä¸ºé¦é¡µ |
| | | if (!isDashboard(first)) { |
| | | matched = ([{ path: '/index', meta: { title: 'é¦é¡µ' } }] as any).concat(matched) |
| | | matched = ([{ path: '/index', meta: { title: 'é¦é¡µ' } }] as any).concat(matched); |
| | | } |
| | | levelList.value = matched.filter(item => item.meta && item.meta.title && item.meta.breadcrumb !== false) |
| | | } |
| | | levelList.value = matched.filter((item) => item.meta && item.meta.title && item.meta.breadcrumb !== false); |
| | | }; |
| | | const isDashboard = (route: RouteLocationMatched) => { |
| | | const name = route && route.name as string |
| | | const name = route && (route.name as string); |
| | | if (!name) { |
| | | return false |
| | | return false; |
| | | } |
| | | return name.trim() === 'Index' |
| | | } |
| | | return name.trim() === 'Index'; |
| | | }; |
| | | const handleLink = (item: RouteLocationMatched) => { |
| | | const { redirect, path } = item |
| | | redirect ? router.push(redirect as string) : router.push(path) |
| | | } |
| | | const { redirect, path } = item; |
| | | redirect ? router.push(redirect as string) : router.push(path); |
| | | }; |
| | | |
| | | watchEffect(() => { |
| | | // if you go to the redirect page, do not update the breadcrumbs |
| | | if (route.path.startsWith('/redirect/')) return |
| | | getBreadcrumb() |
| | | }) |
| | | if (route.path.startsWith('/redirect/')) return; |
| | | getBreadcrumb(); |
| | | }); |
| | | onMounted(() => { |
| | | getBreadcrumb(); |
| | | }) |
| | | }); |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | |
| | | <!-- ä»£ç æå»º --> |
| | | <script setup lang="ts"> |
| | | |
| | | const props = defineProps({ |
| | | showBtn: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | formJson: { |
| | | type: Object, |
| | | default: undefined |
| | | } |
| | | }) |
| | | const { proxy } = getCurrentInstance() as ComponentInternalInstance; |
| | | const buildRef = ref(); |
| | | const emits = defineEmits(['reJson', 'saveDesign']); |
| | | |
| | | |
| | | |
| | | //è·å表åjson |
| | | const getJson = () => { |
| | | const formJson = JSON.stringify(buildRef.value.getFormJson()) |
| | | const fieldJson = JSON.stringify(buildRef.value.getFieldWidgets()) |
| | | let data = { |
| | | formJson, fieldJson |
| | | } |
| | | emits("saveDesign", data) |
| | | } |
| | | |
| | | onMounted(() => { |
| | | if (props.formJson) { |
| | | buildRef.value.setFormJson(props.formJson) |
| | | } |
| | | }) |
| | | </script> |
| | | |
| | | <template> |
| | | <!-- ä»£ç æå»º --> |
| | | <div> |
| | | <v-form-designer |
| | | class="build" |
| | | ref="buildRef" |
| | | class="build" |
| | | :designer-config="{ importJsonButton: true, exportJsonButton: true, exportCodeButton: true, generateSFCButton: true, formTemplates: true }" |
| | | > |
| | | <template #customToolButtons v-if="showBtn"> |
| | | <template v-if="showBtn" #customToolButtons> |
| | | <el-button link type="primary" icon="Select" @click="getJson">ä¿å</el-button> |
| | | </template> |
| | | </v-form-designer> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | interface Props { |
| | | showBtn: boolean; |
| | | formJson: any; |
| | | } |
| | | |
| | | const props = withDefaults(defineProps<Props>(), { |
| | | showBtn: true, |
| | | formJson: '' |
| | | }); |
| | | |
| | | const buildRef = ref(); |
| | | const emits = defineEmits(['reJson', 'saveDesign']); |
| | | |
| | | //è·å表åjson |
| | | const getJson = () => { |
| | | const formJson = JSON.stringify(buildRef.value.getFormJson()); |
| | | const fieldJson = JSON.stringify(buildRef.value.getFieldWidgets()); |
| | | let data = { |
| | | formJson, |
| | | fieldJson |
| | | }; |
| | | emits('saveDesign', data); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | if (props.formJson) { |
| | | buildRef.value.setFormJson(props.formJson); |
| | | } |
| | | }); |
| | | </script> |
| | | |
| | | <style lang="scss"> |
| | | .build { |
| | | margin: 0 !important; |
| | |
| | | <template> |
| | | <div class=""> |
| | | <v-form-render ref="vFormRef" :form-json="formJson" :form-data="formData" /> |
| | | </div> |
| | | </template> |
| | | |
| | | <!-- å¨æè¡¨åæ¸²æ --> |
| | | <script setup name="Render"> |
| | | <script setup name="Render" lang="ts"> |
| | | interface Props { |
| | | formJson: string | object; |
| | | formData: string | object; |
| | | isView: boolean; |
| | | } |
| | | |
| | | const props = defineProps({ |
| | | formJson: { |
| | | type: [String, Object], |
| | | default: "" |
| | | }, |
| | | formData: { |
| | | type: [String, Object], |
| | | default: "" |
| | | }, |
| | | isView: { |
| | | type: Boolean, |
| | | default: false |
| | | } |
| | | }) |
| | | const props = withDefaults(defineProps<Props>(), { |
| | | formJson: '', |
| | | formData: '', |
| | | isView: false |
| | | }); |
| | | |
| | | const vFormRef = ref(null) |
| | | const vFormRef = ref(null); |
| | | // è·åè¡¨åæ°æ®-弿¥ |
| | | const getFormData = () => { |
| | | return vFormRef.value.getFormData() |
| | | } |
| | | return vFormRef.value.getFormData(); |
| | | }; |
| | | |
| | | /** |
| | | * 设置表åå
容 |
| | |
| | | * formConfigï¼{ formTemplateï¼è¡¨å模æ¿ï¼formDataï¼è¡¨åæ°æ®ï¼hiddenFieldï¼éè¦éèçåæ®µå符串éåï¼disabledFieldï¼éè¦ç¦ç¨çèªè¯»å符串éå} |
| | | */ |
| | | const initForm = (formConf) => { |
| | | const { formTemplate, formData, hiddenField, disabledField } = toRaw(formConf) |
| | | const { formTemplate, formData, hiddenField, disabledField } = toRaw(formConf); |
| | | if (formTemplate) { |
| | | vFormRef.value.setFormJson(formTemplate) |
| | | vFormRef.value.setFormJson(formTemplate); |
| | | if (formData) { |
| | | vFormRef.value.setFormData(formData) |
| | | vFormRef.value.setFormData(formData); |
| | | } |
| | | if (disabledField && disabledField.length > 0) { |
| | | setTimeout(() => { |
| | | vFormRef.value.disableWidgets(disabledField) |
| | | }, 200) |
| | | vFormRef.value.disableWidgets(disabledField); |
| | | }, 200); |
| | | } |
| | | if (hiddenField && hiddenField.length > 0) { |
| | | setTimeout(() => { |
| | | vFormRef.value.hideWidgets(hiddenField) |
| | | }, 200) |
| | | vFormRef.value.hideWidgets(hiddenField); |
| | | }, 200); |
| | | } |
| | | if (props.isView) { |
| | | console.log(props.isView) |
| | | setTimeout(() => { |
| | | vFormRef.value.disableForm() |
| | | }, 100) |
| | | vFormRef.value.disableForm(); |
| | | }, 100); |
| | | } |
| | | } |
| | | } |
| | | defineExpose({ getFormData, initForm }) |
| | | }; |
| | | defineExpose({ getFormData, initForm }); |
| | | </script> |
| | | |
| | | <template> |
| | | <div class=""> |
| | | <v-form-render ref="vFormRef" :form-json="formJson" :form-data="formData" /> |
| | | </div> |
| | | </template> |
| | |
| | | </span> |
| | | <el-tag |
| | | v-else |
| | | :disable-transitions="true" |
| | | :key="item.value + ''" |
| | | :disable-transitions="true" |
| | | :index="index" |
| | | :type="(item.elTagType === 'primary' || item.elTagType === 'default')? '' : item.elTagType" |
| | | :class="item.elTagClass" |
| | | > |
| | | {{ item.label + " " }} |
| | | {{ item.label + ' ' }} |
| | | </el-tag> |
| | | </template> |
| | | </template> |
| | |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import { propTypes } from '@/utils/propTypes'; |
| | | |
| | | |
| | | const props = defineProps({ |
| | | // æ°æ® |
| | | options: { |
| | | type: Array as PropType<DictDataOption[]>, |
| | | default: null, |
| | | }, |
| | | // å½åçå¼ |
| | | value: [Number, String, Array] as PropType<number | string | Array<number | string>>, |
| | | // 彿ªæ¾å°å¹é
çæ°æ®æ¶ï¼æ¾ç¤ºvalue |
| | | showValue: propTypes.bool.def(true), |
| | | separator: propTypes.string.def(","), |
| | | interface Props { |
| | | options: Array<DictDataOption>; |
| | | value: number | string | Array<number | string>; |
| | | showValue: boolean; |
| | | separator: string; |
| | | } |
| | | const props = withDefaults(defineProps<Props>(), { |
| | | showValue: true, |
| | | separator: ',' |
| | | }); |
| | | |
| | | const values = computed(() => { |
| | | if (props.value === '' || props.value === null || typeof props.value === "undefined") return [] |
| | | return Array.isArray(props.value) ? props.value.map(item => '' + item) : String(props.value).split(props.separator); |
| | | if (props.value === '' || props.value === null || typeof props.value === 'undefined') return []; |
| | | return Array.isArray(props.value) ? props.value.map((item) => '' + item) : String(props.value).split(props.separator); |
| | | }); |
| | | |
| | | const unmatch = computed(() => { |
| | | if (props.options?.length == 0 || props.value === '' || props.value === null || typeof props.value === "undefined") return false |
| | | if (props.options?.length == 0 || props.value === '' || props.value === null || typeof props.value === 'undefined') return false; |
| | | // ä¼ å
¥å¼ä¸ºéæ°ç» |
| | | values.value.forEach(item => { |
| | | if (!props.options.some(v => v.value === item)) { |
| | | return true // å¦æææªå¹é
项ï¼å°æ å¿è®¾ç½®ä¸ºtrue |
| | | values.value.forEach((item) => { |
| | | if (!props.options.some((v) => v.value === item)) { |
| | | return true; // å¦æææªå¹é
项ï¼å°æ å¿è®¾ç½®ä¸ºtrue |
| | | } |
| | | }) |
| | | return false // è¿åæ å¿çå¼ |
| | | }); |
| | | return false; // è¿åæ å¿çå¼ |
| | | }); |
| | | |
| | | const unmatchArray = computed(() => { |
| | | // è®°å½æªå¹é
ç项 |
| | | // è®°å½æªå¹é
ç项 |
| | | const itemUnmatchArray: Array<string | number> = []; |
| | | if (props.value !== '' && props.value !== null && typeof props.value !== "undefined") { |
| | | values.value.forEach(item => { |
| | | if (!props.options.some(v => v.value === item)) { |
| | | if (props.value !== '' && props.value !== null && typeof props.value !== 'undefined') { |
| | | values.value.forEach((item) => { |
| | | if (!props.options.some((v) => v.value === item)) { |
| | | itemUnmatchArray.push(item); |
| | | } |
| | | }) |
| | | }); |
| | | } |
| | | // 没ævalue䏿¾ç¤º |
| | | return handleArray(itemUnmatchArray); |
| | | }); |
| | | |
| | | const handleArray = (array: Array<string | number>) => { |
| | | if (array.length === 0) return ""; |
| | | if (array.length === 0) return ''; |
| | | return array.reduce((pre, cur) => { |
| | | return pre + " " + cur; |
| | | return pre + ' ' + cur; |
| | | }); |
| | | } |
| | | }; |
| | | </script> |
| | | |
| | | <style scoped> |
| | |
| | | <template> |
| | | <div> |
| | | <el-upload |
| | | v-if="type === 'url'" |
| | | ref="uploadRef" |
| | | :action="upload.url" |
| | | :before-upload="handleBeforeUpload" |
| | | :on-success="handleUploadSuccess" |
| | |
| | | name="file" |
| | | :show-file-list="false" |
| | | :headers="upload.headers" |
| | | ref="uploadRef" |
| | | v-if="type === 'url'" |
| | | > |
| | | </el-upload> |
| | | <div class="editor"> |
| | | <quill-editor |
| | | ref="quillEditorRef" |
| | | v-model:content="content" |
| | | contentType="html" |
| | | @textChange="(e: any) => $emit('update:modelValue', content)" |
| | | content-type="html" |
| | | :options="options" |
| | | :style="styles" |
| | | @text-change="(e: any) => $emit('update:modelValue', content)" |
| | | /> |
| | | </div> |
| | | </div> |
| | |
| | | import { QuillEditor, Quill } from '@vueup/vue-quill'; |
| | | import '@vueup/vue-quill/dist/vue-quill.snow.css'; |
| | | import { propTypes } from '@/utils/propTypes'; |
| | | import { globalHeaders } from "@/utils/request"; |
| | | import { globalHeaders } from '@/utils/request'; |
| | | |
| | | const props = defineProps({ |
| | | /* ç¼è¾å¨çå
容 */ |
| | |
| | | const upload = reactive<UploadOption>({ |
| | | headers: globalHeaders(), |
| | | url: import.meta.env.VITE_APP_BASE_API + '/resource/oss/upload' |
| | | }) |
| | | }); |
| | | const quillEditorRef = ref(); |
| | | |
| | | const options = ref({ |
| | | theme: "snow", |
| | | theme: 'snow', |
| | | bounds: document.body, |
| | | debug: "warn", |
| | | debug: 'warn', |
| | | modules: { |
| | | // å·¥å
·æ é
ç½® |
| | | toolbar: { |
| | | container: [ |
| | | ["bold", "italic", "underline", "strike"], // å ç² æä½ ä¸å线 å é¤çº¿ |
| | | ["blockquote", "code-block"], // å¼ç¨ 代ç å |
| | | [{ list: "ordered" }, { list: "bullet" }], // æåºãæ åºå表 |
| | | [{ indent: "-1" }, { indent: "+1" }], // ç¼©è¿ |
| | | [{ size: ["small", false, "large", "huge"] }], // åä½å¤§å° |
| | | [{ header: [1, 2, 3, 4, 5, 6, false] }], // æ é¢ |
| | | [{ color: [] }, { background: [] }], // åä½é¢è²ãåä½èæ¯é¢è² |
| | | [{ align: [] }], // 坹齿¹å¼ |
| | | ["clean"], // æ¸
é¤ææ¬æ ¼å¼ |
| | | ["link", "image", "video"] // 龿¥ãå¾çãè§é¢ |
| | | ['bold', 'italic', 'underline', 'strike'], // å ç² æä½ ä¸å线 å é¤çº¿ |
| | | ['blockquote', 'code-block'], // å¼ç¨ 代ç å |
| | | [{ list: 'ordered' }, { list: 'bullet' }], // æåºãæ åºå表 |
| | | [{ indent: '-1' }, { indent: '+1' }], // ç¼©è¿ |
| | | [{ size: ['small', false, 'large', 'huge'] }], // åä½å¤§å° |
| | | [{ header: [1, 2, 3, 4, 5, 6, false] }], // æ é¢ |
| | | [{ color: [] }, { background: [] }], // åä½é¢è²ãåä½èæ¯é¢è² |
| | | [{ align: [] }], // 坹齿¹å¼ |
| | | ['clean'], // æ¸
é¤ææ¬æ ¼å¼ |
| | | ['link', 'image', 'video'] // 龿¥ãå¾çãè§é¢ |
| | | ], |
| | | handlers: { |
| | | image: function (value: any) { |
| | | if (value) { |
| | | // è°ç¨elementå¾çä¸ä¼ |
| | | (document.querySelector(".editor-img-uploader>.el-upload") as HTMLDivElement)?.click(); |
| | | (document.querySelector('.editor-img-uploader>.el-upload') as HTMLDivElement)?.click(); |
| | | } else { |
| | | Quill.format("image", true); |
| | | Quill.format('image', true); |
| | | } |
| | | }, |
| | | }, |
| | | } |
| | | } |
| | | } |
| | | }, |
| | | placeholder: "请è¾å
¥å
容", |
| | | readOnly: props.readOnly, |
| | | placeholder: '请è¾å
¥å
容', |
| | | readOnly: props.readOnly |
| | | }); |
| | | |
| | | const styles = computed(() => { |
| | |
| | | style.height = `${props.height}px`; |
| | | } |
| | | return style; |
| | | }) |
| | | }); |
| | | |
| | | const content = ref(""); |
| | | watch(() => props.modelValue, (v) => { |
| | | if (v !== content.value) { |
| | | content.value = v === undefined ? "<p></p>" : v; |
| | | } |
| | | }, { immediate: true }); |
| | | const content = ref(''); |
| | | watch( |
| | | () => props.modelValue, |
| | | (v) => { |
| | | if (v !== content.value) { |
| | | content.value = v === undefined ? '<p></p>' : v; |
| | | } |
| | | }, |
| | | { immediate: true } |
| | | ); |
| | | |
| | | // å¾çä¸ä¼ æåè¿åå¾çå°å |
| | | const handleUploadSuccess = (res: any) => { |
| | |
| | | // è·åå
æ ä½ç½® |
| | | let length = quill.selection.savedRange.index; |
| | | // æå
¥å¾çï¼res为æå¡å¨è¿åçå¾ç龿¥å°å |
| | | quill.insertEmbed(length, "image", res.data.url); |
| | | quill.insertEmbed(length, 'image', res.data.url); |
| | | // è°æ´å
æ å°æå |
| | | quill.setSelection(length + 1); |
| | | proxy?.$modal.closeLoading(); |
| | |
| | | proxy?.$modal.loading(res.msg); |
| | | proxy?.$modal.closeLoading(); |
| | | } |
| | | } |
| | | }; |
| | | |
| | | // å¾çä¸ä¼ åæ¦æª |
| | | const handleBeforeUpload = (file: any) => { |
| | | const type = ["image/jpeg", "image/jpg", "image/png", "image/svg"]; |
| | | const type = ['image/jpeg', 'image/jpg', 'image/png', 'image/svg']; |
| | | const isJPG = type.includes(file.type); |
| | | //æ£éªæä»¶æ ¼å¼ |
| | | if (!isJPG) { |
| | |
| | | } |
| | | proxy?.$modal.loading('æ£å¨ä¸ä¼ æä»¶ï¼è¯·ç¨å...'); |
| | | return true; |
| | | } |
| | | }; |
| | | |
| | | // å¾çå¤±è´¥æ¦æª |
| | | const handleUploadError = (err: any) => { |
| | | console.error(err); |
| | | proxy?.$modal.msgError('ä¸ä¼ æä»¶å¤±è´¥'); |
| | | } |
| | | }; |
| | | </script> |
| | | |
| | | <style> |
| | |
| | | .quill-img { |
| | | display: none; |
| | | } |
| | | .ql-snow .ql-tooltip[data-mode="link"]::before { |
| | | content: "请è¾å
¥é¾æ¥å°å:"; |
| | | .ql-snow .ql-tooltip[data-mode='link']::before { |
| | | content: '请è¾å
¥é¾æ¥å°å:'; |
| | | } |
| | | .ql-snow .ql-tooltip.ql-editing a.ql-action::after { |
| | | border-right: 0; |
| | | content: "ä¿å"; |
| | | content: 'ä¿å'; |
| | | padding-right: 0; |
| | | } |
| | | .ql-snow .ql-tooltip[data-mode="video"]::before { |
| | | content: "请è¾å
¥è§é¢å°å:"; |
| | | .ql-snow .ql-tooltip[data-mode='video']::before { |
| | | content: '请è¾å
¥è§é¢å°å:'; |
| | | } |
| | | .ql-snow .ql-picker.ql-size .ql-picker-label::before, |
| | | .ql-snow .ql-picker.ql-size .ql-picker-item::before { |
| | | content: "14px"; |
| | | content: '14px'; |
| | | } |
| | | .ql-snow .ql-picker.ql-size .ql-picker-label[data-value="small"]::before, |
| | | .ql-snow .ql-picker.ql-size .ql-picker-item[data-value="small"]::before { |
| | | content: "10px"; |
| | | .ql-snow .ql-picker.ql-size .ql-picker-label[data-value='small']::before, |
| | | .ql-snow .ql-picker.ql-size .ql-picker-item[data-value='small']::before { |
| | | content: '10px'; |
| | | } |
| | | .ql-snow .ql-picker.ql-size .ql-picker-label[data-value="large"]::before, |
| | | .ql-snow .ql-picker.ql-size .ql-picker-item[data-value="large"]::before { |
| | | content: "18px"; |
| | | .ql-snow .ql-picker.ql-size .ql-picker-label[data-value='large']::before, |
| | | .ql-snow .ql-picker.ql-size .ql-picker-item[data-value='large']::before { |
| | | content: '18px'; |
| | | } |
| | | .ql-snow .ql-picker.ql-size .ql-picker-label[data-value="huge"]::before, |
| | | .ql-snow .ql-picker.ql-size .ql-picker-item[data-value="huge"]::before { |
| | | content: "32px"; |
| | | .ql-snow .ql-picker.ql-size .ql-picker-label[data-value='huge']::before, |
| | | .ql-snow .ql-picker.ql-size .ql-picker-item[data-value='huge']::before { |
| | | content: '32px'; |
| | | } |
| | | .ql-snow .ql-picker.ql-header .ql-picker-label::before, |
| | | .ql-snow .ql-picker.ql-header .ql-picker-item::before { |
| | | content: "ææ¬"; |
| | | content: 'ææ¬'; |
| | | } |
| | | .ql-snow .ql-picker.ql-header .ql-picker-label[data-value="1"]::before, |
| | | .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="1"]::before { |
| | | content: "æ é¢1"; |
| | | .ql-snow .ql-picker.ql-header .ql-picker-label[data-value='1']::before, |
| | | .ql-snow .ql-picker.ql-header .ql-picker-item[data-value='1']::before { |
| | | content: 'æ é¢1'; |
| | | } |
| | | .ql-snow .ql-picker.ql-header .ql-picker-label[data-value="2"]::before, |
| | | .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="2"]::before { |
| | | content: "æ é¢2"; |
| | | .ql-snow .ql-picker.ql-header .ql-picker-label[data-value='2']::before, |
| | | .ql-snow .ql-picker.ql-header .ql-picker-item[data-value='2']::before { |
| | | content: 'æ é¢2'; |
| | | } |
| | | .ql-snow .ql-picker.ql-header .ql-picker-label[data-value="3"]::before, |
| | | .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="3"]::before { |
| | | content: "æ é¢3"; |
| | | .ql-snow .ql-picker.ql-header .ql-picker-label[data-value='3']::before, |
| | | .ql-snow .ql-picker.ql-header .ql-picker-item[data-value='3']::before { |
| | | content: 'æ é¢3'; |
| | | } |
| | | .ql-snow .ql-picker.ql-header .ql-picker-label[data-value="4"]::before, |
| | | .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="4"]::before { |
| | | content: "æ é¢4"; |
| | | .ql-snow .ql-picker.ql-header .ql-picker-label[data-value='4']::before, |
| | | .ql-snow .ql-picker.ql-header .ql-picker-item[data-value='4']::before { |
| | | content: 'æ é¢4'; |
| | | } |
| | | .ql-snow .ql-picker.ql-header .ql-picker-label[data-value="5"]::before, |
| | | .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="5"]::before { |
| | | content: "æ é¢5"; |
| | | .ql-snow .ql-picker.ql-header .ql-picker-label[data-value='5']::before, |
| | | .ql-snow .ql-picker.ql-header .ql-picker-item[data-value='5']::before { |
| | | content: 'æ é¢5'; |
| | | } |
| | | .ql-snow .ql-picker.ql-header .ql-picker-label[data-value="6"]::before, |
| | | .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="6"]::before { |
| | | content: "æ é¢6"; |
| | | .ql-snow .ql-picker.ql-header .ql-picker-label[data-value='6']::before, |
| | | .ql-snow .ql-picker.ql-header .ql-picker-item[data-value='6']::before { |
| | | content: 'æ é¢6'; |
| | | } |
| | | .ql-snow .ql-picker.ql-font .ql-picker-label::before, |
| | | .ql-snow .ql-picker.ql-font .ql-picker-item::before { |
| | | content: "æ ååä½"; |
| | | content: 'æ ååä½'; |
| | | } |
| | | .ql-snow .ql-picker.ql-font .ql-picker-label[data-value="serif"]::before, |
| | | .ql-snow .ql-picker.ql-font .ql-picker-item[data-value="serif"]::before { |
| | | content: "衬线åä½"; |
| | | .ql-snow .ql-picker.ql-font .ql-picker-label[data-value='serif']::before, |
| | | .ql-snow .ql-picker.ql-font .ql-picker-item[data-value='serif']::before { |
| | | content: '衬线åä½'; |
| | | } |
| | | .ql-snow .ql-picker.ql-font .ql-picker-label[data-value="monospace"]::before, |
| | | .ql-snow .ql-picker.ql-font .ql-picker-item[data-value="monospace"]::before { |
| | | content: "ç宽åä½"; |
| | | .ql-snow .ql-picker.ql-font .ql-picker-label[data-value='monospace']::before, |
| | | .ql-snow .ql-picker.ql-font .ql-picker-item[data-value='monospace']::before { |
| | | content: 'ç宽åä½'; |
| | | } |
| | | </style> |
| | |
| | | <template> |
| | | <div class="upload-file"> |
| | | <el-upload |
| | | ref="fileUploadRef" |
| | | multiple |
| | | :action="uploadFileUrl" |
| | | :before-upload="handleBeforeUpload" |
| | |
| | | :show-file-list="false" |
| | | :headers="headers" |
| | | class="upload-file-uploader" |
| | | ref="fileUploadRef" |
| | | > |
| | | <!-- ä¸ä¼ æé® --> |
| | | <el-button type="primary">éåæä»¶</el-button> |
| | | </el-upload> |
| | | <!-- ä¸ä¼ æç¤º --> |
| | | <div class="el-upload__tip" v-if="showTip"> |
| | | <div v-if="showTip" class="el-upload__tip"> |
| | | 请ä¸ä¼ |
| | | <template v-if="fileSize"> |
| | | 大å°ä¸è¶
è¿ <b style="color: #f56c6c">{{ fileSize }}MB</b> |
| | | </template> |
| | | <template v-if="fileType"> |
| | | æ ¼å¼ä¸º <b style="color: #f56c6c">{{ fileType.join("/") }}</b> |
| | | æ ¼å¼ä¸º <b style="color: #f56c6c">{{ fileType.join('/') }}</b> |
| | | </template> |
| | | çæä»¶ |
| | | </div> |
| | | <!-- æä»¶å表 --> |
| | | <transition-group class="upload-file-list el-upload-list el-upload-list--text" name="el-fade-in-linear" tag="ul"> |
| | | <li :key="file.uid" class="el-upload-list__item ele-upload-list__item-content" v-for="(file, index) in fileList"> |
| | | <li v-for="(file, index) in fileList" :key="file.uid" class="el-upload-list__item ele-upload-list__item-content"> |
| | | <el-link :href="`${file.url}`" :underline="false" target="_blank"> |
| | | <span class="el-icon-document"> {{ getFileName(file.name) }} </span> |
| | | </el-link> |
| | | <div class="ele-upload-list__item-content-action"> |
| | | <el-link :underline="false" @click="handleDelete(index)" type="danger">å é¤</el-link> |
| | | <el-link :underline="false" type="danger" @click="handleDelete(index)">å é¤</el-link> |
| | | </div> |
| | | </li> |
| | | </transition-group> |
| | |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import { listByIds, delOss } from "@/api/system/oss"; |
| | | import { listByIds, delOss } from '@/api/system/oss'; |
| | | import { propTypes } from '@/utils/propTypes'; |
| | | import { globalHeaders } from "@/utils/request"; |
| | | import { globalHeaders } from '@/utils/request'; |
| | | |
| | | const props = defineProps({ |
| | | modelValue: [String, Object, Array], |
| | | // æ°ééå¶ |
| | | limit: propTypes.number.def(5), |
| | | // 大å°éå¶(MB) |
| | | fileSize: propTypes.number.def(5), |
| | | // æä»¶ç±»å, ä¾å¦['png', 'jpg', 'jpeg'] |
| | | fileType: propTypes.array.def(["doc", "xls", "ppt", "txt", "pdf"]), |
| | | // æ¯å¦æ¾ç¤ºæç¤º |
| | | isShowTip: propTypes.bool.def(true), |
| | | modelValue: [String, Object, Array], |
| | | // æ°ééå¶ |
| | | limit: propTypes.number.def(5), |
| | | // 大å°éå¶(MB) |
| | | fileSize: propTypes.number.def(5), |
| | | // æä»¶ç±»å, ä¾å¦['png', 'jpg', 'jpeg'] |
| | | fileType: propTypes.array.def(['doc', 'xls', 'ppt', 'txt', 'pdf']), |
| | | // æ¯å¦æ¾ç¤ºæç¤º |
| | | isShowTip: propTypes.bool.def(true) |
| | | }); |
| | | |
| | | const { proxy } = getCurrentInstance() as ComponentInternalInstance; |
| | |
| | | const uploadList = ref<any[]>([]); |
| | | |
| | | const baseUrl = import.meta.env.VITE_APP_BASE_API; |
| | | const uploadFileUrl = ref(baseUrl + "/resource/oss/upload"); // ä¸ä¼ æä»¶æå¡å¨å°å |
| | | const uploadFileUrl = ref(baseUrl + '/resource/oss/upload'); // ä¸ä¼ æä»¶æå¡å¨å°å |
| | | const headers = ref(globalHeaders()); |
| | | |
| | | const fileList = ref<any[]>([]); |
| | | const showTip = computed( |
| | | () => props.isShowTip && (props.fileType || props.fileSize) |
| | | ); |
| | | const showTip = computed(() => props.isShowTip && (props.fileType || props.fileSize)); |
| | | |
| | | const fileUploadRef = ref<ElUploadInstance>(); |
| | | |
| | | watch(() => props.modelValue, async val => { |
| | | watch( |
| | | () => props.modelValue, |
| | | async (val) => { |
| | | if (val) { |
| | | let temp = 1; |
| | | // é¦å
å°å¼è½¬ä¸ºæ°ç» |
| | | let list = []; |
| | | if (Array.isArray(val)) { |
| | | list = val; |
| | | } else { |
| | | const res = await listByIds(val as string) |
| | | list = res.data.map((oss) => { |
| | | const data = { name: oss.originalName, url: oss.url, ossId: oss.ossId }; |
| | | return data; |
| | | }); |
| | | } |
| | | // ç¶åå°æ°ç»è½¬ä¸ºå¯¹è±¡æ°ç» |
| | | fileList.value = list.map(item => { |
| | | item = { name: item.name, url: item.url, ossId: item.ossId }; |
| | | item.uid = item.uid || new Date().getTime() + temp++; |
| | | return item; |
| | | let temp = 1; |
| | | // é¦å
å°å¼è½¬ä¸ºæ°ç» |
| | | let list = []; |
| | | if (Array.isArray(val)) { |
| | | list = val; |
| | | } else { |
| | | const res = await listByIds(val as string); |
| | | list = res.data.map((oss) => { |
| | | const data = { |
| | | name: oss.originalName, |
| | | url: oss.url, |
| | | ossId: oss.ossId |
| | | }; |
| | | return data; |
| | | }); |
| | | } |
| | | // ç¶åå°æ°ç»è½¬ä¸ºå¯¹è±¡æ°ç» |
| | | fileList.value = list.map((item) => { |
| | | item = { name: item.name, url: item.url, ossId: item.ossId }; |
| | | item.uid = item.uid || new Date().getTime() + temp++; |
| | | return item; |
| | | }); |
| | | } else { |
| | | fileList.value = []; |
| | | return []; |
| | | fileList.value = []; |
| | | return []; |
| | | } |
| | | }, { deep: true, immediate: true }); |
| | | }, |
| | | { deep: true, immediate: true } |
| | | ); |
| | | |
| | | // ä¸ä¼ åæ ¡æ£æ ¼å¼åå¤§å° |
| | | const handleBeforeUpload = (file: any) => { |
| | | // æ ¡æ£æä»¶ç±»å |
| | | if (props.fileType.length) { |
| | | const fileName = file.name.split('.'); |
| | | const fileExt = fileName[fileName.length - 1]; |
| | | const isTypeOk = props.fileType.indexOf(fileExt) >= 0; |
| | | if (!isTypeOk) { |
| | | proxy?.$modal.msgError(`æä»¶æ ¼å¼ä¸æ£ç¡®, 请ä¸ä¼ ${props.fileType.join("/")}æ ¼å¼æä»¶!`); |
| | | return false; |
| | | } |
| | | // æ ¡æ£æä»¶ç±»å |
| | | if (props.fileType.length) { |
| | | const fileName = file.name.split('.'); |
| | | const fileExt = fileName[fileName.length - 1]; |
| | | const isTypeOk = props.fileType.indexOf(fileExt) >= 0; |
| | | if (!isTypeOk) { |
| | | proxy?.$modal.msgError(`æä»¶æ ¼å¼ä¸æ£ç¡®, 请ä¸ä¼ ${props.fileType.join('/')}æ ¼å¼æä»¶!`); |
| | | return false; |
| | | } |
| | | // æ ¡æ£æä»¶å¤§å° |
| | | if (props.fileSize) { |
| | | const isLt = file.size / 1024 / 1024 < props.fileSize; |
| | | if (!isLt) { |
| | | proxy?.$modal.msgError(`ä¸ä¼ æä»¶å¤§å°ä¸è½è¶
è¿ ${props.fileSize} MB!`); |
| | | return false; |
| | | } |
| | | } |
| | | // æ ¡æ£æä»¶å¤§å° |
| | | if (props.fileSize) { |
| | | const isLt = file.size / 1024 / 1024 < props.fileSize; |
| | | if (!isLt) { |
| | | proxy?.$modal.msgError(`ä¸ä¼ æä»¶å¤§å°ä¸è½è¶
è¿ ${props.fileSize} MB!`); |
| | | return false; |
| | | } |
| | | proxy?.$modal.loading("æ£å¨ä¸ä¼ æä»¶ï¼è¯·ç¨å..."); |
| | | number.value++; |
| | | return true; |
| | | } |
| | | } |
| | | proxy?.$modal.loading('æ£å¨ä¸ä¼ æä»¶ï¼è¯·ç¨å...'); |
| | | number.value++; |
| | | return true; |
| | | }; |
| | | |
| | | // æä»¶ä¸ªæ°è¶
åº |
| | | const handleExceed = () => { |
| | | proxy?.$modal.msgError(`ä¸ä¼ æä»¶æ°éä¸è½è¶
è¿ ${props.limit} 个!`); |
| | | } |
| | | proxy?.$modal.msgError(`ä¸ä¼ æä»¶æ°éä¸è½è¶
è¿ ${props.limit} 个!`); |
| | | }; |
| | | |
| | | // ä¸ä¼ 失败 |
| | | const handleUploadError = () => { |
| | | proxy?.$modal.msgError("ä¸ä¼ æä»¶å¤±è´¥"); |
| | | } |
| | | proxy?.$modal.msgError('ä¸ä¼ æä»¶å¤±è´¥'); |
| | | }; |
| | | |
| | | // ä¸ä¼ æååè° |
| | | const handleUploadSuccess = (res: any, file: UploadFile) => { |
| | | if (res.code === 200) { |
| | | uploadList.value.push({ name: res.data.fileName, url: res.data.url, ossId: res.data.ossId }); |
| | | uploadedSuccessfully(); |
| | | } else { |
| | | number.value--; |
| | | proxy?.$modal.closeLoading(); |
| | | proxy?.$modal.msgError(res.msg); |
| | | fileUploadRef.value?.handleRemove(file); |
| | | uploadedSuccessfully(); |
| | | } |
| | | } |
| | | if (res.code === 200) { |
| | | uploadList.value.push({ |
| | | name: res.data.fileName, |
| | | url: res.data.url, |
| | | ossId: res.data.ossId |
| | | }); |
| | | uploadedSuccessfully(); |
| | | } else { |
| | | number.value--; |
| | | proxy?.$modal.closeLoading(); |
| | | proxy?.$modal.msgError(res.msg); |
| | | fileUploadRef.value?.handleRemove(file); |
| | | uploadedSuccessfully(); |
| | | } |
| | | }; |
| | | |
| | | // å 餿件 |
| | | const handleDelete = (index: number) => { |
| | | let ossId = fileList.value[index].ossId; |
| | | delOss(ossId); |
| | | fileList.value.splice(index, 1); |
| | | emit("update:modelValue", listToString(fileList.value)); |
| | | } |
| | | let ossId = fileList.value[index].ossId; |
| | | delOss(ossId); |
| | | fileList.value.splice(index, 1); |
| | | emit('update:modelValue', listToString(fileList.value)); |
| | | }; |
| | | |
| | | // ä¸ä¼ ç»æå¤ç |
| | | const uploadedSuccessfully = () => { |
| | | if (number.value > 0 && uploadList.value.length === number.value) { |
| | | fileList.value = fileList.value.filter(f => f.url !== undefined).concat(uploadList.value); |
| | | uploadList.value = []; |
| | | number.value = 0; |
| | | emit("update:modelValue", listToString(fileList.value)); |
| | | proxy?.$modal.closeLoading(); |
| | | } |
| | | } |
| | | if (number.value > 0 && uploadList.value.length === number.value) { |
| | | fileList.value = fileList.value.filter((f) => f.url !== undefined).concat(uploadList.value); |
| | | uploadList.value = []; |
| | | number.value = 0; |
| | | emit('update:modelValue', listToString(fileList.value)); |
| | | proxy?.$modal.closeLoading(); |
| | | } |
| | | }; |
| | | |
| | | // è·åæä»¶åç§° |
| | | const getFileName = (name: string) => { |
| | | // 妿æ¯urlé£ä¹åæåçåå 妿䏿¯ç´æ¥è¿å |
| | | if (name.lastIndexOf("/") > -1) { |
| | | return name.slice(name.lastIndexOf("/") + 1); |
| | | } else { |
| | | return name; |
| | | } |
| | | } |
| | | // 妿æ¯urlé£ä¹åæåçåå 妿䏿¯ç´æ¥è¿å |
| | | if (name.lastIndexOf('/') > -1) { |
| | | return name.slice(name.lastIndexOf('/') + 1); |
| | | } else { |
| | | return name; |
| | | } |
| | | }; |
| | | |
| | | // 对象转ææå®å符串åé |
| | | const listToString = (list: any[], separator?: string) => { |
| | | let strs = ""; |
| | | separator = separator || ","; |
| | | list.forEach(item => { |
| | | if (item.ossId) { |
| | | strs += item.ossId + separator; |
| | | } |
| | | }) |
| | | return strs != "" ? strs.substring(0, strs.length - 1) : ""; |
| | | } |
| | | let strs = ''; |
| | | separator = separator || ','; |
| | | list.forEach((item) => { |
| | | if (item.ossId) { |
| | | strs += item.ossId + separator; |
| | | } |
| | | }); |
| | | return strs != '' ? strs.substring(0, strs.length - 1) : ''; |
| | | }; |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | .upload-file-uploader { |
| | | margin-bottom: 5px; |
| | | margin-bottom: 5px; |
| | | } |
| | | |
| | | .upload-file-list .el-upload-list__item { |
| | | border: 1px solid #e4e7ed; |
| | | line-height: 2; |
| | | margin-bottom: 10px; |
| | | position: relative; |
| | | border: 1px solid #e4e7ed; |
| | | line-height: 2; |
| | | margin-bottom: 10px; |
| | | position: relative; |
| | | } |
| | | |
| | | .upload-file-list .ele-upload-list__item-content { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | color: inherit; |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | color: inherit; |
| | | } |
| | | |
| | | .ele-upload-list__item-content-action .el-link { |
| | | margin-right: 10px; |
| | | margin-right: 10px; |
| | | } |
| | | </style> |
| | |
| | | <template> |
| | | <div style="padding: 0 15px;" @click="toggleClick"> |
| | | <div style="padding: 0 15px" @click="toggleClick"> |
| | | <svg :class="{ 'is-active': isActive }" class="hamburger" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" width="64" height="64"> |
| | | <path |
| | | d="M408 442h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8zm-8 204c0 4.4 3.6 8 8 8h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56zm504-486H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0 632H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zM142.4 642.1L298.7 519a8.84 8.84 0 0 0 0-13.9L142.4 381.9c-5.8-4.6-14.4-.5-14.4 6.9v246.3a8.9 8.9 0 0 0 14.4 7z" |
| | |
| | | |
| | | defineProps({ |
| | | isActive: propTypes.bool.def(false) |
| | | }) |
| | | }); |
| | | |
| | | const emit = defineEmits(['toggleClick']) |
| | | const emit = defineEmits(['toggleClick']); |
| | | const toggleClick = () => { |
| | | emit('toggleClick'); |
| | | } |
| | | }; |
| | | </script> |
| | | |
| | | <style scoped> |
| | |
| | | <template> |
| | | <div :class="{ 'show': show }" class="header-search"> |
| | | <svg-icon class-name="search-icon" icon-class="search" @click.stop="click"/> |
| | | <div :class="{ show: show }" class="header-search"> |
| | | <svg-icon class-name="search-icon" icon-class="search" @click.stop="click" /> |
| | | <el-select |
| | | ref="headerSearchSelectRef" |
| | | v-model="search" |
| | |
| | | class="header-search-select" |
| | | @change="change" |
| | | > |
| | | <el-option v-for="option in options" :key="option.item.path" :value="option.item" |
| | | :label="option.item.title.join(' > ')"/> |
| | | <el-option v-for="option in options" :key="option.item.path" :value="option.item" :label="option.item.title.join(' > ')" /> |
| | | </el-select> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup lang="ts" name="HeaderSearch"> |
| | | import Fuse from 'fuse.js'; |
| | | import {getNormalPath} from '@/utils/ruoyi'; |
| | | import {isHttp} from '@/utils/validate'; |
| | | import { getNormalPath } from '@/utils/ruoyi'; |
| | | import { isHttp } from '@/utils/validate'; |
| | | import usePermissionStore from '@/store/modules/permission'; |
| | | import {RouteOption} from 'vue-router'; |
| | | import { RouteRecordRaw } from 'vue-router'; |
| | | |
| | | type Router = Array<{ |
| | | path: string; |
| | | title: string[]; |
| | | }> |
| | | }>; |
| | | |
| | | const search = ref(''); |
| | | const options = ref<any>([]); |
| | |
| | | const routes = computed(() => usePermissionStore().routes); |
| | | |
| | | const click = () => { |
| | | show.value = !show.value |
| | | show.value = !show.value; |
| | | if (show.value) { |
| | | headerSearchSelectRef.value && headerSearchSelectRef.value.focus() |
| | | headerSearchSelectRef.value && headerSearchSelectRef.value.focus(); |
| | | } |
| | | }; |
| | | const close = () => { |
| | | headerSearchSelectRef.value && headerSearchSelectRef.value.blur() |
| | | options.value = [] |
| | | show.value = false |
| | | } |
| | | headerSearchSelectRef.value && headerSearchSelectRef.value.blur(); |
| | | options.value = []; |
| | | show.value = false; |
| | | }; |
| | | const change = (val: any) => { |
| | | const path = val.path; |
| | | const query = val.query; |
| | | if (isHttp(path)) { |
| | | // http(s):// è·¯å¾æ°çªå£æå¼ |
| | | const pindex = path.indexOf("http"); |
| | | window.open(path.substr(pindex, path.length), "_blank"); |
| | | const pindex = path.indexOf('http'); |
| | | window.open(path.substr(pindex, path.length), '_blank'); |
| | | } else { |
| | | if (query) { |
| | | router.push({ path: path, query: JSON.parse(query) }); |
| | | } else { |
| | | router.push(path) |
| | | router.push(path); |
| | | } |
| | | } |
| | | search.value = '' |
| | | options.value = [] |
| | | search.value = ''; |
| | | options.value = []; |
| | | nextTick(() => { |
| | | show.value = false |
| | | }) |
| | | } |
| | | show.value = false; |
| | | }); |
| | | }; |
| | | const initFuse = (list: Router) => { |
| | | fuse.value = new Fuse(list, { |
| | | shouldSort: true, |
| | |
| | | location: 0, |
| | | distance: 100, |
| | | minMatchCharLength: 1, |
| | | keys: [{ |
| | | name: 'title', |
| | | weight: 0.7 |
| | | }, { |
| | | name: 'path', |
| | | weight: 0.3 |
| | | }] |
| | | }) |
| | | } |
| | | keys: [ |
| | | { |
| | | name: 'title', |
| | | weight: 0.7 |
| | | }, |
| | | { |
| | | name: 'path', |
| | | weight: 0.3 |
| | | } |
| | | ] |
| | | }); |
| | | }; |
| | | // Filter out the routes that can be displayed in the sidebar |
| | | // And generate the internationalized title |
| | | const generateRoutes = (routes: RouteOption[], basePath = '', prefixTitle: string[] = []) => { |
| | | let res: Router = [] |
| | | routes.forEach(r => { |
| | | const generateRoutes = (routes: RouteRecordRaw[], basePath = '', prefixTitle: string[] = []) => { |
| | | let res: Router = []; |
| | | routes.forEach((r) => { |
| | | // skip hidden router |
| | | if (!r.hidden) { |
| | | const p = r.path.length > 0 && r.path[0] === '/' ? r.path : '/' + r.path; |
| | |
| | | path: !isHttp(r.path) ? getNormalPath(basePath + p) : r.path, |
| | | title: [...prefixTitle], |
| | | query: '' |
| | | } |
| | | }; |
| | | if (r.meta && r.meta.title) { |
| | | data.title = [...data.title, r.meta.title]; |
| | | if (r.redirect !== 'noRedirect') { |
| | |
| | | } |
| | | |
| | | if (r.query) { |
| | | data.query = r.query |
| | | data.query = r.query; |
| | | } |
| | | |
| | | // recursive child routes |
| | |
| | | } |
| | | } |
| | | } |
| | | }) |
| | | }); |
| | | return res; |
| | | } |
| | | }; |
| | | const querySearch = (query: string) => { |
| | | if (query !== '') { |
| | | options.value = fuse.value.search(query) |
| | | options.value = fuse.value.search(query); |
| | | } else { |
| | | options.value = [] |
| | | options.value = []; |
| | | } |
| | | } |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | searchPool.value = generateRoutes(routes.value); |
| | | }) |
| | | }); |
| | | |
| | | // watchEffect(() => { |
| | | // searchPool.value = generateRoutes(routes.value) |
| | |
| | | |
| | | watch(show, (value) => { |
| | | if (value) { |
| | | document.body.addEventListener('click', close) |
| | | document.body.addEventListener('click', close); |
| | | } else { |
| | | document.body.removeEventListener('click', close) |
| | | document.body.removeEventListener('click', close); |
| | | } |
| | | }) |
| | | }); |
| | | |
| | | watch(searchPool, (list) => { |
| | | initFuse(list) |
| | | }) |
| | | initFuse(list); |
| | | }); |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | |
| | | <template> |
| | | <div class="relative" :style="{ width: width }"> |
| | | <el-input v-model="modelValue" readonly @click="visible = !visible" placeholder="ç¹å»éæ©å¾æ "> |
| | | <el-input v-model="modelValue" readonly placeholder="ç¹å»éæ©å¾æ " @click="visible = !visible"> |
| | | <template #prepend> |
| | | <svg-icon :icon-class="modelValue" /> |
| | | </template> |
| | |
| | | |
| | | <el-popover shadow="none" :visible="visible" placement="bottom-end" trigger="click" :width="450"> |
| | | <template #reference> |
| | | <div @click="visible = !visible" class="cursor-pointer text-[#999] absolute right-[10px] top-0 height-[32px] leading-[32px]"> |
| | | <div class="cursor-pointer text-[#999] absolute right-[10px] top-0 height-[32px] leading-[32px]" @click="visible = !visible"> |
| | | <i-ep-caret-top v-show="visible"></i-ep-caret-top> |
| | | <i-ep-caret-bottom v-show="!visible"></i-ep-caret-bottom> |
| | | </div> |
| | | </template> |
| | | |
| | | <el-input class="p-2" v-model="filterValue" placeholder="æç´¢å¾æ " clearable @input="filterIcons" /> |
| | | <el-input v-model="filterValue" class="p-2" placeholder="æç´¢å¾æ " clearable @input="filterIcons" /> |
| | | |
| | | <el-scrollbar height="w-[200px]"> |
| | | <ul class="icon-list"> |
| | | <el-tooltip v-for="(iconName, index) in iconNames" :key="index" :content="iconName" placement="bottom" effect="light"> |
| | | <li :class="['icon-item', {active: modelValue == iconName}]" @click="selectedIcon(iconName)"> |
| | | <li :class="['icon-item', { active: modelValue == iconName }]" @click="selectedIcon(iconName)"> |
| | | <svg-icon color="var(--el-text-color-regular)" :icon-class="iconName" /> |
| | | </li> |
| | | </el-tooltip> |
| | |
| | | */ |
| | | const filterIcons = () => { |
| | | if (filterValue.value) { |
| | | iconNames.value = icons.filter(iconName => |
| | | iconName.includes(filterValue.value) |
| | | ); |
| | | iconNames.value = icons.filter((iconName) => iconName.includes(filterValue.value)); |
| | | } else { |
| | | iconNames.value = icons; |
| | | } |
| | | } |
| | | }; |
| | | /** |
| | | * 鿩徿 |
| | | * @param iconName éæ©ç徿 åç§° |
| | |
| | | const selectedIcon = (iconName: string) => { |
| | | emit('update:modelValue', iconName); |
| | | visible.value = false; |
| | | } |
| | | }; |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | .el-scrollbar { |
| | | max-height: calc(50vh - 100px)!important; |
| | | max-height: calc(50vh - 100px) !important; |
| | | overflow-y: auto; |
| | | } |
| | | .el-divider--horizontal { |
| | |
| | | } |
| | | } |
| | | .active { |
| | | border-color: var(--el-color-primary); |
| | | color: var(--el-color-primary); |
| | | } |
| | | border-color: var(--el-color-primary); |
| | | color: var(--el-color-primary); |
| | | } |
| | | } |
| | | </style> |
| | |
| | | src: propTypes.string.def(''), |
| | | width: { |
| | | type: [Number, String], |
| | | default: "" |
| | | default: '' |
| | | }, |
| | | height: { |
| | | type: [Number, String], |
| | | default: "" |
| | | default: '' |
| | | } |
| | | }); |
| | | |
| | |
| | | if (!props.src) { |
| | | return; |
| | | } |
| | | let real_src = props.src.split(",")[0]; |
| | | let real_src = props.src.split(',')[0]; |
| | | return real_src; |
| | | }); |
| | | |
| | |
| | | if (!props.src) { |
| | | return; |
| | | } |
| | | let real_src_list = props.src.split(","); |
| | | let real_src_list = props.src.split(','); |
| | | let srcList: string[] = []; |
| | | real_src_list.forEach(item => { |
| | | real_src_list.forEach((item) => { |
| | | return srcList.push(item); |
| | | }); |
| | | return srcList; |
| | | }); |
| | | |
| | | const realWidth = computed(() => |
| | | typeof props.width == "string" ? props.width : `${props.width}px` |
| | | ); |
| | | const realWidth = computed(() => (typeof props.width == 'string' ? props.width : `${props.width}px`)); |
| | | |
| | | const realHeight = computed(() => |
| | | typeof props.height == "string" ? props.height : `${props.height}px` |
| | | ); |
| | | const realHeight = computed(() => (typeof props.height == 'string' ? props.height : `${props.height}px`)); |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | |
| | | <template> |
| | | <div class="component-upload-image"> |
| | | <el-upload |
| | | ref="imageUpload" |
| | | multiple |
| | | :action="uploadImgUrl" |
| | | list-type="picture-card" |
| | |
| | | :limit="limit" |
| | | :on-error="handleUploadError" |
| | | :on-exceed="handleExceed" |
| | | ref="imageUpload" |
| | | :before-remove="handleDelete" |
| | | :show-file-list="true" |
| | | :headers="headers" |
| | |
| | | </el-icon> |
| | | </el-upload> |
| | | <!-- ä¸ä¼ æç¤º --> |
| | | <div class="el-upload__tip" v-if="showTip"> |
| | | <div v-if="showTip" class="el-upload__tip"> |
| | | 请ä¸ä¼ |
| | | <template v-if="fileSize"> |
| | | 大å°ä¸è¶
è¿ <b style="color: #f56c6c">{{ fileSize }}MB</b> |
| | | </template> |
| | | <template v-if="fileType"> |
| | | æ ¼å¼ä¸º <b style="color: #f56c6c">{{ fileType.join("/") }}</b> |
| | | æ ¼å¼ä¸º <b style="color: #f56c6c">{{ fileType.join('/') }}</b> |
| | | </template> |
| | | çæä»¶ |
| | | </div> |
| | |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import { listByIds, delOss } from "@/api/system/oss"; |
| | | import { ComponentInternalInstance } from "vue"; |
| | | import { OssVO } from "@/api/system/oss/types"; |
| | | import { listByIds, delOss } from '@/api/system/oss'; |
| | | import { OssVO } from '@/api/system/oss/types'; |
| | | import { propTypes } from '@/utils/propTypes'; |
| | | import {globalHeaders} from "@/utils/request"; |
| | | import { globalHeaders } from '@/utils/request'; |
| | | |
| | | const props = defineProps({ |
| | | modelValue: [String, Object, Array], |
| | | // å¾çæ°ééå¶ |
| | | limit: propTypes.number.def(5), |
| | | // 大å°éå¶(MB) |
| | | fileSize: propTypes.number.def(5), |
| | | // æä»¶ç±»å, ä¾å¦['png', 'jpg', 'jpeg'] |
| | | fileType: propTypes.array.def(["png", "jpg", "jpeg"]), |
| | | // æ¯å¦æ¾ç¤ºæç¤º |
| | | isShowTip: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | modelValue: [String, Object, Array], |
| | | // å¾çæ°ééå¶ |
| | | limit: propTypes.number.def(5), |
| | | // 大å°éå¶(MB) |
| | | fileSize: propTypes.number.def(5), |
| | | // æä»¶ç±»å, ä¾å¦['png', 'jpg', 'jpeg'] |
| | | fileType: propTypes.array.def(['png', 'jpg', 'jpeg']), |
| | | // æ¯å¦æ¾ç¤ºæç¤º |
| | | isShowTip: { |
| | | type: Boolean, |
| | | default: true |
| | | } |
| | | }); |
| | | |
| | | const { proxy } = getCurrentInstance() as ComponentInternalInstance; |
| | | const emit = defineEmits(['update:modelValue']); |
| | | const number = ref(0); |
| | | const uploadList = ref<any[]>([]); |
| | | const dialogImageUrl = ref(""); |
| | | const dialogImageUrl = ref(''); |
| | | const dialogVisible = ref(false); |
| | | |
| | | const baseUrl = import.meta.env.VITE_APP_BASE_API; |
| | | const uploadImgUrl = ref(baseUrl + "/resource/oss/upload"); // ä¸ä¼ çå¾çæå¡å¨å°å |
| | | const uploadImgUrl = ref(baseUrl + '/resource/oss/upload'); // ä¸ä¼ çå¾çæå¡å¨å°å |
| | | const headers = ref(globalHeaders()); |
| | | |
| | | const fileList = ref<any[]>([]); |
| | | const showTip = computed( |
| | | () => props.isShowTip && (props.fileType || props.fileSize) |
| | | ); |
| | | const showTip = computed(() => props.isShowTip && (props.fileType || props.fileSize)); |
| | | |
| | | const imageUploadRef = ref<ElUploadInstance>(); |
| | | |
| | | watch(() => props.modelValue, async val => { |
| | | watch( |
| | | () => props.modelValue, |
| | | async (val) => { |
| | | if (val) { |
| | | // é¦å
å°å¼è½¬ä¸ºæ°ç» |
| | | let list: OssVO[] = []; |
| | | if (Array.isArray(val)) { |
| | | list = val as OssVO[]; |
| | | // é¦å
å°å¼è½¬ä¸ºæ°ç» |
| | | let list: OssVO[] = []; |
| | | if (Array.isArray(val)) { |
| | | list = val as OssVO[]; |
| | | } else { |
| | | const res = await listByIds(val as string); |
| | | list = res.data; |
| | | } |
| | | // ç¶åå°æ°ç»è½¬ä¸ºå¯¹è±¡æ°ç» |
| | | fileList.value = list.map((item) => { |
| | | // åç¬¦ä¸²åæ¾å¤ç 妿æ¤å¤åçæ¯urlå¯ç´æ¥åæ¾ å¦æåçæ¯idéè¦è°ç¨æ¥å£æ¥åºæ¥ |
| | | let itemData; |
| | | if (typeof item === 'string') { |
| | | itemData = { name: item, url: item }; |
| | | } else { |
| | | const res = await listByIds(val as string) |
| | | list = res.data |
| | | // æ¤å¤name使ç¨ossId 鲿¢å é¤åºç°éå |
| | | itemData = { name: item.ossId, url: item.url, ossId: item.ossId }; |
| | | } |
| | | // ç¶åå°æ°ç»è½¬ä¸ºå¯¹è±¡æ°ç» |
| | | fileList.value = list.map(item => { |
| | | // åç¬¦ä¸²åæ¾å¤ç 妿æ¤å¤åçæ¯urlå¯ç´æ¥åæ¾ å¦æåçæ¯idéè¦è°ç¨æ¥å£æ¥åºæ¥ |
| | | let itemData; |
| | | if (typeof item === "string") { |
| | | itemData = { name: item, url: item }; |
| | | } else { |
| | | // æ¤å¤name使ç¨ossId 鲿¢å é¤åºç°éå |
| | | itemData = { name: item.ossId, url: item.url, ossId: item.ossId }; |
| | | } |
| | | return itemData; |
| | | }); |
| | | return itemData; |
| | | }); |
| | | } else { |
| | | fileList.value = []; |
| | | return []; |
| | | fileList.value = []; |
| | | return []; |
| | | } |
| | | }, { deep: true, immediate: true }); |
| | | }, |
| | | { deep: true, immediate: true } |
| | | ); |
| | | |
| | | /** ä¸ä¼ åloadingå è½½ */ |
| | | const handleBeforeUpload = (file: any) => { |
| | | let isImg = false; |
| | | if (props.fileType.length) { |
| | | let fileExtension = ""; |
| | | if (file.name.lastIndexOf(".") > -1) { |
| | | fileExtension = file.name.slice(file.name.lastIndexOf(".") + 1); |
| | | } |
| | | isImg = props.fileType.some((type: any) => { |
| | | if (file.type.indexOf(type) > -1) return true; |
| | | if (fileExtension && fileExtension.indexOf(type) > -1) return true; |
| | | return false; |
| | | }); |
| | | } else { |
| | | isImg = file.type.indexOf("image") > -1; |
| | | let isImg = false; |
| | | if (props.fileType.length) { |
| | | let fileExtension = ''; |
| | | if (file.name.lastIndexOf('.') > -1) { |
| | | fileExtension = file.name.slice(file.name.lastIndexOf('.') + 1); |
| | | } |
| | | if (!isImg) { |
| | | proxy?.$modal.msgError( |
| | | `æä»¶æ ¼å¼ä¸æ£ç¡®, 请ä¸ä¼ ${props.fileType.join("/")}å¾çæ ¼å¼æä»¶!` |
| | | ); |
| | | return false; |
| | | isImg = props.fileType.some((type: any) => { |
| | | if (file.type.indexOf(type) > -1) return true; |
| | | if (fileExtension && fileExtension.indexOf(type) > -1) return true; |
| | | return false; |
| | | }); |
| | | } else { |
| | | isImg = file.type.indexOf('image') > -1; |
| | | } |
| | | if (!isImg) { |
| | | proxy?.$modal.msgError(`æä»¶æ ¼å¼ä¸æ£ç¡®, 请ä¸ä¼ ${props.fileType.join('/')}å¾çæ ¼å¼æä»¶!`); |
| | | return false; |
| | | } |
| | | if (props.fileSize) { |
| | | const isLt = file.size / 1024 / 1024 < props.fileSize; |
| | | if (!isLt) { |
| | | proxy?.$modal.msgError(`ä¸ä¼ 头åå¾ç大å°ä¸è½è¶
è¿ ${props.fileSize} MB!`); |
| | | return false; |
| | | } |
| | | if (props.fileSize) { |
| | | const isLt = file.size / 1024 / 1024 < props.fileSize; |
| | | if (!isLt) { |
| | | proxy?.$modal.msgError(`ä¸ä¼ 头åå¾ç大å°ä¸è½è¶
è¿ ${props.fileSize} MB!`); |
| | | return false; |
| | | } |
| | | } |
| | | proxy?.$modal.loading("æ£å¨ä¸ä¼ å¾çï¼è¯·ç¨å..."); |
| | | number.value++; |
| | | } |
| | | } |
| | | proxy?.$modal.loading('æ£å¨ä¸ä¼ å¾çï¼è¯·ç¨å...'); |
| | | number.value++; |
| | | }; |
| | | |
| | | // æä»¶ä¸ªæ°è¶
åº |
| | | const handleExceed = () => { |
| | | proxy?.$modal.msgError(`ä¸ä¼ æä»¶æ°éä¸è½è¶
è¿ ${props.limit} 个!`); |
| | | } |
| | | proxy?.$modal.msgError(`ä¸ä¼ æä»¶æ°éä¸è½è¶
è¿ ${props.limit} 个!`); |
| | | }; |
| | | |
| | | // ä¸ä¼ æååè° |
| | | const handleUploadSuccess = (res: any, file: UploadFile) => { |
| | | if (res.code === 200) { |
| | | uploadList.value.push({ name: res.data.fileName, url: res.data.url, ossId: res.data.ossId }); |
| | | uploadedSuccessfully(); |
| | | } else { |
| | | number.value--; |
| | | proxy?.$modal.closeLoading(); |
| | | proxy?.$modal.msgError(res.msg); |
| | | imageUploadRef.value?.handleRemove(file); |
| | | uploadedSuccessfully(); |
| | | } |
| | | } |
| | | if (res.code === 200) { |
| | | uploadList.value.push({ name: res.data.fileName, url: res.data.url, ossId: res.data.ossId }); |
| | | uploadedSuccessfully(); |
| | | } else { |
| | | number.value--; |
| | | proxy?.$modal.closeLoading(); |
| | | proxy?.$modal.msgError(res.msg); |
| | | imageUploadRef.value?.handleRemove(file); |
| | | uploadedSuccessfully(); |
| | | } |
| | | }; |
| | | |
| | | // å é¤å¾ç |
| | | const handleDelete = (file: UploadFile): boolean => { |
| | | const findex = fileList.value.map(f => f.name).indexOf(file.name); |
| | | if (findex > -1 && uploadList.value.length === number.value) { |
| | | let ossId = fileList.value[findex].ossId; |
| | | delOss(ossId); |
| | | fileList.value.splice(findex, 1); |
| | | emit("update:modelValue", listToString(fileList.value)); |
| | | return false; |
| | | } |
| | | return true; |
| | | } |
| | | const findex = fileList.value.map((f) => f.name).indexOf(file.name); |
| | | if (findex > -1 && uploadList.value.length === number.value) { |
| | | let ossId = fileList.value[findex].ossId; |
| | | delOss(ossId); |
| | | fileList.value.splice(findex, 1); |
| | | emit('update:modelValue', listToString(fileList.value)); |
| | | return false; |
| | | } |
| | | return true; |
| | | }; |
| | | |
| | | // ä¸ä¼ ç»æå¤ç |
| | | const uploadedSuccessfully = () => { |
| | | if (number.value > 0 && uploadList.value.length === number.value) { |
| | | fileList.value = fileList.value.filter(f => f.url !== undefined).concat(uploadList.value); |
| | | uploadList.value = []; |
| | | number.value = 0; |
| | | emit("update:modelValue", listToString(fileList.value)); |
| | | proxy?.$modal.closeLoading(); |
| | | } |
| | | } |
| | | if (number.value > 0 && uploadList.value.length === number.value) { |
| | | fileList.value = fileList.value.filter((f) => f.url !== undefined).concat(uploadList.value); |
| | | uploadList.value = []; |
| | | number.value = 0; |
| | | emit('update:modelValue', listToString(fileList.value)); |
| | | proxy?.$modal.closeLoading(); |
| | | } |
| | | }; |
| | | |
| | | // ä¸ä¼ 失败 |
| | | const handleUploadError = () => { |
| | | proxy?.$modal.msgError("ä¸ä¼ å¾ç失败"); |
| | | proxy?.$modal.closeLoading(); |
| | | } |
| | | proxy?.$modal.msgError('ä¸ä¼ å¾ç失败'); |
| | | proxy?.$modal.closeLoading(); |
| | | }; |
| | | |
| | | // é¢è§ |
| | | const handlePictureCardPreview = (file: any) => { |
| | | dialogImageUrl.value = file.url; |
| | | dialogVisible.value = true; |
| | | } |
| | | dialogImageUrl.value = file.url; |
| | | dialogVisible.value = true; |
| | | }; |
| | | |
| | | // 对象转ææå®å符串åé |
| | | const listToString = (list: any[], separator?: string) => { |
| | | let strs = ""; |
| | | separator = separator || ","; |
| | | for (let i in list) { |
| | | if (undefined !== list[i].ossId && list[i].url.indexOf("blob:") !== 0) { |
| | | strs += list[i].ossId + separator; |
| | | } |
| | | let strs = ''; |
| | | separator = separator || ','; |
| | | for (let i in list) { |
| | | if (undefined !== list[i].ossId && list[i].url.indexOf('blob:') !== 0) { |
| | | strs += list[i].ossId + separator; |
| | | } |
| | | return strs != "" ? strs.substring(0, strs.length - 1) : ""; |
| | | } |
| | | } |
| | | return strs != '' ? strs.substring(0, strs.length - 1) : ''; |
| | | }; |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | // .el-upload--picture-card æ§å¶å å·é¨å |
| | | :deep(.hide .el-upload--picture-card) { |
| | | display: none; |
| | | display: none; |
| | | } |
| | | </style> |
| | |
| | | const appStore = useAppStore(); |
| | | const { locale } = useI18n(); |
| | | |
| | | |
| | | const message: any = { |
| | | zh_CN: '忢è¯è¨æåï¼', |
| | | en_US: 'Switch Language Successful!', |
| | | } |
| | | en_US: 'Switch Language Successful!' |
| | | }; |
| | | const handleLanguageChange = (lang: string) => { |
| | | locale.value = lang; |
| | | appStore.changeLanguage(lang); |
| | | ElMessage.success(message[lang] || '忢è¯è¨æåï¼'); |
| | | } |
| | | }; |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | |
| | | <template> |
| | | <div :class="{ 'hidden': hidden }" class="pagination-container"> |
| | | <div :class="{ hidden: hidden }" class="pagination-container"> |
| | | <el-pagination |
| | | :background="background" |
| | | v-model:current-page="currentPage" |
| | | v-model:page-size="pageSize" |
| | | :background="background" |
| | | :layout="layout" |
| | | :page-sizes="pageSizes" |
| | | :pager-count="pagerCount" |
| | |
| | | |
| | | <script lang="ts"> |
| | | export default { |
| | | name: 'Pagination' |
| | | } |
| | | name: 'Pagination' |
| | | }; |
| | | </script> |
| | | |
| | | <script setup lang="ts"> |
| | | import { scrollTo } from '@/utils/scroll-to' |
| | | import { propTypes } from "@/utils/propTypes"; |
| | | import { scrollTo } from '@/utils/scroll-to'; |
| | | import { propTypes } from '@/utils/propTypes'; |
| | | |
| | | const props = defineProps({ |
| | | total: propTypes.number, |
| | | page: propTypes.number.def(1), |
| | | limit: propTypes.number.def(20), |
| | | pageSizes: { |
| | | type: Array as PropType<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'), |
| | | background: propTypes.bool.def(true), |
| | | autoScroll: propTypes.bool.def(true), |
| | | hidden: propTypes.bool.def(false), |
| | | float: propTypes.string.def('right') |
| | | }) |
| | | total: propTypes.number, |
| | | page: propTypes.number.def(1), |
| | | limit: propTypes.number.def(20), |
| | | pageSizes: { |
| | | type: Array, |
| | | 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'), |
| | | background: propTypes.bool.def(true), |
| | | autoScroll: propTypes.bool.def(true), |
| | | hidden: propTypes.bool.def(false), |
| | | float: propTypes.string.def('right') |
| | | }); |
| | | |
| | | const emit = defineEmits(['update:page', 'update:limit', 'pagination']); |
| | | const currentPage = computed({ |
| | | get() { |
| | | return props.page |
| | | }, |
| | | set(val) { |
| | | emit('update:page', val) |
| | | } |
| | | }) |
| | | get() { |
| | | return props.page; |
| | | }, |
| | | set(val) { |
| | | emit('update:page', val); |
| | | } |
| | | }); |
| | | const pageSize = computed({ |
| | | get() { |
| | | return props.limit |
| | | }, |
| | | set(val){ |
| | | emit('update:limit', val) |
| | | } |
| | | }) |
| | | get() { |
| | | return props.limit; |
| | | }, |
| | | set(val) { |
| | | emit('update:limit', val); |
| | | } |
| | | }); |
| | | function handleSizeChange(val: number) { |
| | | if (currentPage.value * val > props.total) { |
| | | currentPage.value = 1 |
| | | } |
| | | emit('pagination', { page: currentPage.value, limit: val }) |
| | | if (props.autoScroll) { |
| | | scrollTo(0, 800) |
| | | } |
| | | if (currentPage.value * val > props.total) { |
| | | currentPage.value = 1; |
| | | } |
| | | emit('pagination', { page: currentPage.value, limit: val }); |
| | | if (props.autoScroll) { |
| | | scrollTo(0, 800); |
| | | } |
| | | } |
| | | function handleCurrentChange(val: number) { |
| | | emit('pagination', { page: val, limit: pageSize.value }) |
| | | if (props.autoScroll) { |
| | | scrollTo(0, 800) |
| | | } |
| | | emit('pagination', { page: val, limit: pageSize.value }); |
| | | if (props.autoScroll) { |
| | | scrollTo(0, 800); |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .pagination-container { |
| | | padding: 32px 16px; |
| | | .el-pagination{ |
| | | .el-pagination { |
| | | float: v-bind(float); |
| | | } |
| | | } |
| | |
| | | <template> |
| | | <div class="top-right-btn" :style="style"> |
| | | <el-row> |
| | | <el-tooltip class="item" effect="dark" :content="showSearch ? 'éèæç´¢' : 'æ¾ç¤ºæç´¢'" placement="top" v-if="search"> |
| | | <el-tooltip v-if="search" class="item" effect="dark" :content="showSearch ? 'éèæç´¢' : 'æ¾ç¤ºæç´¢'" placement="top"> |
| | | <el-button circle icon="Search" @click="toggleSearch()" /> |
| | | </el-tooltip> |
| | | <el-tooltip class="item" effect="dark" content="å·æ°" placement="top"> |
| | | <el-button circle icon="Refresh" @click="refresh()" /> |
| | | </el-tooltip> |
| | | <el-tooltip class="item" effect="dark" content="æ¾ç¤º/éèå" placement="top" v-if="columns"> |
| | | <el-tooltip v-if="columns" class="item" effect="dark" content="æ¾ç¤º/éèå" placement="top"> |
| | | <div class="show-btn"> |
| | | <el-popover placement="bottom" trigger="click"> |
| | | <div class="tree-header">æ¾ç¤º/éèå</div> |
| | |
| | | ref="columnRef" |
| | | :data="columns" |
| | | show-checkbox |
| | | @check="columnChange" |
| | | node-key="key" |
| | | :props="{ label: 'label', children: 'children' }" |
| | | @check="columnChange" |
| | | ></el-tree> |
| | | <template #reference> |
| | | <el-button circle icon="Menu" /> |
| | |
| | | import { propTypes } from '@/utils/propTypes'; |
| | | |
| | | const props = defineProps({ |
| | | showSearch: propTypes.bool.def(true), |
| | | columns: { |
| | | type: Array as PropType<FieldOption[]>, |
| | | }, |
| | | search: propTypes.bool.def(true), |
| | | gutter: propTypes.number.def(10), |
| | | }) |
| | | showSearch: propTypes.bool.def(true), |
| | | columns: propTypes.fieldOption, |
| | | search: propTypes.bool.def(true), |
| | | gutter: propTypes.number.def(10) |
| | | }); |
| | | |
| | | const columnRef = ref<ElTreeInstance>(); |
| | | const emits = defineEmits(['update:showSearch', 'queryTable']); |
| | | |
| | | const style = computed(() => { |
| | | const ret: any = {}; |
| | | if (props.gutter) { |
| | | ret.marginRight = `${props.gutter / 2}px`; |
| | | } |
| | | return ret; |
| | | const ret: any = {}; |
| | | if (props.gutter) { |
| | | ret.marginRight = `${props.gutter / 2}px`; |
| | | } |
| | | return ret; |
| | | }); |
| | | |
| | | // æç´¢ |
| | | function toggleSearch() { |
| | | emits("update:showSearch", !props.showSearch); |
| | | emits('update:showSearch', !props.showSearch); |
| | | } |
| | | |
| | | // å·æ° |
| | | function refresh() { |
| | | emits("queryTable"); |
| | | emits('queryTable'); |
| | | } |
| | | |
| | | // æ´æ¹æ°æ®åçæ¾ç¤ºåéè |
| | | function columnChange(...args: any[]) { |
| | | props.columns?.forEach((item) => { |
| | | item.visible = args[1].checkedKeys.includes(item.key); |
| | | }) |
| | | }); |
| | | } |
| | | |
| | | // æ¾éååå§é»è®¤éèå |
| | | onMounted(() => { |
| | | props.columns?.forEach((item) => { |
| | | if (item.visible) { |
| | | columnRef.value?.setChecked(item.key, true, false); |
| | | // value.value.push(item.key); |
| | | } |
| | | }) |
| | | }) |
| | | props.columns?.forEach((item) => { |
| | | if (item.visible) { |
| | | columnRef.value?.setChecked(item.key, true, false); |
| | | // value.value.push(item.key); |
| | | } |
| | | }); |
| | | }); |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | |
| | | .my-el-transfer { |
| | | text-align: center; |
| | | } |
| | | .tree-header{ |
| | | .tree-header { |
| | | width: 100%; |
| | | line-height: 24px; |
| | | text-align: center; |
| | |
| | | const url = ref('https://plus-doc.dromara.org/'); |
| | | |
| | | function goto() { |
| | | window.open(url.value) |
| | | window.open(url.value); |
| | | } |
| | | </script> |
| | |
| | | const url = ref('https://gitee.com/dromara/RuoYi-Vue-Plus'); |
| | | |
| | | function goto() { |
| | | window.open(url.value) |
| | | window.open(url.value); |
| | | } |
| | | </script> |
| | |
| | | </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); |
| | | |
| | | const sizeOptions = ref([ |
| | | { label: "è¾å¤§", value: "large" }, |
| | | { label: "é»è®¤", value: "default" }, |
| | | { label: "ç¨å°", value: "small" }, |
| | | { label: 'è¾å¤§', value: 'large' }, |
| | | { label: 'é»è®¤', value: 'default' }, |
| | | { label: 'ç¨å°', value: 'small' } |
| | | ]); |
| | | |
| | | const handleSetSize = (size: string) => { |
| | | appStore.setSize(size); |
| | | } |
| | | appStore.setSize(size); |
| | | }; |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | |
| | | import { propTypes } from '@/utils/propTypes'; |
| | | |
| | | const props = defineProps({ |
| | | iconClass: propTypes.string.isRequired, |
| | | className: propTypes.string.def(''), |
| | | color: propTypes.string.def(''), |
| | | }) |
| | | const iconName = computed(() => `#icon-${props.iconClass}`); |
| | | iconClass: propTypes.string.isRequired, |
| | | className: propTypes.string.def(''), |
| | | color: propTypes.string.def('') |
| | | }); |
| | | const iconName = computed(() => `#icon-${props.iconClass}`); |
| | | const svgClass = computed(() => { |
| | | if (props.className) { |
| | | return `svg-icon ${props.className}` |
| | | } |
| | | return 'svg-icon' |
| | | }) |
| | | if (props.className) { |
| | | return `svg-icon ${props.className}`; |
| | | } |
| | | return 'svg-icon'; |
| | | }); |
| | | </script> |
| | | |
| | | <style scope lang="scss"> |
| | |
| | | <template> |
| | | <el-menu :default-active="activeMenu" mode="horizontal" @select="handleSelect" :ellipsis="false"> |
| | | <el-menu :default-active="activeMenu" mode="horizontal" :ellipsis="false" @select="handleSelect"> |
| | | <template v-for="(item, index) in topMenus"> |
| | | <el-menu-item :style="{'--theme': theme}" :index="item.path" :key="index" v-if="index < visibleNumber" |
| | | ><svg-icon |
| | | v-if="item.meta && item.meta.icon && item.meta.icon !== '#'" |
| | | :icon-class="item.meta ? item.meta.icon : '' " /> {{ item.meta?.title }}</el-menu-item |
| | | <el-menu-item v-if="index < visibleNumber" :key="index" :style="{ '--theme': theme }" :index="item.path" |
| | | ><svg-icon v-if="item.meta && item.meta.icon && item.meta.icon !== '#'" :icon-class="item.meta ? item.meta.icon : ''" /> |
| | | {{ item.meta?.title }}</el-menu-item |
| | | > |
| | | </template> |
| | | |
| | | <!-- é¡¶é¨èåè¶
åºæ°éæå --> |
| | | <el-sub-menu :style="{'--theme': theme}" index="more" v-if="topMenus.length > visibleNumber"> |
| | | <el-sub-menu v-if="topMenus.length > visibleNumber" :style="{ '--theme': theme }" index="more"> |
| | | <template #title>æ´å¤èå</template> |
| | | <template v-for="(item, index) in topMenus"> |
| | | <el-menu-item :index="item.path" :key="index" v-if="index >= visibleNumber" |
| | | ><svg-icon :icon-class="item.meta ? item.meta.icon : '' " /> {{ item.meta?.title }}</el-menu-item |
| | | <el-menu-item v-if="index >= visibleNumber" :key="index" :index="item.path" |
| | | ><svg-icon :icon-class="item.meta ? item.meta.icon : ''" /> {{ item.meta?.title }}</el-menu-item |
| | | > |
| | | </template> |
| | | </el-sub-menu> |
| | |
| | | import useAppStore from '@/store/modules/app'; |
| | | import useSettingsStore from '@/store/modules/settings'; |
| | | import usePermissionStore from '@/store/modules/permission'; |
| | | import { RouteOption } from 'vue-router'; |
| | | import { RouteRecordRaw } from 'vue-router'; |
| | | |
| | | // 顶鍿 åå§æ° |
| | | const visibleNumber = ref<number>(-1); |
| | |
| | | // éèä¾§è¾¹æ è·¯ç± |
| | | const hideList = ['/index', '/user/profile']; |
| | | |
| | | const appStore = useAppStore() |
| | | const settingsStore = useSettingsStore() |
| | | const permissionStore = usePermissionStore() |
| | | const appStore = useAppStore(); |
| | | const settingsStore = useSettingsStore(); |
| | | const permissionStore = usePermissionStore(); |
| | | const route = useRoute(); |
| | | const router = useRouter(); |
| | | |
| | |
| | | |
| | | // 顶鍿¾ç¤ºèå |
| | | const topMenus = computed(() => { |
| | | let topMenus:RouteOption[] = []; |
| | | let topMenus: RouteRecordRaw[] = []; |
| | | routers.value.map((menu) => { |
| | | if (menu.hidden !== true) { |
| | | // å
¼å®¹é¡¶é¨æ ä¸çº§èåå
é¨è·³è½¬ |
| | | if (menu.path === "/") { |
| | | topMenus.push(menu.children? menu.children[0] : menu); |
| | | if (menu.path === '/') { |
| | | topMenus.push(menu.children ? menu.children[0] : menu); |
| | | } else { |
| | | topMenus.push(menu); |
| | | topMenus.push(menu); |
| | | } |
| | | } |
| | | }) |
| | | }); |
| | | return topMenus; |
| | | }) |
| | | }); |
| | | |
| | | // 设置åè·¯ç± |
| | | const childrenMenus = computed(() => { |
| | | let childrenMenus:RouteOption[] = []; |
| | | let childrenMenus: RouteRecordRaw[] = []; |
| | | routers.value.map((router) => { |
| | | router.children?.forEach((item) => { |
| | | if (item.parentPath === undefined) { |
| | | if(router.path === "/") { |
| | | item.path = "/" + item.path; |
| | | if (router.path === '/') { |
| | | item.path = '/' + item.path; |
| | | } else { |
| | | if(!isHttp(item.path)) { |
| | | item.path = router.path + "/" + item.path; |
| | | if (!isHttp(item.path)) { |
| | | item.path = router.path + '/' + item.path; |
| | | } |
| | | } |
| | | item.parentPath = router.path; |
| | | } |
| | | childrenMenus.push(item); |
| | | }) |
| | | }) |
| | | }); |
| | | }); |
| | | return constantRoutes.concat(childrenMenus); |
| | | }) |
| | | }); |
| | | |
| | | // é»è®¤æ¿æ´»çèå |
| | | const activeMenu = computed(() => { |
| | | const path = route.path; |
| | | let activePath = path; |
| | | if (path !== undefined && path.lastIndexOf("/") > 0 && hideList.indexOf(path) === -1) { |
| | | if (path !== undefined && path.lastIndexOf('/') > 0 && hideList.indexOf(path) === -1) { |
| | | const tmpPath = path.substring(1, path.length); |
| | | activePath = "/" + tmpPath.substring(0, tmpPath.indexOf("/")); |
| | | activePath = '/' + tmpPath.substring(0, tmpPath.indexOf('/')); |
| | | if (!route.meta.link) { |
| | | appStore.toggleSideBarHide(false); |
| | | appStore.toggleSideBarHide(false); |
| | | } |
| | | } else if(!route.children) { |
| | | } else if (!route.children) { |
| | | activePath = path; |
| | | appStore.toggleSideBarHide(true); |
| | | } |
| | | activeRoutes(activePath); |
| | | return activePath; |
| | | }) |
| | | }); |
| | | |
| | | const setVisibleNumber = () => { |
| | | const width = document.body.getBoundingClientRect().width / 3; |
| | | visibleNumber.value = parseInt(String(width / 85)); |
| | | } |
| | | }; |
| | | |
| | | const handleSelect = (key: string) => { |
| | | currentIndex.value = key; |
| | | const route = routers.value.find(item => item.path === key); |
| | | const route = routers.value.find((item) => item.path === key); |
| | | if (isHttp(key)) { |
| | | // http(s):// è·¯å¾æ°çªå£æå¼ |
| | | window.open(key, "_blank"); |
| | | window.open(key, '_blank'); |
| | | } else if (!route || !route.children) { |
| | | // 没æåè·¯ç±è·¯å¾å
é¨æå¼ |
| | | const routeMenu = childrenMenus.value.find(item => item.path === key); |
| | | const routeMenu = childrenMenus.value.find((item) => item.path === key); |
| | | if (routeMenu && routeMenu.query) { |
| | | let query = JSON.parse(routeMenu.query); |
| | | router.push({ path: key, query: query }); |
| | |
| | | activeRoutes(key); |
| | | appStore.toggleSideBarHide(false); |
| | | } |
| | | } |
| | | }; |
| | | |
| | | const activeRoutes = (key: string) => { |
| | | let routes:RouteOption[] = []; |
| | | let routes: RouteRecordRaw[] = []; |
| | | if (childrenMenus.value && childrenMenus.value.length > 0) { |
| | | childrenMenus.value.map((item) => { |
| | | if (key == item.parentPath || (key == "index" && "" == item.path)) { |
| | | if (key == item.parentPath || (key == 'index' && '' == item.path)) { |
| | | routes.push(item); |
| | | } |
| | | }); |
| | | } |
| | | if(routes.length > 0) { |
| | | if (routes.length > 0) { |
| | | permissionStore.setSidebarRouters(routes); |
| | | } else { |
| | | appStore.toggleSideBarHide(true); |
| | | } |
| | | return routes; |
| | | } |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | window.addEventListener('resize', setVisibleNumber) |
| | | }) |
| | | window.addEventListener('resize', setVisibleNumber); |
| | | }); |
| | | onBeforeUnmount(() => { |
| | | window.removeEventListener('resize', setVisibleNumber) |
| | | }) |
| | | window.removeEventListener('resize', setVisibleNumber); |
| | | }); |
| | | |
| | | onMounted(() => { |
| | | setVisibleNumber() |
| | | }) |
| | | setVisibleNumber(); |
| | | }); |
| | | </script> |
| | | |
| | | <style lang="scss"> |
| | |
| | | margin: 0 10px !important; |
| | | } |
| | | |
| | | .topmenu-container.el-menu--horizontal > .el-menu-item.is-active, .el-menu--horizontal > .el-sub-menu.is-active .el-submenu__title { |
| | | .topmenu-container.el-menu--horizontal > .el-menu-item.is-active, |
| | | .el-menu--horizontal > .el-sub-menu.is-active .el-submenu__title { |
| | | border-bottom: 2px solid #{'var(--theme)'} !important; |
| | | color: #303133; |
| | | } |
| | |
| | | } |
| | | |
| | | /* èæ¯è²éè */ |
| | | .topmenu-container.el-menu--horizontal>.el-menu-item:not(.is-disabled):focus, .topmenu-container.el-menu--horizontal>.el-menu-item:not(.is-disabled):hover, .topmenu-container.el-menu--horizontal>.el-submenu .el-submenu__title:hover { |
| | | .topmenu-container.el-menu--horizontal > .el-menu-item:not(.is-disabled):focus, |
| | | .topmenu-container.el-menu--horizontal > .el-menu-item:not(.is-disabled):hover, |
| | | .topmenu-container.el-menu--horizontal > .el-submenu .el-submenu__title:hover { |
| | | background-color: #ffffff !important; |
| | | } |
| | | |
| | |
| | | <template> |
| | | <div class="el-tree-select"> |
| | | <el-select |
| | | style="width: 100%" |
| | | v-model="valueId" |
| | | ref="treeSelect" |
| | | v-model="valueId" |
| | | style="width: 100%" |
| | | :filterable="true" |
| | | :clearable="true" |
| | | @clear="clearHandle" |
| | | :filter-method="selectFilterData" |
| | | :placeholder="placeholder" |
| | | @clear="clearHandle" |
| | | > |
| | | <el-option :value="valueId" :label="valueTitle"> |
| | | <el-tree |
| | |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | interface ObjMap { |
| | | value: string; |
| | | label: string; |
| | | children: string; |
| | | } |
| | | interface Props { |
| | | objMap: ObjMap; |
| | | accordion: boolean; |
| | | value: string | number; |
| | | options: any[]; |
| | | placeholder: string; |
| | | } |
| | | |
| | | const props = defineProps({ |
| | | /* é
置项 */ |
| | | objMap: { |
| | | type: Object, |
| | | default: () => { |
| | | return { |
| | | value: 'id', // IDåæ®µå |
| | | label: 'label', // æ¾ç¤ºåç§° |
| | | children: 'children' // åçº§åæ®µå |
| | | } |
| | | } |
| | | const props = withDefaults(defineProps<Props>(), { |
| | | objMap: () => { |
| | | return { |
| | | value: 'id', |
| | | label: 'label', |
| | | children: 'children' |
| | | }; |
| | | }, |
| | | /* èªå¨æ¶èµ· */ |
| | | accordion: { |
| | | type: Boolean, |
| | | default: () => { |
| | | return false |
| | | } |
| | | }, |
| | | /**å½åååæ°æ®ç»å®çå¼ */ |
| | | value: { |
| | | type: [String, Number], |
| | | default: '' |
| | | }, |
| | | /**å½åçæ°æ® */ |
| | | options: { |
| | | type: Array, |
| | | default: () => [] |
| | | }, |
| | | /**è¾å
¥æ¡å
é¨çæå */ |
| | | placeholder: { |
| | | type: String, |
| | | default: '' |
| | | } |
| | | }) |
| | | |
| | | accordion: false, |
| | | value: '', |
| | | options: () => [], |
| | | placeholder: '' |
| | | }); |
| | | |
| | | const selectTree = ref<ElTreeSelectInstance>(); |
| | | |
| | |
| | | const valueId = computed({ |
| | | get: () => props.value, |
| | | set: (val) => { |
| | | emit('update:value', val) |
| | | emit('update:value', val); |
| | | } |
| | | }); |
| | | const valueTitle = ref(''); |
| | |
| | | const initHandle = () => { |
| | | nextTick(() => { |
| | | const selectedValue = valueId.value; |
| | | if (selectedValue !== null && typeof (selectedValue) !== 'undefined') { |
| | | const node = selectTree.value?.getNode(selectedValue) |
| | | if (selectedValue !== null && typeof selectedValue !== 'undefined') { |
| | | const node = selectTree.value?.getNode(selectedValue); |
| | | if (node) { |
| | | valueTitle.value = node.data[props.objMap.label] |
| | | selectTree.value?.setCurrentKey(selectedValue) // 设置é»è®¤éä¸ |
| | | defaultExpandedKey.value = [selectedValue] // 设置é»è®¤å±å¼ |
| | | valueTitle.value = node.data[props.objMap.label]; |
| | | selectTree.value?.setCurrentKey(selectedValue); // 设置é»è®¤éä¸ |
| | | defaultExpandedKey.value = [selectedValue]; // 设置é»è®¤å±å¼ |
| | | } |
| | | } else { |
| | | clearHandle() |
| | | clearHandle(); |
| | | } |
| | | }) |
| | | } |
| | | }); |
| | | }; |
| | | const handleNodeClick = (node: any) => { |
| | | valueTitle.value = node[props.objMap.label] |
| | | valueTitle.value = node[props.objMap.label]; |
| | | valueId.value = node[props.objMap.value]; |
| | | defaultExpandedKey.value = []; |
| | | selectTree.value?.blur() |
| | | selectFilterData('') |
| | | } |
| | | selectTree.value?.blur(); |
| | | selectFilterData(''); |
| | | }; |
| | | const selectFilterData = (val: any) => { |
| | | selectTree.value?.filter(val) |
| | | } |
| | | selectTree.value?.filter(val); |
| | | }; |
| | | const filterNode = (value: any, data: any) => { |
| | | if (!value) return true |
| | | return data[props.objMap['label']].indexOf(value) !== -1 |
| | | } |
| | | if (!value) return true; |
| | | return data[props.objMap['label']].indexOf(value) !== -1; |
| | | }; |
| | | const clearHandle = () => { |
| | | valueTitle.value = '' |
| | | valueId.value = '' |
| | | valueTitle.value = ''; |
| | | valueId.value = ''; |
| | | defaultExpandedKey.value = []; |
| | | clearSelected() |
| | | } |
| | | clearSelected(); |
| | | }; |
| | | const clearSelected = () => { |
| | | const allNode = document.querySelectorAll('#tree-option .el-tree-node') |
| | | allNode.forEach((element) => element.classList.remove('is-current')) |
| | | } |
| | | const allNode = document.querySelectorAll('#tree-option .el-tree-node'); |
| | | allNode.forEach((element) => element.classList.remove('is-current')); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | initHandle() |
| | | }) |
| | | initHandle(); |
| | | }); |
| | | |
| | | watch(valueId, () => { |
| | | initHandle(); |
| | | }) |
| | | }); |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | @import "@/assets/styles/variables.module.scss"; |
| | | @import '@/assets/styles/variables.module.scss'; |
| | | |
| | | .el-scrollbar .el-scrollbar__view .el-select-dropdown__item { |
| | | padding: 0; |
| | |
| | | |
| | | const props = defineProps({ |
| | | src: propTypes.string.isRequired |
| | | }) |
| | | }); |
| | | |
| | | const height = ref(document.documentElement.clientHeight - 94.5 + "px;") |
| | | const loading = ref(true) |
| | | const url = computed(() => props.src) |
| | | const height = ref(document.documentElement.clientHeight - 94.5 + 'px;'); |
| | | const loading = ref(true); |
| | | const url = computed(() => props.src); |
| | | |
| | | onMounted(() => { |
| | | setTimeout(() => { |
| | | loading.value = false; |
| | | }, 300); |
| | | window.onresize = function temp() { |
| | | height.value = document.documentElement.clientHeight - 94.5 + "px;"; |
| | | height.value = document.documentElement.clientHeight - 94.5 + 'px;'; |
| | | }; |
| | | }) |
| | | }); |
| | | </script> |
| | |
| | | // ãå
¶ä»è§è²ãæé®æéæ ¡éª |
| | | const { value } = binding; |
| | | if (value && value instanceof Array && value.length > 0) { |
| | | const hasPermission = permissions.some((permi) => { |
| | | const hasPermission = permissions.some((permi: string) => { |
| | | return permi === '*:*:*' || value.includes(permi); |
| | | }); |
| | | if (!hasPermission) { |
| | |
| | | const { value } = binding; |
| | | const { roles } = useUserStore(); |
| | | if (value && value instanceof Array && value.length > 0) { |
| | | const hasRole = roles.some((role) => { |
| | | const hasRole = roles.some((role: string) => { |
| | | return role === 'admin' || value.includes(role); |
| | | }); |
| | | if (!hasRole) { |
| | |
| | | <router-view v-slot="{ Component, route }"> |
| | | <transition :enter-active-class="animante" mode="out-in"> |
| | | <keep-alive :include="tagsViewStore.cachedViews"> |
| | | <component v-if="!route.meta.link" :is="Component" :key="route.path" /> |
| | | <component :is="Component" v-if="!route.meta.link" :key="route.path" /> |
| | | </keep-alive> |
| | | </transition> |
| | | </router-view> |
| | |
| | | <script setup name="AppMain" lang="ts"> |
| | | import useTagsViewStore from '@/store/modules/tagsView'; |
| | | import useSettingsStore from '@/store/modules/settings'; |
| | | import IframeToggle from './IframeToggle/index.vue' |
| | | import { ComponentInternalInstance } from "vue"; |
| | | import IframeToggle from './IframeToggle/index.vue'; |
| | | const { proxy } = getCurrentInstance() as ComponentInternalInstance; |
| | | const tagsViewStore = useTagsViewStore(); |
| | | |
| | | // éæºå¨ç»éå |
| | | const animante = ref<string>(''); |
| | | const animationEnable = ref(useSettingsStore().animationEnable); |
| | | watch(()=> useSettingsStore().animationEnable, (val) => { |
| | | watch( |
| | | () => useSettingsStore().animationEnable, |
| | | (val) => { |
| | | animationEnable.value = val; |
| | | if (val) { |
| | | animante.value = proxy?.animate.animateList[Math.round(Math.random() * proxy?.animate.animateList.length)] as string; |
| | | animante.value = proxy?.animate.animateList[Math.round(Math.random() * proxy?.animate.animateList.length)] as string; |
| | | } else { |
| | | animante.value = proxy?.animate.defaultAnimate as string; |
| | | animante.value = proxy?.animate.defaultAnimate as string; |
| | | } |
| | | }, { immediate: true }); |
| | | }, |
| | | { immediate: true } |
| | | ); |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | |
| | | overflow: hidden; |
| | | } |
| | | |
| | | .fixed-header+.app-main { |
| | | .fixed-header + .app-main { |
| | | padding-top: 50px; |
| | | } |
| | | |
| | |
| | | min-height: calc(100vh - 84px); |
| | | } |
| | | |
| | | .fixed-header+.app-main { |
| | | .fixed-header + .app-main { |
| | | padding-top: 84px; |
| | | } |
| | | } |
| | |
| | | <transition-group name="fade-transform" mode="out-in"> |
| | | <inner-link |
| | | v-for="(item, index) in tagsViewStore.iframeViews" |
| | | :key="item.path" |
| | | :iframeId="'iframe' + index" |
| | | v-show="route.path === item.path" |
| | | :key="item.path" |
| | | :iframe-id="'iframe' + index" |
| | | :src="iframeUrl(item.meta ? item.meta.link : '', item.query)" |
| | | ></inner-link> |
| | | </transition-group> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import InnerLink from "../InnerLink/index.vue"; |
| | | import InnerLink from '../InnerLink/index.vue'; |
| | | import useTagsViewStore from '@/store/modules/tagsView'; |
| | | |
| | | const route = useRoute(); |
| | |
| | | |
| | | function iframeUrl(url: string, query: any) { |
| | | if (Object.keys(query).length > 0) { |
| | | let params = Object.keys(query).map((key) => key + "=" + query[key]).join("&"); |
| | | return url + "?" + params; |
| | | let params = Object.keys(query) |
| | | .map((key) => key + '=' + query[key]) |
| | | .join('&'); |
| | | return url + '?' + params; |
| | | } |
| | | return url; |
| | | } |
| | |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import { propTypes } from '@/utils/propTypes'; |
| | | |
| | | const props = defineProps({ |
| | | src: { |
| | | type: String, |
| | | default: "/" |
| | | }, |
| | | iframeId: { |
| | | type: String |
| | | } |
| | | src: propTypes.string.def('/'), |
| | | iframeId: propTypes.string.isRequired |
| | | }); |
| | | const height = ref(document.documentElement.clientHeight - 94.5 + "px"); |
| | | const height = ref(document.documentElement.clientHeight - 94.5 + 'px'); |
| | | </script> |
| | |
| | | <template> |
| | | <div class="navbar"> |
| | | <hamburger id="hamburger-container" :is-active="appStore.sidebar.opened" class="hamburger-container" @toggleClick="toggleSideBar" /> |
| | | <breadcrumb id="breadcrumb-container" class="breadcrumb-container" v-if="!settingsStore.topNav" /> |
| | | <top-nav id="topmenu-container" class="topmenu-container" v-if="settingsStore.topNav" /> |
| | | <hamburger id="hamburger-container" :is-active="appStore.sidebar.opened" class="hamburger-container" @toggle-click="toggleSideBar" /> |
| | | <breadcrumb v-if="!settingsStore.topNav" id="breadcrumb-container" class="breadcrumb-container" /> |
| | | <top-nav v-if="settingsStore.topNav" id="topmenu-container" class="topmenu-container" /> |
| | | |
| | | <div class="right-menu flex align-center"> |
| | | <template v-if="appStore.device !== 'mobile'"> |
| | | <el-select |
| | | v-if="userId === 1 && tenantEnabled" |
| | | v-model="companyName" |
| | | clearable |
| | | filterable |
| | | reserve-keyword |
| | | :placeholder="$t('navbar.selectTenant')" |
| | | v-if="userId === 1 && tenantEnabled" |
| | | @change="dynamicTenantEvent" |
| | | @clear="dynamicClearEvent" |
| | | > |
| | |
| | | </el-tooltip> |
| | | </template> |
| | | <div class="avatar-container"> |
| | | <el-dropdown @command="handleCommand" class="right-menu-item hover-effect" trigger="click"> |
| | | <el-dropdown class="right-menu-item hover-effect" trigger="click" @command="handleCommand"> |
| | | <div class="avatar-wrapper"> |
| | | <img :src="userStore.avatar" class="user-avatar" /> |
| | | <el-icon><caret-bottom /></el-icon> |
| | | </div> |
| | | <template #dropdown> |
| | | <el-dropdown-menu> |
| | | <router-link to="/user/profile" v-if="!dynamic"> |
| | | <router-link v-if="!dynamic" to="/user/profile"> |
| | | <el-dropdown-item>{{ $t('navbar.personalCenter') }}</el-dropdown-item> |
| | | </router-link> |
| | | <el-dropdown-item command="setLayout" v-if="settingsStore.showSettings"> |
| | | <el-dropdown-item v-if="settingsStore.showSettings" command="setLayout"> |
| | | <span>{{ $t('navbar.layoutSetting') }}</span> |
| | | </el-dropdown-item> |
| | | <el-dropdown-item divided command="logout"> |
| | |
| | | import useAppStore from '@/store/modules/app'; |
| | | import useUserStore from '@/store/modules/user'; |
| | | import useSettingsStore from '@/store/modules/settings'; |
| | | import { getTenantList } from "@/api/login"; |
| | | import { dynamicClear, dynamicTenant } from "@/api/system/tenant"; |
| | | import { ComponentInternalInstance } from "vue"; |
| | | import { TenantVO } from "@/api/types"; |
| | | import { getTenantList } from '@/api/login'; |
| | | import { dynamicClear, dynamicTenant } from '@/api/system/tenant'; |
| | | import { TenantVO } from '@/api/types'; |
| | | import notice from './notice/index.vue'; |
| | | import useNoticeStore from '@/store/modules/notice'; |
| | | |
| | |
| | | |
| | | const openSearchMenu = () => { |
| | | searchMenuRef.value?.openSearch(); |
| | | } |
| | | }; |
| | | |
| | | // 卿忢 |
| | | const dynamicTenantEvent = async (tenantId: string) => { |
| | |
| | | proxy?.$tab.closeAllPage(); |
| | | proxy?.$router.push('/'); |
| | | } |
| | | } |
| | | }; |
| | | |
| | | const dynamicClearEvent = async () => { |
| | | await dynamicClear(); |
| | | dynamic.value = false; |
| | | proxy?.$tab.closeAllPage(); |
| | | proxy?.$router.push('/'); |
| | | } |
| | | }; |
| | | |
| | | /** ç§æ·å表 */ |
| | | const initTenantList = async () => { |
| | |
| | | if (tenantEnabled.value) { |
| | | tenantList.value = data.voList; |
| | | } |
| | | } |
| | | }; |
| | | |
| | | defineExpose({ |
| | | initTenantList, |
| | | }) |
| | | initTenantList |
| | | }); |
| | | |
| | | const toggleSideBar = () => { |
| | | appStore.toggleSideBar(false); |
| | | } |
| | | }; |
| | | |
| | | const logout = async () => { |
| | | await ElMessageBox.confirm('ç¡®å®æ³¨éå¹¶éåºç³»ç»åï¼', 'æç¤º', { |
| | | confirmButtonText: 'ç¡®å®', |
| | | cancelButtonText: 'åæ¶', |
| | | type: 'warning' |
| | | }) |
| | | await userStore.logout() |
| | | location.href = import.meta.env.VITE_APP_CONTEXT_PATH + 'index'; |
| | | } |
| | | await ElMessageBox.confirm('ç¡®å®æ³¨éå¹¶éåºç³»ç»åï¼', 'æç¤º', { |
| | | confirmButtonText: 'ç¡®å®', |
| | | cancelButtonText: 'åæ¶', |
| | | type: 'warning' |
| | | }); |
| | | await userStore.logout(); |
| | | location.href = import.meta.env.VITE_APP_CONTEXT_PATH + 'index'; |
| | | }; |
| | | |
| | | const emits = defineEmits(['setLayout']) |
| | | const emits = defineEmits(['setLayout']); |
| | | const setLayout = () => { |
| | | emits('setLayout'); |
| | | } |
| | | emits('setLayout'); |
| | | }; |
| | | // å®ä¹Commandæ¹æ³å¯¹è±¡ éè¿keyç´æ¥è°ç¨æ¹æ³ |
| | | const commandMap: {[key: string]: any} = { |
| | | setLayout, |
| | | logout |
| | | const commandMap: { [key: string]: any } = { |
| | | setLayout, |
| | | logout |
| | | }; |
| | | const handleCommand = (command: string) => { |
| | | // 夿æ¯å¦åå¨è¯¥æ¹æ³ |
| | | if (commandMap[command]) { |
| | | commandMap[command](); |
| | | } |
| | | } |
| | | |
| | | // 夿æ¯å¦åå¨è¯¥æ¹æ³ |
| | | if (commandMap[command]) { |
| | | commandMap[command](); |
| | | } |
| | | }; |
| | | //ç¨æ·±åº¦çå¬ æ¶æ¯ |
| | | watch(() => noticeStore.state.value.notices, (newVal, oldVal) => { |
| | | newNotice.value = newVal.filter((item: any) => !item.read).length; |
| | | }, { deep: true }); |
| | | watch( |
| | | () => noticeStore.state.value.notices, |
| | | (newVal) => { |
| | | newNotice.value = newVal.filter((item: any) => !item.read).length; |
| | | }, |
| | | { deep: true } |
| | | ); |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | |
| | | :deep(.el-select .el-input__wrapper) { |
| | | height:30px; |
| | | height: 30px; |
| | | } |
| | | |
| | | :deep(.el-badge__content.is-fixed){ |
| | | top: 12px; |
| | | :deep(.el-badge__content.is-fixed) { |
| | | top: 12px; |
| | | } |
| | | |
| | | .flex { |
| | |
| | | <template> |
| | | <el-drawer v-model="showSettings" :withHeader="false" direction="rtl" size="300px" close-on-click-modal> |
| | | <el-drawer v-model="showSettings" :with-header="false" direction="rtl" size="300px" close-on-click-modal> |
| | | <h3 class="drawer-title">主é¢é£æ ¼è®¾ç½®</h3> |
| | | |
| | | <div class="setting-drawer-block-checbox"> |
| | | <div class="setting-drawer-block-checbox-item" @click="handleTheme(SideThemeEnum.DARK)"> |
| | | <img src="@/assets/images/dark.svg" alt="dark" /> |
| | | <div v-if="sideTheme === 'theme-dark'" class="setting-drawer-block-checbox-selectIcon" style="display: block;"> |
| | | <div v-if="sideTheme === 'theme-dark'" class="setting-drawer-block-checbox-selectIcon" style="display: block"> |
| | | <i aria-label="徿 : check" class="anticon anticon-check"> |
| | | <svg viewBox="64 64 896 896" data-icon="check" width="1em" height="1em" :fill="theme" aria-hidden="true" focusable="false" class> |
| | | <path |
| | |
| | | </div> |
| | | <div class="setting-drawer-block-checbox-item" @click="handleTheme(SideThemeEnum.LIGHT)"> |
| | | <img src="@/assets/images/light.svg" alt="light" /> |
| | | <div v-if="sideTheme === 'theme-light'" class="setting-drawer-block-checbox-selectIcon" style="display: block;"> |
| | | <div v-if="sideTheme === 'theme-light'" class="setting-drawer-block-checbox-selectIcon" style="display: block"> |
| | | <i aria-label="徿 : check" class="anticon anticon-check"> |
| | | <svg viewBox="64 64 896 896" data-icon="check" width="1em" height="1em" :fill="theme" aria-hidden="true" focusable="false" class> |
| | | <path |
| | |
| | | <div class="drawer-item"> |
| | | <span>æ·±è²æ¨¡å¼</span> |
| | | <span class="comp-style"> |
| | | <el-switch v-model="isDark" @change="toggleDark" class="drawer-switch" /> |
| | | <el-switch v-model="isDark" class="drawer-switch" @change="toggleDark" /> |
| | | </span> |
| | | </div> |
| | | |
| | |
| | | </template> |
| | | |
| | | <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 { handleThemeStyle } from '@/utils/theme' |
| | | import { ComponentInternalInstance } from "vue"; |
| | | import { SettingTypeEnum } from "@/enums/SettingTypeEnum"; |
| | | import { SideThemeEnum } from "@/enums/SideThemeEnum"; |
| | | import { useDynamicTitle } from '@/utils/dynamicTitle'; |
| | | import useAppStore from '@/store/modules/app'; |
| | | import useSettingsStore from '@/store/modules/settings'; |
| | | import usePermissionStore from '@/store/modules/permission'; |
| | | import { handleThemeStyle } from '@/utils/theme'; |
| | | import { SettingTypeEnum } from '@/enums/SettingTypeEnum'; |
| | | import { SideThemeEnum } from '@/enums/SideThemeEnum'; |
| | | |
| | | const { proxy } = getCurrentInstance() as ComponentInternalInstance; |
| | | const appStore = useAppStore() |
| | | const settingsStore = useSettingsStore() |
| | | const permissionStore = usePermissionStore() |
| | | |
| | | const appStore = useAppStore(); |
| | | const settingsStore = useSettingsStore(); |
| | | const permissionStore = usePermissionStore(); |
| | | |
| | | const showSettings = ref(false); |
| | | const theme = ref(settingsStore.theme); |
| | | const sideTheme = ref(settingsStore.sideTheme); |
| | | const storeSettings = computed(() => settingsStore); |
| | | const predefineColors = ref(["#409EFF", "#ff4500", "#ff8c00", "#ffd700", "#90ee90", "#00ced1", "#1e90ff", "#c71585"]); |
| | | const predefineColors = ref(['#409EFF', '#ff4500', '#ff8c00', '#ffd700', '#90ee90', '#00ced1', '#1e90ff', '#c71585']); |
| | | |
| | | // æ¯å¦æé»æ¨¡å¼ |
| | | const isDark = useDark({ |
| | | storageKey: 'useDarkKey', |
| | | valueDark: 'dark', |
| | | valueLight: 'light', |
| | | valueLight: 'light' |
| | | }); |
| | | watch(isDark, ()=> { |
| | | watch(isDark, () => { |
| | | if (isDark.value) { |
| | | settingsStore.changeSetting({ key: SettingTypeEnum.SIDE_THEME, value: SideThemeEnum.DARK }) |
| | | settingsStore.changeSetting({ key: SettingTypeEnum.SIDE_THEME, value: SideThemeEnum.DARK }); |
| | | } else { |
| | | settingsStore.changeSetting({ key: SettingTypeEnum.SIDE_THEME, value: sideTheme.value }) |
| | | settingsStore.changeSetting({ key: SettingTypeEnum.SIDE_THEME, value: sideTheme.value }); |
| | | } |
| | | }) |
| | | }); |
| | | const toggleDark = () => useToggle(isDark); |
| | | |
| | | /** æ¯å¦éè¦topNav */ |
| | | const topNav = computed({ |
| | | get: () => storeSettings.value.topNav, |
| | | set: (val) => { |
| | | settingsStore.changeSetting({ key: SettingTypeEnum.TOP_NAV, value: val }) |
| | | if (!val) { |
| | | appStore.toggleSideBarHide(false); |
| | | permissionStore.setSidebarRouters(permissionStore.defaultRoutes); |
| | | } |
| | | get: () => storeSettings.value.topNav, |
| | | set: (val) => { |
| | | settingsStore.changeSetting({ key: SettingTypeEnum.TOP_NAV, value: val }); |
| | | if (!val) { |
| | | appStore.toggleSideBarHide(false); |
| | | permissionStore.setSidebarRouters(permissionStore.defaultRoutes); |
| | | } |
| | | }) |
| | | } |
| | | }); |
| | | /** æ¯å¦éè¦tagview */ |
| | | const tagsView = computed({ |
| | | get: () => storeSettings.value.tagsView, |
| | | set: (val) => { |
| | | settingsStore.changeSetting({ key: SettingTypeEnum.TAGS_VIEW, value: val }) |
| | | } |
| | | }) |
| | | get: () => storeSettings.value.tagsView, |
| | | set: (val) => { |
| | | settingsStore.changeSetting({ key: SettingTypeEnum.TAGS_VIEW, value: val }); |
| | | } |
| | | }); |
| | | /**æ¯å¦éè¦åºå®å¤´é¨ */ |
| | | const fixedHeader = computed({ |
| | | get: () => storeSettings.value.fixedHeader, |
| | | set: (val) => { |
| | | settingsStore.changeSetting({ key: SettingTypeEnum.FIXED_HEADER, value: val }) |
| | | } |
| | | }) |
| | | get: () => storeSettings.value.fixedHeader, |
| | | set: (val) => { |
| | | settingsStore.changeSetting({ key: SettingTypeEnum.FIXED_HEADER, value: val }); |
| | | } |
| | | }); |
| | | /**æ¯å¦éè¦ä¾§è¾¹æ çlogo */ |
| | | const sidebarLogo = computed({ |
| | | get: () => storeSettings.value.sidebarLogo, |
| | | set: (val) => { |
| | | settingsStore.changeSetting({ key: SettingTypeEnum.SIDEBAR_LOGO, value: val }) |
| | | } |
| | | }) |
| | | get: () => storeSettings.value.sidebarLogo, |
| | | set: (val) => { |
| | | settingsStore.changeSetting({ key: SettingTypeEnum.SIDEBAR_LOGO, value: val }); |
| | | } |
| | | }); |
| | | /**æ¯å¦éè¦ä¾§è¾¹æ ç卿ç½é¡µçtitle */ |
| | | const dynamicTitle = computed({ |
| | | get: () => storeSettings.value.dynamicTitle, |
| | | set: (val) => { |
| | | settingsStore.changeSetting({ key: SettingTypeEnum.DYNAMIC_TITLE, value: val }) |
| | | // å¨æè®¾ç½®ç½é¡µæ é¢ |
| | | useDynamicTitle() |
| | | } |
| | | }) |
| | | get: () => storeSettings.value.dynamicTitle, |
| | | set: (val) => { |
| | | settingsStore.changeSetting({ key: SettingTypeEnum.DYNAMIC_TITLE, value: val }); |
| | | // å¨æè®¾ç½®ç½é¡µæ é¢ |
| | | useDynamicTitle(); |
| | | } |
| | | }); |
| | | |
| | | const themeChange = (val: string | null) => { |
| | | settingsStore.changeSetting({ key: SettingTypeEnum.THEME, value: val }) |
| | | theme.value = val; |
| | | if (val) { |
| | | handleThemeStyle(val); |
| | | } |
| | | } |
| | | const themeChange = (val: string) => { |
| | | settingsStore.changeSetting({ key: SettingTypeEnum.THEME, value: val }); |
| | | theme.value = val; |
| | | if (val) { |
| | | handleThemeStyle(val); |
| | | } |
| | | }; |
| | | const handleTheme = (val: string) => { |
| | | sideTheme.value = val; |
| | | if (isDark.value && val === SideThemeEnum.LIGHT) { |
| | | // æé»æ¨¡å¼é¢è²ä¸å |
| | | settingsStore.changeSetting({ key: SettingTypeEnum.SIDE_THEME, value: SideThemeEnum.DARK }) |
| | | return |
| | | } |
| | | settingsStore.changeSetting({ key: SettingTypeEnum.SIDE_THEME, value: val }) |
| | | } |
| | | sideTheme.value = val; |
| | | if (isDark.value && val === SideThemeEnum.LIGHT) { |
| | | // æé»æ¨¡å¼é¢è²ä¸å |
| | | settingsStore.changeSetting({ key: SettingTypeEnum.SIDE_THEME, value: SideThemeEnum.DARK }); |
| | | return; |
| | | } |
| | | settingsStore.changeSetting({ key: SettingTypeEnum.SIDE_THEME, value: val }); |
| | | }; |
| | | const saveSetting = () => { |
| | | proxy?.$modal.loading("æ£å¨ä¿åå°æ¬å°ï¼è¯·ç¨å..."); |
| | | let layoutSetting = { |
| | | "topNav": storeSettings.value.topNav, |
| | | "tagsView": storeSettings.value.tagsView, |
| | | "fixedHeader": storeSettings.value.fixedHeader, |
| | | "sidebarLogo": storeSettings.value.sidebarLogo, |
| | | "dynamicTitle": storeSettings.value.dynamicTitle, |
| | | "sideTheme": storeSettings.value.sideTheme, |
| | | "theme": storeSettings.value.theme |
| | | }; |
| | | localStorage.setItem("layout-setting", JSON.stringify(layoutSetting)); |
| | | setTimeout(() => {proxy?.$modal.closeLoading()}, 1000) |
| | | } |
| | | proxy?.$modal.loading('æ£å¨ä¿åå°æ¬å°ï¼è¯·ç¨å...'); |
| | | let layoutSetting = { |
| | | topNav: storeSettings.value.topNav, |
| | | tagsView: storeSettings.value.tagsView, |
| | | fixedHeader: storeSettings.value.fixedHeader, |
| | | sidebarLogo: storeSettings.value.sidebarLogo, |
| | | dynamicTitle: storeSettings.value.dynamicTitle, |
| | | sideTheme: storeSettings.value.sideTheme, |
| | | theme: storeSettings.value.theme |
| | | }; |
| | | localStorage.setItem('layout-setting', JSON.stringify(layoutSetting)); |
| | | setTimeout(() => { |
| | | proxy?.$modal.closeLoading(); |
| | | }, 1000); |
| | | }; |
| | | const resetSetting = () => { |
| | | proxy?.$modal.loading("æ£å¨æ¸
é¤è®¾ç½®ç¼åå¹¶å·æ°ï¼è¯·ç¨å..."); |
| | | localStorage.removeItem("layout-setting") |
| | | setTimeout("window.location.reload()", 1000) |
| | | } |
| | | proxy?.$modal.loading('æ£å¨æ¸
é¤è®¾ç½®ç¼åå¹¶å·æ°ï¼è¯·ç¨å...'); |
| | | localStorage.removeItem('layout-setting'); |
| | | setTimeout('window.location.reload()', 1000); |
| | | }; |
| | | const openSetting = () => { |
| | | showSettings.value = true; |
| | | } |
| | | showSettings.value = true; |
| | | }; |
| | | |
| | | defineExpose({ |
| | | openSetting, |
| | | }) |
| | | openSetting |
| | | }); |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import { isExternal } from '@/utils/validate' |
| | | import { isExternal } from '@/utils/validate'; |
| | | |
| | | const props = defineProps({ |
| | | to: { |
| | | type: [String, Object], |
| | | required: true |
| | | } |
| | | }) |
| | | to: { |
| | | type: [String, Object], |
| | | required: true |
| | | } |
| | | }); |
| | | |
| | | const isExt = computed(() => { |
| | | return isExternal(props.to as string) |
| | | }) |
| | | return isExternal(props.to as string); |
| | | }); |
| | | |
| | | const type = computed(() => { |
| | | if (isExt.value) { |
| | | return 'a' |
| | | } |
| | | return 'router-link' |
| | | }) |
| | | if (isExt.value) { |
| | | return 'a'; |
| | | } |
| | | return 'router-link'; |
| | | }); |
| | | |
| | | function linkProps() { |
| | | if (isExt.value) { |
| | | return { |
| | | href: props.to, |
| | | target: '_blank', |
| | | rel: 'noopener' |
| | | } |
| | | } |
| | | if (isExt.value) { |
| | | return { |
| | | to: props.to |
| | | } |
| | | href: props.to, |
| | | target: '_blank', |
| | | rel: 'noopener' |
| | | }; |
| | | } |
| | | return { |
| | | to: props.to |
| | | }; |
| | | } |
| | | </script> |
| | |
| | | <template> |
| | | <div |
| | | class="sidebar-logo-container" |
| | | :class="{ 'collapse': collapse }" |
| | | :class="{ collapse: collapse }" |
| | | :style="{ backgroundColor: sideTheme === 'theme-dark' ? variables.menuBackground : variables.menuLightBackground }" |
| | | > |
| | | <transition :enter-active-class="proxy?.animate.logoAnimate.enter" mode="out-in"> |
| | |
| | | </template> |
| | | |
| | | <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 { ComponentInternalInstance } from "vue"; |
| | | import variables from '@/assets/styles/variables.module.scss'; |
| | | import logo from '@/assets/logo/logo.png'; |
| | | import useSettingsStore from '@/store/modules/settings'; |
| | | const { proxy } = getCurrentInstance() as ComponentInternalInstance; |
| | | |
| | | defineProps({ |
| | | collapse: { |
| | | type: Boolean, |
| | | required: true |
| | | } |
| | | }) |
| | | collapse: { |
| | | type: Boolean, |
| | | required: true |
| | | } |
| | | }); |
| | | |
| | | const title = ref('RuoYi-Vue-Plus'); |
| | | const settingsStore = useSettingsStore(); |
| | |
| | | font-weight: 600; |
| | | line-height: 50px; |
| | | font-size: 14px; |
| | | font-family: Avenir, Helvetica Neue, Arial, Helvetica, sans-serif; |
| | | font-family: |
| | | Avenir, |
| | | Helvetica Neue, |
| | | Arial, |
| | | Helvetica, |
| | | sans-serif; |
| | | vertical-align: middle; |
| | | } |
| | | } |
| | |
| | | |
| | | <el-sub-menu v-else ref="subMenu" :index="resolvePath(item.path)" teleported> |
| | | <template v-if="item.meta" #title> |
| | | <svg-icon :icon-class="item.meta ? item.meta.icon : '' " /> |
| | | <svg-icon :icon-class="item.meta ? item.meta.icon : ''" /> |
| | | <span class="menu-title" :title="hasTitle(item.meta?.title)">{{ item.meta?.title }}</span> |
| | | </template> |
| | | |
| | |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import { isExternal } from '@/utils/validate' |
| | | import AppLink from './Link.vue' |
| | | import { getNormalPath } from '@/utils/ruoyi' |
| | | import { RouteOption } from "vue-router"; |
| | | import { isExternal } from '@/utils/validate'; |
| | | import AppLink from './Link.vue'; |
| | | import { getNormalPath } from '@/utils/ruoyi'; |
| | | import { RouteRecordRaw } from 'vue-router'; |
| | | |
| | | const props = defineProps({ |
| | | // route object |
| | | item: { |
| | | type: Object as PropType<RouteOption>, |
| | | required: true |
| | | }, |
| | | isNest: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | basePath: { |
| | | type: String, |
| | | default: '' |
| | | } |
| | | }) |
| | | // route object |
| | | item: { |
| | | type: Object as PropType<RouteRecordRaw>, |
| | | required: true |
| | | }, |
| | | isNest: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | basePath: { |
| | | type: String, |
| | | default: '' |
| | | } |
| | | }); |
| | | |
| | | const onlyOneChild = ref<any>({}); |
| | | |
| | | const hasOneShowingChild = (parent: RouteOption, children?:RouteOption[]) => { |
| | | if (!children) { |
| | | children = []; |
| | | const hasOneShowingChild = (parent: RouteRecordRaw, children?: RouteRecordRaw[]) => { |
| | | if (!children) { |
| | | children = []; |
| | | } |
| | | const showingChildren = children.filter((item) => { |
| | | if (item.hidden) { |
| | | return false; |
| | | } else { |
| | | // Temp set(will be used if only has one showing child) |
| | | onlyOneChild.value = item; |
| | | return true; |
| | | } |
| | | const showingChildren = children.filter(item => { |
| | | if (item.hidden) { |
| | | return false |
| | | } else { |
| | | // Temp set(will be used if only has one showing child) |
| | | onlyOneChild.value = item |
| | | return true |
| | | } |
| | | }) |
| | | }); |
| | | |
| | | // When there is only one child router, the child router is displayed by default |
| | | if (showingChildren.length === 1) { |
| | | return true |
| | | } |
| | | // When there is only one child router, the child router is displayed by default |
| | | if (showingChildren.length === 1) { |
| | | return true; |
| | | } |
| | | |
| | | // Show parent if there are no child router to display |
| | | if (showingChildren.length === 0) { |
| | | onlyOneChild.value = { ...parent, path: '', noShowingChildren: true } |
| | | if (parent.name === '2222') { |
| | | console.log(onlyOneChild.value) |
| | | } |
| | | return true |
| | | } |
| | | // Show parent if there are no child router to display |
| | | if (showingChildren.length === 0) { |
| | | onlyOneChild.value = { ...parent, path: '', noShowingChildren: true }; |
| | | return true; |
| | | } |
| | | |
| | | |
| | | return false |
| | | return false; |
| | | }; |
| | | |
| | | const resolvePath = (routePath:string, routeQuery?:string): any => { |
| | | if (isExternal(routePath)) { |
| | | return routePath |
| | | } |
| | | if (isExternal(props.basePath)) { |
| | | return props.basePath |
| | | } |
| | | if (routeQuery) { |
| | | let query = JSON.parse(routeQuery); |
| | | return { path: getNormalPath(props.basePath + '/' + routePath), query: query } |
| | | } |
| | | return getNormalPath(props.basePath + '/' + routePath) |
| | | } |
| | | const resolvePath = (routePath: string, routeQuery?: string): any => { |
| | | if (isExternal(routePath)) { |
| | | return routePath; |
| | | } |
| | | if (isExternal(props.basePath)) { |
| | | return props.basePath; |
| | | } |
| | | if (routeQuery) { |
| | | let query = JSON.parse(routeQuery); |
| | | return { path: getNormalPath(props.basePath + '/' + routePath), query: query }; |
| | | } |
| | | return getNormalPath(props.basePath + '/' + routePath); |
| | | }; |
| | | |
| | | const hasTitle = (title: string | undefined): string => { |
| | | if(!title || title.length <= 5) { |
| | | return ""; |
| | | } |
| | | return title; |
| | | } |
| | | if (!title || title.length <= 5) { |
| | | return ''; |
| | | } |
| | | return title; |
| | | }; |
| | | </script> |
| | |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | 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 { RouteOption } from "vue-router"; |
| | | 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 { RouteRecordRaw } from 'vue-router'; |
| | | const { proxy } = getCurrentInstance() as ComponentInternalInstance; |
| | | |
| | | const route = useRoute(); |
| | | const appStore = useAppStore() |
| | | const settingsStore = useSettingsStore() |
| | | const permissionStore = usePermissionStore() |
| | | |
| | | const sidebarRouters = computed<RouteOption[]>(() => permissionStore.sidebarRouters); |
| | | const appStore = useAppStore(); |
| | | const settingsStore = useSettingsStore(); |
| | | const permissionStore = usePermissionStore(); |
| | | const sidebarRouters = computed<RouteRecordRaw[]>(() => permissionStore.sidebarRouters); |
| | | const showLogo = computed(() => settingsStore.sidebarLogo); |
| | | const sideTheme = computed(() => settingsStore.sideTheme); |
| | | const theme = computed(() => settingsStore.theme); |
| | | const isCollapse = computed(() => !appStore.sidebar.opened); |
| | | |
| | | const activeMenu = computed(() => { |
| | | const { meta, path } = route; |
| | | // if set path, the sidebar will highlight the path you set |
| | | if (meta.activeMenu) { |
| | | return meta.activeMenu; |
| | | } |
| | | return path; |
| | | }) |
| | | const { meta, path } = route; |
| | | // if set path, the sidebar will highlight the path you set |
| | | if (meta.activeMenu) { |
| | | return meta.activeMenu; |
| | | } |
| | | return path; |
| | | }); |
| | | |
| | | const bgColor = computed(() => sideTheme.value === 'theme-dark' ? variables.menuBackground : variables.menuLightBackground); |
| | | const textColor = computed(() => sideTheme.value === 'theme-dark' ? variables.menuColor : variables.menuLightColor); |
| | | const bgColor = computed(() => (sideTheme.value === 'theme-dark' ? variables.menuBackground : variables.menuLightBackground)); |
| | | const textColor = computed(() => (sideTheme.value === 'theme-dark' ? variables.menuColor : variables.menuLightColor)); |
| | | </script> |
| | |
| | | const route = useRoute(); |
| | | const loading = ref(true); |
| | | |
| | | |
| | | /** |
| | | * æ¥æ¶Routeä¼ éçåæ° |
| | | * @param {Object} route.query. |
| | |
| | | const code = route.query.code as string; |
| | | const state = route.query.state as string; |
| | | const source = route.query.source as string; |
| | | const tenantId = localStorage.getItem("tenantId") ? localStorage.getItem("tenantId") as string : '000000'; |
| | | |
| | | const tenantId = localStorage.getItem('tenantId') ? (localStorage.getItem('tenantId') as string) : '000000'; |
| | | |
| | | const processResponse = async (res: any) => { |
| | | if (res.code !== 200) { |
| | |
| | | }; |
| | | |
| | | const loginByCode = async (data: LoginData) => { |
| | | console.log(2) |
| | | try { |
| | | const res = await login(data); |
| | | await processResponse(res); |
| | |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import useTagsViewStore from '@/store/modules/tagsView' |
| | | import { TagView } from 'vue-router' |
| | | import useTagsViewStore from '@/store/modules/tagsView'; |
| | | import { TagView } from 'vue-router'; |
| | | const tagAndTagSpacing = ref(4); |
| | | |
| | | const scrollContainerRef = ref<ElScrollbarInstance>() |
| | | const scrollContainerRef = ref<ElScrollbarInstance>(); |
| | | const scrollWrapper = computed(() => scrollContainerRef.value?.$refs.wrapRef as any); |
| | | |
| | | onMounted(() => { |
| | | scrollWrapper.value?.addEventListener('scroll', emitScroll, true) |
| | | }) |
| | | scrollWrapper.value?.addEventListener('scroll', emitScroll, true); |
| | | }); |
| | | onBeforeUnmount(() => { |
| | | scrollWrapper.value?.removeEventListener('scroll', emitScroll) |
| | | }) |
| | | scrollWrapper.value?.removeEventListener('scroll', emitScroll); |
| | | }); |
| | | |
| | | const handleScroll = (e: WheelEvent) => { |
| | | const eventDelta = (e as any).wheelDelta || - e.deltaY * 40 |
| | | const $scrollWrapper = scrollWrapper.value; |
| | | $scrollWrapper.scrollLeft = $scrollWrapper.scrollLeft + eventDelta / 4 |
| | | } |
| | | const emits = defineEmits(['scroll']) |
| | | const eventDelta = (e as any).wheelDelta || -e.deltaY * 40; |
| | | const $scrollWrapper = scrollWrapper.value; |
| | | $scrollWrapper.scrollLeft = $scrollWrapper.scrollLeft + eventDelta / 4; |
| | | }; |
| | | const emits = defineEmits(['scroll']); |
| | | const emitScroll = () => { |
| | | emits('scroll') |
| | | } |
| | | emits('scroll'); |
| | | }; |
| | | |
| | | const tagsViewStore = useTagsViewStore() |
| | | const tagsViewStore = useTagsViewStore(); |
| | | const visitedViews = computed(() => tagsViewStore.visitedViews); |
| | | |
| | | const moveToTarget = (currentTag: TagView) => { |
| | | const $container = scrollContainerRef.value?.$el |
| | | const $containerWidth = $container.offsetWidth |
| | | const $scrollWrapper = scrollWrapper.value; |
| | | const $container = scrollContainerRef.value?.$el; |
| | | const $containerWidth = $container.offsetWidth; |
| | | const $scrollWrapper = scrollWrapper.value; |
| | | |
| | | let firstTag = null |
| | | let lastTag = null |
| | | let firstTag = null; |
| | | let lastTag = null; |
| | | |
| | | // find first tag and last tag |
| | | if (visitedViews.value.length > 0) { |
| | | firstTag = visitedViews.value[0] |
| | | lastTag = visitedViews.value[visitedViews.value.length - 1] |
| | | // find first tag and last tag |
| | | if (visitedViews.value.length > 0) { |
| | | firstTag = visitedViews.value[0]; |
| | | lastTag = visitedViews.value[visitedViews.value.length - 1]; |
| | | } |
| | | |
| | | if (firstTag === currentTag) { |
| | | $scrollWrapper.scrollLeft = 0; |
| | | } else if (lastTag === currentTag) { |
| | | $scrollWrapper.scrollLeft = $scrollWrapper.scrollWidth - $containerWidth; |
| | | } else { |
| | | const tagListDom: any = document.getElementsByClassName('tags-view-item'); |
| | | const currentIndex = visitedViews.value.findIndex((item) => item === currentTag); |
| | | let prevTag = null; |
| | | let nextTag = null; |
| | | |
| | | for (const k in tagListDom) { |
| | | if (k !== 'length' && Object.hasOwnProperty.call(tagListDom, k)) { |
| | | if (tagListDom[k].dataset.path === visitedViews.value[currentIndex - 1].path) { |
| | | prevTag = tagListDom[k]; |
| | | } |
| | | if (tagListDom[k].dataset.path === visitedViews.value[currentIndex + 1].path) { |
| | | nextTag = tagListDom[k]; |
| | | } |
| | | } |
| | | } |
| | | |
| | | if (firstTag === currentTag) { |
| | | $scrollWrapper.scrollLeft = 0 |
| | | } else if (lastTag === currentTag) { |
| | | $scrollWrapper.scrollLeft = $scrollWrapper.scrollWidth - $containerWidth |
| | | } else { |
| | | const tagListDom: any = document.getElementsByClassName('tags-view-item'); |
| | | const currentIndex = visitedViews.value.findIndex(item => item === currentTag) |
| | | let prevTag = null |
| | | let nextTag = null |
| | | // the tag's offsetLeft after of nextTag |
| | | const afterNextTagOffsetLeft = nextTag.offsetLeft + nextTag.offsetWidth + tagAndTagSpacing.value; |
| | | |
| | | for (const k in tagListDom) { |
| | | if (k !== 'length' && Object.hasOwnProperty.call(tagListDom, k)) { |
| | | if (tagListDom[k].dataset.path === visitedViews.value[currentIndex - 1].path) { |
| | | prevTag = tagListDom[k]; |
| | | } |
| | | if (tagListDom[k].dataset.path === visitedViews.value[currentIndex + 1].path) { |
| | | nextTag = tagListDom[k]; |
| | | } |
| | | } |
| | | } |
| | | |
| | | // the tag's offsetLeft after of nextTag |
| | | const afterNextTagOffsetLeft = nextTag.offsetLeft + nextTag.offsetWidth + tagAndTagSpacing.value |
| | | |
| | | // the tag's offsetLeft before of prevTag |
| | | const beforePrevTagOffsetLeft = prevTag.offsetLeft - tagAndTagSpacing.value |
| | | if (afterNextTagOffsetLeft > $scrollWrapper.scrollLeft + $containerWidth) { |
| | | $scrollWrapper.scrollLeft = afterNextTagOffsetLeft - $containerWidth |
| | | } else if (beforePrevTagOffsetLeft < $scrollWrapper.scrollLeft) { |
| | | $scrollWrapper.scrollLeft = beforePrevTagOffsetLeft |
| | | } |
| | | // the tag's offsetLeft before of prevTag |
| | | const beforePrevTagOffsetLeft = prevTag.offsetLeft - tagAndTagSpacing.value; |
| | | if (afterNextTagOffsetLeft > $scrollWrapper.scrollLeft + $containerWidth) { |
| | | $scrollWrapper.scrollLeft = afterNextTagOffsetLeft - $containerWidth; |
| | | } else if (beforePrevTagOffsetLeft < $scrollWrapper.scrollLeft) { |
| | | $scrollWrapper.scrollLeft = beforePrevTagOffsetLeft; |
| | | } |
| | | } |
| | | } |
| | | }; |
| | | |
| | | defineExpose({ |
| | | moveToTarget, |
| | | }) |
| | | moveToTarget |
| | | }); |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | |
| | | > |
| | | {{ tag.title }} |
| | | <span v-if="!isAffix(tag)" @click.prevent.stop="closeSelectedTag(tag)"> |
| | | <close class="el-icon-close" style="width: 1em; height: 1em;vertical-align: middle;" /> |
| | | <close class="el-icon-close" style="width: 1em; height: 1em; vertical-align: middle" /> |
| | | </span> |
| | | </router-link> |
| | | </scroll-pane> |
| | | <ul v-show="visible" :style="{ left: left + 'px', top: top + 'px' }" class="contextmenu"> |
| | | <li @click="refreshSelectedTag(selectedTag)"><refresh-right style="width: 1em; height: 1em;" /> å·æ°é¡µé¢</li> |
| | | <li v-if="!isAffix(selectedTag)" @click="closeSelectedTag(selectedTag)"><close style="width: 1em; height: 1em;" /> å
³éå½å</li> |
| | | <li @click="closeOthersTags"><circle-close style="width: 1em; height: 1em;" /> å
³éå
¶ä»</li> |
| | | <li v-if="!isFirstView()" @click="closeLeftTags"><back style="width: 1em; height: 1em;" /> å
³é左侧</li> |
| | | <li v-if="!isLastView()" @click="closeRightTags"><right style="width: 1em; height: 1em;" /> å
³éå³ä¾§</li> |
| | | <li @click="closeAllTags(selectedTag)"><circle-close style="width: 1em; height: 1em;" /> å
¨é¨å
³é</li> |
| | | <li @click="refreshSelectedTag(selectedTag)"><refresh-right style="width: 1em; height: 1em" /> å·æ°é¡µé¢</li> |
| | | <li v-if="!isAffix(selectedTag)" @click="closeSelectedTag(selectedTag)"><close style="width: 1em; height: 1em" /> å
³éå½å</li> |
| | | <li @click="closeOthersTags"><circle-close style="width: 1em; height: 1em" /> å
³éå
¶ä»</li> |
| | | <li v-if="!isFirstView()" @click="closeLeftTags"><back style="width: 1em; height: 1em" /> å
³é左侧</li> |
| | | <li v-if="!isLastView()" @click="closeRightTags"><right style="width: 1em; height: 1em" /> å
³éå³ä¾§</li> |
| | | <li @click="closeAllTags(selectedTag)"><circle-close style="width: 1em; height: 1em" /> å
¨é¨å
³é</li> |
| | | </ul> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import ScrollPane from './ScrollPane.vue' |
| | | import { getNormalPath } from '@/utils/ruoyi' |
| | | import useTagsViewStore from "@/store/modules/tagsView"; |
| | | import useSettingsStore from '@/store/modules/settings' |
| | | import usePermissionStore from '@/store/modules/permission' |
| | | import { ComponentInternalInstance } from "vue"; |
| | | import { RouteOption, TagView, RouteLocationRaw } from "vue-router"; |
| | | import ScrollPane from './ScrollPane.vue'; |
| | | import { getNormalPath } from '@/utils/ruoyi'; |
| | | import useTagsViewStore from '@/store/modules/tagsView'; |
| | | import useSettingsStore from '@/store/modules/settings'; |
| | | import usePermissionStore from '@/store/modules/permission'; |
| | | import { RouteRecordRaw, TagView } from 'vue-router'; |
| | | |
| | | const visible = ref(false); |
| | | const top = ref(0); |
| | | const left = ref(0); |
| | | const selectedTag = ref<TagView>({}); |
| | | const affixTags = ref<TagView[]>([]); |
| | | const scrollPaneRef = ref(ScrollPane); |
| | | const scrollPaneRef = ref<InstanceType<typeof ScrollPane>>(); |
| | | |
| | | const { proxy } = getCurrentInstance() as ComponentInternalInstance; |
| | | const route = useRoute(); |
| | |
| | | const theme = computed(() => useSettingsStore().theme); |
| | | |
| | | watch(route, () => { |
| | | addTags(); |
| | | moveToCurrentTag(); |
| | | }) |
| | | addTags(); |
| | | moveToCurrentTag(); |
| | | }); |
| | | watch(visible, (value) => { |
| | | if (value) { |
| | | document.body.addEventListener('click', closeMenu); |
| | | } else { |
| | | document.body.removeEventListener('click', closeMenu); |
| | | } |
| | | }) |
| | | if (value) { |
| | | document.body.addEventListener('click', closeMenu); |
| | | } else { |
| | | document.body.removeEventListener('click', closeMenu); |
| | | } |
| | | }); |
| | | |
| | | const isActive = (r: TagView): boolean => { |
| | | return r.path === route.path; |
| | | } |
| | | return r.path === route.path; |
| | | }; |
| | | const activeStyle = (tag: TagView) => { |
| | | if (!isActive(tag)) return {}; |
| | | return { |
| | | "background-color": theme.value, |
| | | "border-color": theme.value |
| | | }; |
| | | } |
| | | if (!isActive(tag)) return {}; |
| | | return { |
| | | 'background-color': theme.value, |
| | | 'border-color': theme.value |
| | | }; |
| | | }; |
| | | const isAffix = (tag: TagView) => { |
| | | return tag.meta && tag.meta.affix; |
| | | } |
| | | return tag.meta && tag.meta.affix; |
| | | }; |
| | | const isFirstView = () => { |
| | | try { |
| | | return selectedTag.value.fullPath === '/index' || selectedTag.value.fullPath === visitedViews.value[1].fullPath; |
| | | } catch (err) { |
| | | return false; |
| | | } |
| | | } |
| | | try { |
| | | return selectedTag.value.fullPath === '/index' || selectedTag.value.fullPath === visitedViews.value[1].fullPath; |
| | | } catch (err) { |
| | | return false; |
| | | } |
| | | }; |
| | | const isLastView = () => { |
| | | try { |
| | | return selectedTag.value.fullPath === visitedViews.value[visitedViews.value.length - 1].fullPath; |
| | | } catch (err) { |
| | | return false; |
| | | try { |
| | | return selectedTag.value.fullPath === visitedViews.value[visitedViews.value.length - 1].fullPath; |
| | | } catch (err) { |
| | | return false; |
| | | } |
| | | }; |
| | | const filterAffixTags = (routes: RouteRecordRaw[], basePath = '') => { |
| | | let tags: TagView[] = []; |
| | | |
| | | routes.forEach((route) => { |
| | | if (route.meta && route.meta.affix) { |
| | | const tagPath = getNormalPath(basePath + '/' + route.path); |
| | | tags.push({ |
| | | fullPath: tagPath, |
| | | path: tagPath, |
| | | name: route.name as string, |
| | | meta: { ...route.meta } |
| | | }); |
| | | } |
| | | } |
| | | const filterAffixTags = (routes:RouteOption [], basePath = '') => { |
| | | let tags:TagView[] = [] |
| | | routes.forEach(route => { |
| | | if (route.meta && route.meta.affix) { |
| | | const tagPath = getNormalPath(basePath + '/' + route.path); |
| | | tags.push({ |
| | | fullPath: tagPath, |
| | | path: tagPath, |
| | | name: route.name, |
| | | meta: { ...route.meta } |
| | | }) |
| | | } |
| | | if (route.children) { |
| | | const tempTags = filterAffixTags(route.children, route.path); |
| | | if (tempTags.length >= 1) { |
| | | tags = [...tags, ...tempTags]; |
| | | } |
| | | } |
| | | }) |
| | | return tags |
| | | } |
| | | if (route.children) { |
| | | const tempTags = filterAffixTags(route.children, route.path); |
| | | if (tempTags.length >= 1) { |
| | | tags = [...tags, ...tempTags]; |
| | | } |
| | | } |
| | | }); |
| | | return tags; |
| | | }; |
| | | const initTags = () => { |
| | | const res = filterAffixTags(routes.value); |
| | | affixTags.value = res; |
| | | for (const tag of res) { |
| | | // Must have tag name |
| | | if (tag.name) { |
| | | useTagsViewStore().addVisitedView(tag); |
| | | } |
| | | const res = filterAffixTags(routes.value as any); |
| | | affixTags.value = res; |
| | | for (const tag of res) { |
| | | // Must have tag name |
| | | if (tag.name) { |
| | | useTagsViewStore().addVisitedView(tag); |
| | | } |
| | | } |
| | | } |
| | | }; |
| | | const addTags = () => { |
| | | const { name } = route; |
| | | if(route.query.title) { |
| | | route.meta.title = route.query.title; |
| | | } |
| | | if (name) { |
| | | useTagsViewStore().addView(route); |
| | | if (route.meta.link) { |
| | | useTagsViewStore().addIframeView(route); |
| | | } |
| | | } |
| | | return false |
| | | } |
| | | const moveToCurrentTag = () => { |
| | | nextTick(() => { |
| | | for (const r of visitedViews.value) { |
| | | if (r.path === route.path) { |
| | | scrollPaneRef.value.moveToTarget(r); |
| | | // when query is different then update |
| | | if (r.fullPath !== route.fullPath) { |
| | | useTagsViewStore().updateVisitedView(route); |
| | | } |
| | | } |
| | | } |
| | | }) |
| | | } |
| | | const refreshSelectedTag = (view: TagView) => { |
| | | proxy?.$tab.refreshPage(view); |
| | | const { name } = route; |
| | | if (route.query.title) { |
| | | route.meta.title = route.query.title as string; |
| | | } |
| | | if (name) { |
| | | useTagsViewStore().addView(route as any); |
| | | if (route.meta.link) { |
| | | useTagsViewStore().delIframeView(route); |
| | | useTagsViewStore().addIframeView(route as any); |
| | | } |
| | | } |
| | | } |
| | | return false; |
| | | }; |
| | | const moveToCurrentTag = () => { |
| | | nextTick(() => { |
| | | for (const r of visitedViews.value) { |
| | | if (r.path === route.path) { |
| | | scrollPaneRef.value?.moveToTarget(r); |
| | | // when query is different then update |
| | | if (r.fullPath !== route.fullPath) { |
| | | useTagsViewStore().updateVisitedView(route); |
| | | } |
| | | } |
| | | } |
| | | }); |
| | | }; |
| | | const refreshSelectedTag = (view: TagView) => { |
| | | proxy?.$tab.refreshPage(view); |
| | | if (route.meta.link) { |
| | | useTagsViewStore().delIframeView(route as any); |
| | | } |
| | | }; |
| | | const closeSelectedTag = (view: TagView) => { |
| | | proxy?.$tab.closePage(view).then(({ visitedViews }: any) => { |
| | | if (isActive(view)) { |
| | | toLastView(visitedViews, view); |
| | | } |
| | | }) |
| | | } |
| | | proxy?.$tab.closePage(view).then(({ visitedViews }: any) => { |
| | | if (isActive(view)) { |
| | | toLastView(visitedViews, view); |
| | | } |
| | | }); |
| | | }; |
| | | const closeRightTags = () => { |
| | | proxy?.$tab.closeRightPage(selectedTag.value).then(visitedViews => { |
| | | if (!visitedViews.find(i => i.fullPath === route.fullPath)) { |
| | | toLastView(visitedViews); |
| | | } |
| | | }) |
| | | } |
| | | proxy?.$tab.closeRightPage(selectedTag.value).then((visitedViews) => { |
| | | if (!visitedViews.find((i) => i.fullPath === route.fullPath)) { |
| | | toLastView(visitedViews); |
| | | } |
| | | }); |
| | | }; |
| | | const closeLeftTags = () => { |
| | | proxy?.$tab.closeLeftPage(selectedTag.value).then(visitedViews => { |
| | | if (!visitedViews.find(i => i.fullPath === route.fullPath)) { |
| | | toLastView(visitedViews); |
| | | } |
| | | }) |
| | | } |
| | | proxy?.$tab.closeLeftPage(selectedTag.value).then((visitedViews) => { |
| | | if (!visitedViews.find((i: TagView) => i.fullPath === route.fullPath)) { |
| | | toLastView(visitedViews); |
| | | } |
| | | }); |
| | | }; |
| | | const closeOthersTags = () => { |
| | | router.push(selectedTag.value as RouteLocationRaw).catch(() => { }); |
| | | proxy?.$tab.closeOtherPage(selectedTag.value).then(() => { |
| | | moveToCurrentTag(); |
| | | }) |
| | | } |
| | | router.push(selectedTag.value).catch(() => {}); |
| | | proxy?.$tab.closeOtherPage(selectedTag.value).then(() => { |
| | | moveToCurrentTag(); |
| | | }); |
| | | }; |
| | | const closeAllTags = (view: TagView) => { |
| | | proxy?.$tab.closeAllPage().then(({ visitedViews }) => { |
| | | if (affixTags.value.some(tag => tag.path === route.path)) { |
| | | return; |
| | | } |
| | | toLastView(visitedViews, view); |
| | | }) |
| | | } |
| | | const toLastView = (visitedViews:TagView[], view?: TagView) => { |
| | | const latestView = visitedViews.slice(-1)[0]; |
| | | if (latestView) { |
| | | router.push(latestView.fullPath as string); |
| | | } else { |
| | | // now the default is to redirect to the home page if there is no tags-view, |
| | | // you can adjust it according to your needs. |
| | | if (view?.name === 'Dashboard') { |
| | | // to reload home page |
| | | router.replace({ path: '/redirect' + view?.fullPath }); |
| | | } else { |
| | | router.push('/'); |
| | | } |
| | | proxy?.$tab.closeAllPage().then(({ visitedViews }) => { |
| | | if (affixTags.value.some((tag) => tag.path === route.path)) { |
| | | return; |
| | | } |
| | | } |
| | | toLastView(visitedViews, view); |
| | | }); |
| | | }; |
| | | const toLastView = (visitedViews: TagView[], view?: TagView) => { |
| | | const latestView = visitedViews.slice(-1)[0]; |
| | | if (latestView) { |
| | | router.push(latestView.fullPath as string); |
| | | } else { |
| | | // now the default is to redirect to the home page if there is no tags-view, |
| | | // you can adjust it according to your needs. |
| | | if (view?.name === 'Dashboard') { |
| | | // to reload home page |
| | | router.replace({ path: '/redirect' + view?.fullPath }); |
| | | } else { |
| | | router.push('/'); |
| | | } |
| | | } |
| | | }; |
| | | const openMenu = (tag: TagView, e: MouseEvent) => { |
| | | const menuMinWidth = 105; |
| | | const offsetLeft = proxy?.$el.getBoundingClientRect().left; // container margin left |
| | | const offsetWidth = proxy?.$el.offsetWidth; // container width |
| | | const maxLeft = offsetWidth - menuMinWidth; // left boundary |
| | | const l = e.clientX - offsetLeft + 15; // 15: margin right |
| | | const menuMinWidth = 105; |
| | | const offsetLeft = proxy?.$el.getBoundingClientRect().left; // container margin left |
| | | const offsetWidth = proxy?.$el.offsetWidth; // container width |
| | | const maxLeft = offsetWidth - menuMinWidth; // left boundary |
| | | const l = e.clientX - offsetLeft + 15; // 15: margin right |
| | | |
| | | if (l > maxLeft) { |
| | | left.value = maxLeft; |
| | | } else { |
| | | left.value = l; |
| | | } |
| | | if (l > maxLeft) { |
| | | left.value = maxLeft; |
| | | } else { |
| | | left.value = l; |
| | | } |
| | | |
| | | top.value = e.clientY |
| | | visible.value = true; |
| | | selectedTag.value = tag; |
| | | } |
| | | top.value = e.clientY; |
| | | visible.value = true; |
| | | selectedTag.value = tag; |
| | | }; |
| | | const closeMenu = () => { |
| | | visible.value = false; |
| | | } |
| | | visible.value = false; |
| | | }; |
| | | const handleScroll = () => { |
| | | closeMenu(); |
| | | } |
| | | |
| | | closeMenu(); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | initTags(); |
| | | addTags(); |
| | | }) |
| | | initTags(); |
| | | addTags(); |
| | | }); |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | |
| | | width: 100%; |
| | | background-color: var(--el-bg-color); |
| | | border: 1px solid var(--el-border-color-light); |
| | | box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.12), 0 0 3px 0 rgba(0, 0, 0, 0.04); |
| | | box-shadow: |
| | | 0 1px 3px 0 rgba(0, 0, 0, 0.12), |
| | | 0 0 3px 0 rgba(0, 0, 0, 0.04); |
| | | .tags-view-wrapper { |
| | | .tags-view-item { |
| | | display: inline-block; |
| | |
| | | color: #fff; |
| | | border-color: #42b983; |
| | | &::before { |
| | | content: ""; |
| | | content: ''; |
| | | background: #fff; |
| | | display: inline-block; |
| | | width: 8px; |
| | |
| | | <el-dialog v-model="state.isShowSearch" destroy-on-close :show-close="false"> |
| | | <template #footer> |
| | | <el-autocomplete |
| | | ref="layoutMenuAutocompleteRef" |
| | | v-model="state.menuQuery" |
| | | :fetch-suggestions="menuSearch" |
| | | placeholder="æç´¢" |
| | | ref="layoutMenuAutocompleteRef" |
| | | @select="onHandleSelect" |
| | | :fit-input-width="true" |
| | | @select="onHandleSelect" |
| | | > |
| | | <template #prefix> |
| | | <svg-icon class-name="search-icon" icon-class="search" /> |
| | |
| | | import { getNormalPath } from '@/utils/ruoyi'; |
| | | import { isHttp } from '@/utils/validate'; |
| | | import usePermissionStore from '@/store/modules/permission'; |
| | | import { RouteOption } from 'vue-router'; |
| | | import { RouteRecordRaw } from 'vue-router'; |
| | | type Router = Array<{ |
| | | path: string; |
| | | icon: string; |
| | | title: string[]; |
| | | }> |
| | | path: string; |
| | | icon: string; |
| | | title: string[]; |
| | | }>; |
| | | type SearchState<T = any> = { |
| | | isShowSearch: boolean; |
| | | menuQuery: string; |
| | | menuList: T[]; |
| | | isShowSearch: boolean; |
| | | menuQuery: string; |
| | | menuList: T[]; |
| | | }; |
| | | // å®ä¹åéå
容 |
| | | const layoutMenuAutocompleteRef = ref(); |
| | | const router = useRouter(); |
| | | const routes = computed(() => usePermissionStore().routes); |
| | | const state = reactive<SearchState>({ |
| | | isShowSearch: false, |
| | | menuQuery: '', |
| | | menuList: [], |
| | | isShowSearch: false, |
| | | menuQuery: '', |
| | | menuList: [] |
| | | }); |
| | | |
| | | // æç´¢å¼¹çªæå¼ |
| | | const openSearch = () => { |
| | | state.menuQuery = ''; |
| | | state.isShowSearch = true; |
| | | state.menuList = generateRoutes(routes.value); |
| | | nextTick(() => { |
| | | setTimeout(() => { |
| | | layoutMenuAutocompleteRef.value.focus(); |
| | | }); |
| | | }); |
| | | state.menuQuery = ''; |
| | | state.isShowSearch = true; |
| | | state.menuList = generateRoutes(routes.value); |
| | | nextTick(() => { |
| | | setTimeout(() => { |
| | | layoutMenuAutocompleteRef.value.focus(); |
| | | }); |
| | | }); |
| | | }; |
| | | // æç´¢å¼¹çªå
³é |
| | | const closeSearch = () => { |
| | | state.isShowSearch = false; |
| | | state.isShowSearch = false; |
| | | }; |
| | | // èåæç´¢æ°æ®è¿æ»¤ |
| | | const menuSearch = (queryString: string, cb: Function) => { |
| | | let options = state.menuList.filter((item) => { |
| | | return item.title.indexOf(queryString) > -1; |
| | | }); |
| | | cb(options); |
| | | let options = state.menuList.filter((item) => { |
| | | return item.title.indexOf(queryString) > -1; |
| | | }); |
| | | cb(options); |
| | | }; |
| | | |
| | | // Filter out the routes that can be displayed in the sidebar |
| | | // And generate the internationalized title |
| | | const generateRoutes = (routes: RouteOption[], basePath = '', prefixTitle: string[] = []) => { |
| | | let res: Router = [] |
| | | routes.forEach(r => { |
| | | // skip hidden router |
| | | if (!r.hidden) { |
| | | const p = r.path.length > 0 && r.path[0] === '/' ? r.path : '/' + r.path; |
| | | const data: any = { |
| | | path: !isHttp(r.path) ? getNormalPath(basePath + p) : r.path, |
| | | icon: r.meta?.icon, |
| | | title: [...prefixTitle] |
| | | } |
| | | if (r.meta && r.meta.title) { |
| | | data.title = [...data.title, r.meta.title]; |
| | | if (r.redirect !== 'noRedirect') { |
| | | // only push the routes with title |
| | | // special case: need to exclude parent router without redirect |
| | | res.push(data); |
| | | } |
| | | } |
| | | // recursive child routes |
| | | if (r.children) { |
| | | const tempRoutes = generateRoutes(r.children, data.path, data.title); |
| | | if (tempRoutes.length >= 1) { |
| | | res = [...res, ...tempRoutes]; |
| | | } |
| | | } |
| | | } |
| | | }) |
| | | res.forEach((item: any) => { |
| | | if (item.title instanceof Array) { |
| | | item.title = item.title.join('/'); |
| | | } |
| | | }); |
| | | return res; |
| | | } |
| | | const generateRoutes = (routes: RouteRecordRaw[], basePath = '', prefixTitle: string[] = []) => { |
| | | let res: Router = []; |
| | | routes.forEach((r) => { |
| | | // skip hidden router |
| | | if (!r.hidden) { |
| | | const p = r.path.length > 0 && r.path[0] === '/' ? r.path : '/' + r.path; |
| | | const data: any = { |
| | | path: !isHttp(r.path) ? getNormalPath(basePath + p) : r.path, |
| | | icon: r.meta?.icon, |
| | | title: [...prefixTitle] |
| | | }; |
| | | if (r.meta && r.meta.title) { |
| | | data.title = [...data.title, r.meta.title]; |
| | | if (r.redirect !== 'noRedirect') { |
| | | // only push the routes with title |
| | | // special case: need to exclude parent router without redirect |
| | | res.push(data); |
| | | } |
| | | } |
| | | // recursive child routes |
| | | if (r.children) { |
| | | const tempRoutes = generateRoutes(r.children, data.path, data.title); |
| | | if (tempRoutes.length >= 1) { |
| | | res = [...res, ...tempRoutes]; |
| | | } |
| | | } |
| | | } |
| | | }); |
| | | res.forEach((item: any) => { |
| | | if (item.title instanceof Array) { |
| | | item.title = item.title.join('/'); |
| | | } |
| | | }); |
| | | return res; |
| | | }; |
| | | // å½åèåé䏿¶ |
| | | const onHandleSelect = (val: any) => { |
| | | const paths = val.path; |
| | | if (isHttp(paths)) { |
| | | // http(s):// è·¯å¾æ°çªå£æå¼ |
| | | const pindex = paths.indexOf("http"); |
| | | window.open(paths.substring(pindex, paths.length), "_blank"); |
| | | } else { |
| | | router.push(paths); |
| | | } |
| | | state.menuQuery = '' |
| | | closeSearch(); |
| | | |
| | | const paths = val.path; |
| | | if (isHttp(paths)) { |
| | | // http(s):// è·¯å¾æ°çªå£æå¼ |
| | | const pindex = paths.indexOf('http'); |
| | | window.open(paths.substring(pindex, paths.length), '_blank'); |
| | | } else { |
| | | router.push(paths); |
| | | } |
| | | state.menuQuery = ''; |
| | | closeSearch(); |
| | | }; |
| | | |
| | | // æ´é²åé |
| | | defineExpose({ |
| | | openSearch |
| | | openSearch |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | .layout-search-dialog { |
| | | position: relative; |
| | | :deep(.el-dialog) { |
| | | .el-dialog__header, |
| | | .el-dialog__body { |
| | | display: none; |
| | | } |
| | | .el-dialog__footer { |
| | | width: 100%; |
| | | position: absolute; |
| | | left: 50%; |
| | | transform: translateX(-50%); |
| | | top: -53vh; |
| | | } |
| | | } |
| | | :deep(.el-autocomplete) { |
| | | width: 560px; |
| | | position: absolute; |
| | | top: 150px; |
| | | left: 50%; |
| | | transform: translateX(-50%); |
| | | } |
| | | position: relative; |
| | | :deep(.el-dialog) { |
| | | .el-dialog__header, |
| | | .el-dialog__body { |
| | | display: none; |
| | | } |
| | | .el-dialog__footer { |
| | | width: 100%; |
| | | position: absolute; |
| | | left: 50%; |
| | | transform: translateX(-50%); |
| | | top: -53vh; |
| | | } |
| | | } |
| | | :deep(.el-autocomplete) { |
| | | width: 560px; |
| | | position: absolute; |
| | | top: 150px; |
| | | left: 50%; |
| | | transform: translateX(-50%); |
| | | } |
| | | } |
| | | </style> |
| | |
| | | <template> |
| | | <div class="layout-navbars-breadcrumb-user-news" v-loading="state.loading"> |
| | | <div v-loading="state.loading" class="layout-navbars-breadcrumb-user-news"> |
| | | <div class="head-box"> |
| | | <div class="head-box-title">éç¥å
Œ</div> |
| | | <div class="head-box-btn" @click="readAll">å
¨é¨å·²è¯»</div> |
| | | </div> |
| | | <div class="content-box" v-loading="state.loading"> |
| | | <div v-loading="state.loading" class="content-box"> |
| | | <template v-if="newsList.length > 0"> |
| | | <div class="content-box-item" v-for="(v, k) in newsList" :key="k" @click="onNewsClick(k)"> |
| | | <div v-for="(v, k) in newsList" :key="k" class="content-box-item" @click="onNewsClick(k)"> |
| | | <div class="item-conten"> |
| | | <div>{{ v.message }}</div> |
| | | <div class="content-box-msg"></div> |
| | |
| | | <span v-else class="el-tag el-tag--danger el-tag--mini read">æªè¯»</span> |
| | | </div> |
| | | </template> |
| | | <el-empty :description="'æ¶æ¯ä¸ºç©º'" v-else></el-empty> |
| | | <el-empty v-else :description="'æ¶æ¯ä¸ºç©º'"></el-empty> |
| | | </div> |
| | | <div class="foot-box" @click="onGoToGiteeClick" v-if="newsList.length > 0">åå¾gitee</div> |
| | | <div v-if="newsList.length > 0" class="foot-box" @click="onGoToGiteeClick">åå¾gitee</div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup lang="ts" name="layoutBreadcrumbUserNews"> |
| | | import { ref } from "vue"; |
| | | import { storeToRefs } from 'pinia' |
| | | import { nextTick, onMounted, reactive } from "vue"; |
| | | import { storeToRefs } from 'pinia'; |
| | | import useNoticeStore from '@/store/modules/notice'; |
| | | |
| | | const noticeStore = storeToRefs(useNoticeStore()); |
| | | const {readAll} = useNoticeStore(); |
| | | const { readAll } = useNoticeStore(); |
| | | |
| | | // å®ä¹åéå
容 |
| | | const state = reactive({ |
| | | loading: false, |
| | | loading: false |
| | | }); |
| | | const newsList =ref([]) as any; |
| | | const newsList = ref([]) as any; |
| | | |
| | | /** |
| | | * åå§åæ°æ® |
| | |
| | | state.loading = false; |
| | | }; |
| | | |
| | | |
| | | //ç¹å»æ¶æ¯ï¼åå
¥å·²è¯» |
| | | const onNewsClick = (item: any) => { |
| | | newsList.value[item].read = true; |
| | |
| | | |
| | | // åå¾éç¥ä¸å¿ç¹å» |
| | | const onGoToGiteeClick = () => { |
| | | window.open("https://gitee.com/dromara/RuoYi-Vue-Plus/tree/5.X/"); |
| | | window.open('https://gitee.com/dromara/RuoYi-Vue-Plus/tree/5.X/'); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | |
| | | <settings ref="settingRef" /> |
| | | </el-scrollbar> --> |
| | | <div :class="{ 'fixed-header': fixedHeader }"> |
| | | <navbar ref="navbarRef" @setLayout="setLayout" /> |
| | | <navbar ref="navbarRef" @set-layout="setLayout" /> |
| | | <tags-view v-if="needTagsView" /> |
| | | </div> |
| | | <app-main /> |
| | |
| | | </template> |
| | | |
| | | <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 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'; |
| | | |
| | | const settingsStore = useSettingsStore() |
| | | const settingsStore = useSettingsStore(); |
| | | const theme = computed(() => settingsStore.theme); |
| | | const sidebar = computed(() => useAppStore().sidebar); |
| | | const device = computed(() => useAppStore().device); |
| | |
| | | const fixedHeader = computed(() => settingsStore.fixedHeader); |
| | | |
| | | const classObj = computed(() => ({ |
| | | hideSidebar: !sidebar.value.opened, |
| | | openSidebar: sidebar.value.opened, |
| | | withoutAnimation: sidebar.value.withoutAnimation, |
| | | mobile: device.value === 'mobile' |
| | | })) |
| | | hideSidebar: !sidebar.value.opened, |
| | | openSidebar: sidebar.value.opened, |
| | | withoutAnimation: sidebar.value.withoutAnimation, |
| | | mobile: device.value === 'mobile' |
| | | })); |
| | | |
| | | const { width } = useWindowSize(); |
| | | const WIDTH = 992; // refer to Bootstrap's responsive design |
| | | |
| | | watchEffect(() => { |
| | | if (device.value === 'mobile' && sidebar.value.opened) { |
| | | useAppStore().closeSideBar({ withoutAnimation: false }) |
| | | } |
| | | if (width.value - 1 < WIDTH) { |
| | | useAppStore().toggleDevice('mobile') |
| | | useAppStore().closeSideBar({ withoutAnimation: true }) |
| | | } else { |
| | | useAppStore().toggleDevice('desktop') |
| | | } |
| | | }) |
| | | if (device.value === 'mobile' && sidebar.value.opened) { |
| | | useAppStore().closeSideBar({ withoutAnimation: false }); |
| | | } |
| | | if (width.value - 1 < WIDTH) { |
| | | useAppStore().toggleDevice('mobile'); |
| | | useAppStore().closeSideBar({ withoutAnimation: true }); |
| | | } else { |
| | | useAppStore().toggleDevice('desktop'); |
| | | } |
| | | }); |
| | | |
| | | const navbarRef = ref(Navbar); |
| | | const settingRef = ref(Settings); |
| | | const navbarRef = ref<InstanceType<typeof Navbar>>(); |
| | | const settingRef = ref<InstanceType<typeof Settings>>(); |
| | | |
| | | onMounted(() => { |
| | | nextTick(() => { |
| | | navbarRef.value.initTenantList(); |
| | | }) |
| | | }) |
| | | navbarRef.value?.initTenantList(); |
| | | }); |
| | | }); |
| | | |
| | | const handleClickOutside = () => { |
| | | useAppStore().closeSideBar({ withoutAnimation: false }) |
| | | } |
| | | useAppStore().closeSideBar({ withoutAnimation: false }); |
| | | }; |
| | | |
| | | const setLayout = () => { |
| | | settingRef.value.openSetting(); |
| | | } |
| | | settingRef.value?.openSetting(); |
| | | }; |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | @import "@/assets/styles/mixin.scss"; |
| | | @import "@/assets/styles/variables.module.scss"; |
| | | @import '@/assets/styles/mixin.scss'; |
| | | @import '@/assets/styles/variables.module.scss'; |
| | | |
| | | .app-wrapper { |
| | | @include clearfix; |
| | |
| | | import useUserStore from '@/store/modules/user'; |
| | | import useSettingsStore from '@/store/modules/settings'; |
| | | import usePermissionStore from '@/store/modules/permission'; |
| | | import { RouteRecordRaw } from 'vue-router'; |
| | | |
| | | NProgress.configure({ showSpinner: false }); |
| | | const whiteList = ['/login', '/register', '/social-callback']; |
| | |
| | | isRelogin.show = false; |
| | | const accessRoutes = await usePermissionStore().generateRoutes(); |
| | | // æ ¹æ®rolesæéçæå¯è®¿é®çè·¯ç±è¡¨ |
| | | accessRoutes.forEach((route) => { |
| | | accessRoutes.forEach((route: RouteRecordRaw) => { |
| | | if (!isHttp(route.path)) { |
| | | router.addRoute(route); // å¨ææ·»å å¯è®¿é®è·¯ç±è¡¨ |
| | | } |
| | |
| | | } |
| | | } else { |
| | | // 没ætoken |
| | | if (whiteList.indexOf(to.path) !== -1) { |
| | | if (whiteList.indexOf(to.path as string) !== -1) { |
| | | // å¨å
ç»å½ç½ååï¼ç´æ¥è¿å
¥ |
| | | next(); |
| | | } else { |
| | |
| | | import { useTagsViewStore } from '@/store/modules/tagsView'; |
| | | import router from '@/router'; |
| | | import { TagView, RouteLocationRaw } from 'vue-router'; |
| | | import { TagView, RouteLocationMatched } from 'vue-router'; |
| | | |
| | | export default { |
| | | /** |
| | |
| | | async refreshPage(obj?: TagView): Promise<void> { |
| | | const { path, query, matched } = router.currentRoute.value; |
| | | if (obj === undefined) { |
| | | matched.forEach((m) => { |
| | | matched.forEach((m: RouteLocationMatched) => { |
| | | if (m.components && m.components.default && m.components.default.name) { |
| | | if (!['Layout', 'ParentView'].includes(m.components.default.name)) { |
| | | obj = { name: m.components.default.name, path: path, query: query }; |
| | |
| | | }); |
| | | }, |
| | | // å
³éå½åtab页ç¾ï¼æå¼æ°é¡µç¾ |
| | | closeOpenPage(obj: RouteLocationRaw): void { |
| | | useTagsViewStore().delView(router.currentRoute.value); |
| | | closeOpenPage(obj: TagView): void { |
| | | useTagsViewStore().delView(router.currentRoute.value as any); |
| | | if (obj !== undefined) { |
| | | router.push(obj); |
| | | } |
| | |
| | | async closePage(obj?: TagView): Promise<{ visitedViews: TagView[]; cachedViews: string[] } | any> { |
| | | if (obj === undefined) { |
| | | // prettier-ignore |
| | | const { visitedViews } = await useTagsViewStore().delView(router.currentRoute.value) as any |
| | | const { visitedViews } = await useTagsViewStore().delView(router.currentRoute.value as any) |
| | | const latestView = visitedViews.slice(-1)[0]; |
| | | if (latestView) { |
| | | return router.push(latestView.fullPath); |
| | | return router.push(latestView.fullPath as any); |
| | | } |
| | | return router.push('/'); |
| | | } |
| | |
| | | }, |
| | | // å
³é左侧tabé¡µç¾ |
| | | closeLeftPage(obj?: TagView) { |
| | | return useTagsViewStore().delLeftTags(obj || router.currentRoute.value); |
| | | return useTagsViewStore().delLeftTags(obj || (router.currentRoute.value as any)); |
| | | }, |
| | | // å
³éå³ä¾§tabé¡µç¾ |
| | | closeRightPage(obj?: TagView) { |
| | | return useTagsViewStore().delRightTags(obj || router.currentRoute.value); |
| | | return useTagsViewStore().delRightTags(obj || (router.currentRoute.value as any)); |
| | | }, |
| | | // å
³éå
¶ä»tabé¡µç¾ |
| | | closeOtherPage(obj?: TagView) { |
| | | return useTagsViewStore().delOthersViews(obj || router.currentRoute.value); |
| | | return useTagsViewStore().delOthersViews(obj || (router.currentRoute.value as any)); |
| | | }, |
| | | /** |
| | | * æå¼tabé¡µç¾ |
| | |
| | | import { createWebHistory, createRouter, RouteOption } from 'vue-router'; |
| | | import { createWebHistory, createRouter, RouteRecordRaw } from 'vue-router'; |
| | | /* Layout */ |
| | | import Layout from '@/layout/index.vue'; |
| | | |
| | |
| | | */ |
| | | |
| | | // å
Œ
±è·¯ç± |
| | | export const constantRoutes: RouteOption[] = [ |
| | | export const constantRoutes: RouteRecordRaw[] = [ |
| | | { |
| | | path: '/redirect', |
| | | component: Layout, |
| | |
| | | ]; |
| | | |
| | | // å¨æè·¯ç±ï¼åºäºç¨æ·æé卿å»å è½½ |
| | | export const dynamicRoutes: RouteOption[] = [ |
| | | export const dynamicRoutes: RouteRecordRaw[] = [ |
| | | { |
| | | path: '/system/user-auth', |
| | | component: Layout, |
| | |
| | | |
| | | //å®ç°å
¨é¨å·²è¯» |
| | | const readAll = () => { |
| | | state.notices.forEach((item) => { |
| | | state.notices.forEach((item: any) => { |
| | | item.read = true; |
| | | }); |
| | | }; |
| | |
| | | import router, { constantRoutes, dynamicRoutes } from '@/router'; |
| | | 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 auth from '@/plugins/auth'; |
| | | import { RouteOption } from 'vue-router'; |
| | | |
| | | // å¹é
viewsé颿æç.vueæä»¶ |
| | | const modules = import.meta.glob('./../../views/**/*.vue'); |
| | | |
| | | export const usePermissionStore = defineStore('permission', () => { |
| | | const routes = ref<RouteOption[]>([]); |
| | | const addRoutes = ref<RouteOption[]>([]); |
| | | const defaultRoutes = ref<RouteOption[]>([]); |
| | | const topbarRouters = ref<RouteOption[]>([]); |
| | | const sidebarRouters = ref<RouteOption[]>([]); |
| | | const routes = ref<RouteRecordRaw[]>([]); |
| | | const addRoutes = ref<RouteRecordRaw[]>([]); |
| | | const defaultRoutes = ref<RouteRecordRaw[]>([]); |
| | | const topbarRouters = ref<RouteRecordRaw[]>([]); |
| | | const sidebarRouters = ref<RouteRecordRaw[]>([]); |
| | | |
| | | const setRoutes = (newRoutes: RouteOption[]): void => { |
| | | const setRoutes = (newRoutes: RouteRecordRaw[]): void => { |
| | | addRoutes.value = newRoutes; |
| | | routes.value = constantRoutes.concat(newRoutes); |
| | | }; |
| | | const setDefaultRoutes = (routes: RouteOption[]): void => { |
| | | const setDefaultRoutes = (routes: RouteRecordRaw[]): void => { |
| | | defaultRoutes.value = constantRoutes.concat(routes); |
| | | }; |
| | | const setTopbarRoutes = (routes: RouteOption[]): void => { |
| | | const setTopbarRoutes = (routes: RouteRecordRaw[]): void => { |
| | | topbarRouters.value = routes; |
| | | }; |
| | | const setSidebarRouters = (routes: RouteOption[]): void => { |
| | | const setSidebarRouters = (routes: RouteRecordRaw[]): void => { |
| | | sidebarRouters.value = routes; |
| | | }; |
| | | const generateRoutes = async (): Promise<RouteOption[]> => { |
| | | const generateRoutes = async (): Promise<RouteRecordRaw[]> => { |
| | | const res = await getRouters(); |
| | | const { data } = res; |
| | | const sdata = JSON.parse(JSON.stringify(data)); |
| | |
| | | setSidebarRouters(constantRoutes.concat(sidebarRoutes)); |
| | | setDefaultRoutes(sidebarRoutes); |
| | | setTopbarRoutes(defaultRoutes); |
| | | return new Promise<RouteOption[]>((resolve) => resolve(rewriteRoutes)); |
| | | return new Promise<RouteRecordRaw[]>((resolve) => resolve(rewriteRoutes)); |
| | | }; |
| | | |
| | | /** |
| | |
| | | * @param lastRouter ä¸ä¸çº§è·¯ç± |
| | | * @param type æ¯å¦æ¯éåè·¯ç± |
| | | */ |
| | | const filterAsyncRouter = (asyncRouterMap: RouteOption[], lastRouter?: RouteOption, type = false): RouteOption[] => { |
| | | const filterAsyncRouter = (asyncRouterMap: RouteRecordRaw[], lastRouter?: RouteRecordRaw, type = false): RouteRecordRaw[] => { |
| | | return asyncRouterMap.filter((route) => { |
| | | if (type && route.children) { |
| | | route.children = filterChildren(route.children, undefined); |
| | | } |
| | | if (route.component) { |
| | | // Layout ParentView ç»ä»¶ç¹æ®å¤ç |
| | | if (route.component === 'Layout') { |
| | | route.component = Layout; |
| | | } else if (route.component === 'ParentView') { |
| | | route.component = ParentView; |
| | | } else if (route.component === 'InnerLink') { |
| | | route.component = InnerLink; |
| | | } else { |
| | | route.component = loadView(route.component); |
| | | } |
| | | // Layout ParentView ç»ä»¶ç¹æ®å¤ç |
| | | if (route.component?.toString() === 'Layout') { |
| | | route.component = Layout; |
| | | } else if (route.component?.toString() === 'ParentView') { |
| | | route.component = ParentView; |
| | | } else if (route.component?.toString() === 'InnerLink') { |
| | | route.component = InnerLink; |
| | | } else { |
| | | route.component = loadView(route.component); |
| | | } |
| | | if (route.children != null && route.children && route.children.length) { |
| | | route.children = filterAsyncRouter(route.children, route, type); |
| | |
| | | return true; |
| | | }); |
| | | }; |
| | | const filterChildren = (childrenMap: RouteOption[], lastRouter?: RouteOption): RouteOption[] => { |
| | | let children: RouteOption[] = []; |
| | | const filterChildren = (childrenMap: RouteRecordRaw[], lastRouter?: RouteRecordRaw): RouteRecordRaw[] => { |
| | | let children: RouteRecordRaw[] = []; |
| | | childrenMap.forEach((el) => { |
| | | if (el.children && el.children.length) { |
| | | if (el.component === 'ParentView' && !lastRouter) { |
| | | if (el.component?.toString() === 'ParentView' && !lastRouter) { |
| | | el.children.forEach((c) => { |
| | | c.path = el.path + '/' + c.path; |
| | | if (c.children && c.children.length) { |
| | |
| | | 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(filterChildren(el.children, el)); |
| | | return; |
| | | } |
| | | } |
| | | children = children.concat(el); |
| | |
| | | }); |
| | | |
| | | // å¨æè·¯ç±éåï¼éªè¯æ¯å¦å
·å¤æé |
| | | export const filterDynamicRoutes = (routes: RouteOption[]) => { |
| | | const res: RouteOption[] = []; |
| | | export const filterDynamicRoutes = (routes: RouteRecordRaw[]) => { |
| | | const res: RouteRecordRaw[] = []; |
| | | routes.forEach((route) => { |
| | | if (route.permissions) { |
| | | if (auth.hasPermiOr(route.permissions)) { |
| | |
| | | import defaultSettings from '@/settings'; |
| | | import { SettingTypeEnum } from '@/enums/SettingTypeEnum'; |
| | | import { useDynamicTitle } from '@/utils/dynamicTitle'; |
| | | import { Ref } from 'vue'; |
| | | |
| | | export const useSettingsStore = defineStore('setting', () => { |
| | | const storageSetting = JSON.parse(localStorage.getItem('layout-setting') || '{}'); |
| | | const title = ref<string>(defaultSettings.title); |
| | | const theme = ref<string>(storageSetting.theme || defaultSettings.theme); |
| | | const sideTheme = ref<string>(storageSetting.sideTheme || defaultSettings.sideTheme); |
| | | const showSettings = ref<boolean>(storageSetting.showSettings || defaultSettings.showSettings); |
| | | const topNav = ref<boolean>(storageSetting.topNav === undefined ? defaultSettings.topNav : storageSetting.topNav); |
| | | const tagsView = ref<boolean>(storageSetting.tagsView === undefined ? defaultSettings.tagsView : storageSetting.tagsView); |
| | | const fixedHeader = ref<boolean>(storageSetting.fixedHeader === undefined ? defaultSettings.fixedHeader : storageSetting.fixedHeader); |
| | | const sidebarLogo = ref<boolean>(storageSetting.sidebarLogo === undefined ? defaultSettings.sidebarLogo : storageSetting.sidebarLogo); |
| | | const dynamicTitle = ref<boolean>(storageSetting.dynamicTitle === undefined ? defaultSettings.dynamicTitle : storageSetting.dynamicTitle); |
| | | const animationEnable = ref<boolean>( |
| | | storageSetting.animationEnable === undefined ? defaultSettings.animationEnable : storageSetting.animationEnable |
| | | ); |
| | | const dark = ref<boolean>(storageSetting.dark || defaultSettings.dark); |
| | | |
| | | const prop: { [key: string]: Ref<any> } = { |
| | | title: ref<string>(''), |
| | | theme: ref<string>(storageSetting.theme || defaultSettings.theme), |
| | | sideTheme: ref<string>(storageSetting.sideTheme || defaultSettings.sideTheme), |
| | | showSettings: ref<boolean>(storageSetting.showSettings || defaultSettings.showSettings), |
| | | topNav: ref<boolean>(storageSetting.topNav === undefined ? defaultSettings.topNav : storageSetting.topNav), |
| | | tagsView: ref<boolean>(storageSetting.tagsView === undefined ? defaultSettings.tagsView : storageSetting.tagsView), |
| | | fixedHeader: ref<boolean>(storageSetting.fixedHeader === undefined ? defaultSettings.fixedHeader : storageSetting.fixedHeader), |
| | | sidebarLogo: ref<boolean>(storageSetting.sidebarLogo === undefined ? defaultSettings.sidebarLogo : storageSetting.sidebarLogo), |
| | | dynamicTitle: ref<boolean>(storageSetting.dynamicTitle === undefined ? defaultSettings.dynamicTitle : storageSetting.dynamicTitle), |
| | | animationEnable: ref<boolean>(storageSetting.animationEnable === undefined ? defaultSettings.animationEnable : storageSetting.animationEnable), |
| | | dark: ref<boolean>(storageSetting.dark || defaultSettings.dark) |
| | | theme, |
| | | sideTheme, |
| | | showSettings, |
| | | topNav, |
| | | tagsView, |
| | | fixedHeader, |
| | | sidebarLogo, |
| | | dynamicTitle, |
| | | animationEnable, |
| | | dark |
| | | }; |
| | | |
| | | const { title, theme, sideTheme, showSettings, topNav, tagsView, fixedHeader, sidebarLogo, dynamicTitle, animationEnable, dark } = prop; |
| | | |
| | | // actions |
| | | const changeSetting = (param: { key: SettingTypeEnum; value: any }) => { |
| | |
| | | }; |
| | | |
| | | const addIframeView = (view: TagView): void => { |
| | | if (iframeViews.value.some((v) => v.path === view.path)) return; |
| | | if (iframeViews.value.some((v: TagView) => v.path === view.path)) return; |
| | | iframeViews.value.push( |
| | | Object.assign({}, view, { |
| | | title: view.meta?.title || 'no-name' |
| | |
| | | }; |
| | | const delIframeView = (view: TagView): Promise<TagView[]> => { |
| | | return new Promise((resolve) => { |
| | | iframeViews.value = iframeViews.value.filter((item) => item.path !== view.path); |
| | | iframeViews.value = iframeViews.value.filter((item: TagView) => item.path !== view.path); |
| | | resolve([...iframeViews.value]); |
| | | }); |
| | | }; |
| | | const addVisitedView = (view: TagView): void => { |
| | | if (visitedViews.value.some((v) => v.path === view.path)) return; |
| | | if (visitedViews.value.some((v: TagView) => v.path === view.path)) return; |
| | | visitedViews.value.push( |
| | | Object.assign({}, view, { |
| | | title: view.meta?.title || 'no-name' |
| | |
| | | |
| | | const delOthersVisitedViews = (view: TagView): Promise<TagView[]> => { |
| | | return new Promise((resolve) => { |
| | | visitedViews.value = visitedViews.value.filter((v) => { |
| | | visitedViews.value = visitedViews.value.filter((v: TagView) => { |
| | | return v.meta?.affix || v.path === view.path; |
| | | }); |
| | | resolve([...visitedViews.value]); |
| | |
| | | }; |
| | | const delAllVisitedViews = (): Promise<TagView[]> => { |
| | | return new Promise((resolve) => { |
| | | visitedViews.value = visitedViews.value.filter((tag) => tag.meta?.affix); |
| | | visitedViews.value = visitedViews.value.filter((tag: TagView) => tag.meta?.affix); |
| | | resolve([...visitedViews.value]); |
| | | }); |
| | | }; |
| | |
| | | }); |
| | | }; |
| | | |
| | | const updateVisitedView = (view: TagView): void => { |
| | | const updateVisitedView = (view: TagView | RouteLocationNormalized): void => { |
| | | for (let v of visitedViews.value) { |
| | | if (v.path === view.path) { |
| | | v = Object.assign(v, view); |
| | |
| | | }; |
| | | const delRightTags = (view: TagView): Promise<TagView[]> => { |
| | | return new Promise((resolve) => { |
| | | const index = visitedViews.value.findIndex((v) => v.path === view.path); |
| | | const index = visitedViews.value.findIndex((v: TagView) => v.path === view.path); |
| | | if (index === -1) { |
| | | return; |
| | | } |
| | | visitedViews.value = visitedViews.value.filter((item, idx) => { |
| | | visitedViews.value = visitedViews.value.filter((item: TagView, idx: number) => { |
| | | if (idx <= index || (item.meta && item.meta.affix)) { |
| | | return true; |
| | | } |
| | |
| | | }; |
| | | const delLeftTags = (view: TagView): Promise<TagView[]> => { |
| | | return new Promise((resolve) => { |
| | | const index = visitedViews.value.findIndex((v) => v.path === view.path); |
| | | const index = visitedViews.value.findIndex((v: TagView) => v.path === view.path); |
| | | if (index === -1) { |
| | | return; |
| | | } |
| | | visitedViews.value = visitedViews.value.filter((item, idx) => { |
| | | visitedViews.value = visitedViews.value.filter((item: TagView, idx: number) => { |
| | | if (idx >= index || (item.meta && item.meta.affix)) { |
| | | return true; |
| | | } |
| | |
| | | }); |
| | | }; |
| | | |
| | | const addCachedView = (view: TagView): void => { |
| | | const addCachedView = (view: TagView | RouteLocationNormalized): void => { |
| | | const viewName = view.name as string; |
| | | if (!viewName) return; |
| | | if (cachedViews.value.includes(viewName)) return; |
| | |
| | | import type * as ep from 'element-plus'; |
| | | declare global { |
| | | declare type ElTagType = '' | 'success' | 'warning' | 'info' | 'danger' | 'default' | 'primary'; |
| | | declare type ElFormInstance = InstanceType<typeof ep.ElForm>; |
| | | declare type ElTableInstance = InstanceType<typeof ep.ElTable>; |
| | | declare type ElFormInstance = ep.FormInstance; |
| | | declare type ElTableInstance = ep.TableInstance; |
| | | declare type ElUploadInstance = ep.UploadInstance; |
| | | declare type ElTreeInstance = InstanceType<typeof ep.ElTree>; |
| | | declare type ElTreeSelectInstance = InstanceType<typeof ep.ElTreeSelect>; |
| | | declare type ElSelectInstance = InstanceType<typeof ep.ElSelect>; |
| | | declare type ElUploadInstance = InstanceType<typeof ep.ElUpload>; |
| | | declare type ElCardInstance = InstanceType<typeof ep.ElCard>; |
| | | declare type ElDialogInstance = InstanceType<typeof ep.ElDialog>; |
| | | declare type ElInputInstance = InstanceType<typeof ep.ElInput>; |
| | |
| | | declare module '*.vue' { |
| | | import { DefineComponent } from 'vue'; |
| | | const component: DefineComponent<{}, {}, any>; |
| | | export default component; |
| | | const Component: DefineComponent<{}, {}, any>; |
| | | export default Component; |
| | | } |
| | | |
| | | declare module '*.avif' { |
| | | const src: string; |
| | | export default src; |
| | |
| | | import type { ComponentInternalInstance as ComponentInstance, PropType as VuePropType } from 'vue'; |
| | | import type { ComponentInternalInstance as ComponentInstance, PropType as VuePropType } from 'vue/runtime-core'; |
| | | |
| | | declare global { |
| | | /** vue Instance */ |
| | |
| | | pageNum: number; |
| | | pageSize: number; |
| | | } |
| | | |
| | | declare type DefaultSettings = { |
| | | /** |
| | | * ç½é¡µæ é¢ |
| | | */ |
| | | title: string; |
| | | |
| | | /** |
| | | * ä¾§è¾¹æ ä¸»é¢ theme-dark | theme-light |
| | | */ |
| | | sideTheme?: string; |
| | | |
| | | /** |
| | | * æ¯å¦æ¾ç¤ºç³»ç»å¸å±è®¾ç½® |
| | | */ |
| | | showSettings?: boolean; |
| | | |
| | | /** |
| | | * æ¯å¦æ¾ç¤ºé¡¶é¨å¯¼èª |
| | | */ |
| | | topNav?: boolean; |
| | | |
| | | /** |
| | | * æ¯å¦æ¾ç¤ºå¤æ ç¾å¯¼èª |
| | | */ |
| | | tagsView?: boolean; |
| | | /** |
| | | * æ¯å¦åºå®å¤´é¨ |
| | | */ |
| | | fixedHeader?: boolean; |
| | | /** |
| | | * æ¯å¦æ¾ç¤ºä¾§è¾¹æ Logo |
| | | */ |
| | | sidebarLogo?: boolean; |
| | | /** |
| | | * å¯¼èªæ å¸å± |
| | | */ |
| | | layout?: string; |
| | | /** |
| | | * 䏻颿¨¡å¼ |
| | | */ |
| | | theme?: string; |
| | | |
| | | /** |
| | | * å¸å±å¤§å° |
| | | */ |
| | | size?: string; |
| | | |
| | | /** |
| | | * è¯è¨ |
| | | */ |
| | | language?: string; |
| | | |
| | | /** |
| | | * æ¯å¦æ¾ç¤ºå¨ææ é¢ |
| | | */ |
| | | dynamicTitle?: boolean; |
| | | /** |
| | | * æ¯å¦å¯ç¨å¨ç»ææ |
| | | */ |
| | | animationEnable?: boolean; |
| | | /** |
| | | * æ¯å¦å¯ç¨æé»æ¨¡å¼ |
| | | * |
| | | * true:æé»æ¨¡å¼ |
| | | * false: æäº®æ¨¡å¼ |
| | | */ |
| | | dark?: boolean; |
| | | |
| | | errorLog?: string; |
| | | }; |
| | | } |
| | | export {}; |
| | |
| | | import { RouteRecordRaw } from 'vue-router'; |
| | | |
| | | import { LocationQuery, type RouteMeta as VRouteMeta } from 'vue-router'; |
| | | declare module 'vue-router' { |
| | | declare type RouteOption = { |
| | | hidden?: boolean; |
| | | interface RouteMeta extends VRouteMeta { |
| | | link?: string; |
| | | title?: string; |
| | | affix?: boolean; |
| | | noCache?: boolean; |
| | | activeMenu?: string; |
| | | icon?: string; |
| | | breadcrumb?: boolean; |
| | | } |
| | | |
| | | interface _RouteRecordBase { |
| | | hidden?: boolean | string | number; |
| | | permissions?: string[]; |
| | | roles?: string[]; |
| | | component?: any; |
| | | children?: RouteOption[]; |
| | | alwaysShow?: boolean; |
| | | parentPath?: string; |
| | | meta?: { |
| | | title: string; |
| | | icon: string; |
| | | }; |
| | | query?: string; |
| | | } & RouteRecordRaw; |
| | | |
| | | declare interface _RouteLocationBase { |
| | | children?: RouteOption[]; |
| | | } |
| | | |
| | | declare interface RouteLocationOptions { |
| | | interface _RouteLocationBase { |
| | | children?: _RouteRecordBase[]; |
| | | path?: string; |
| | | } |
| | | |
| | | interface TagView { |
| | | fullPath?: string; |
| | | } |
| | | |
| | | declare interface TagView extends Partial<_RouteLocationBase> { |
| | | name?: string; |
| | | path?: string; |
| | | title?: string; |
| | | meta?: { |
| | | link?: string; |
| | | title?: string; |
| | | affix?: boolean; |
| | | noCache?: boolean; |
| | | }; |
| | | meta?: RouteMeta; |
| | | query?: LocationQuery; |
| | | } |
| | | } |
| | |
| | | |
| | | type PropTypes = VueTypesInterface & { |
| | | readonly style: VueTypeValidableDef<CSSProperties>; |
| | | readonly fieldOption: VueTypeValidableDef<Array<FieldOption>>; |
| | | }; |
| | | |
| | | const propTypes = createTypes({ |
| | |
| | | return config; |
| | | }, |
| | | (error: any) => { |
| | | console.log(error); |
| | | return Promise.reject(error); |
| | | } |
| | | ); |
| | |
| | | } |
| | | return Promise.reject('æ æçä¼è¯ï¼æè
ä¼è¯å·²è¿æï¼è¯·éæ°ç»å½ã'); |
| | | } else if (code === HttpStatus.SERVER_ERROR) { |
| | | console.log(msg); |
| | | ElMessage({ message: msg, type: 'error' }); |
| | | return Promise.reject(new Error(msg)); |
| | | } else if (code === HttpStatus.WARN) { |
| | |
| | | |
| | | import { getToken } from '@/utils/auth'; |
| | | import useNoticeStore from '@/store/modules/notice'; |
| | | import { ElNotification } from "element-plus"; |
| | | import { ElNotification } from 'element-plus'; |
| | | |
| | | const { addNotice } = useNoticeStore(); |
| | | |
| | |
| | | message: e.data, |
| | | type: 'success', |
| | | duration: 3000 |
| | | }) |
| | | }); |
| | | return e.data; |
| | | }; |
| | | }; |
| | |
| | | <template> |
| | | <div class="p-2"> |
| | | <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave"> |
| | | <div class="mb-[10px]" v-show="showSearch"> |
| | | <div v-show="showSearch" class="mb-[10px]"> |
| | | <el-card shadow="hover"> |
| | | <el-form :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px"> |
| | | <el-form ref="queryFormRef" :model="queryParams" :inline="true" label-width="68px"> |
| | | <el-form-item label="é¨é¨id" prop="deptId"> |
| | | <el-input v-model="queryParams.deptId" placeholder="请è¾å
¥é¨é¨id" clearable style="width: 240px" @keyup.enter="handleQuery" /> |
| | | </el-form-item> |
| | |
| | | <template #header> |
| | | <el-row :gutter="10" class="mb8"> |
| | | <el-col :span="1.5"> |
| | | <el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['demo:demo:add']">æ°å¢</el-button> |
| | | <el-button v-hasPermi="['demo:demo:add']" type="primary" plain icon="Plus" @click="handleAdd">æ°å¢</el-button> |
| | | </el-col> |
| | | <el-col :span="1.5"> |
| | | <el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['demo:demo:edit']">ä¿®æ¹</el-button> |
| | | <el-button v-hasPermi="['demo:demo:edit']" type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()">ä¿®æ¹</el-button> |
| | | </el-col> |
| | | <el-col :span="1.5"> |
| | | <el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['demo:demo:remove']" |
| | | <el-button v-hasPermi="['demo:demo:remove']" type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" |
| | | >å é¤</el-button |
| | | > |
| | | </el-col> |
| | | <el-col :span="1.5"> |
| | | <el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['demo:demo:export']">导åº</el-button> |
| | | <el-button v-hasPermi="['demo:demo:export']" type="warning" plain icon="Download" @click="handleExport">导åº</el-button> |
| | | </el-col> |
| | | <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar> |
| | | <right-toolbar v-model:showSearch="showSearch" @query-table="getList"></right-toolbar> |
| | | </el-row> |
| | | </template> |
| | | |
| | | <el-table v-loading="loading" :data="demoList" @selection-change="handleSelectionChange"> |
| | | <el-table-column type="selection" width="55" align="center" /> |
| | | <el-table-column label="主é®" align="center" prop="id" v-if="true" /> |
| | | <el-table-column v-if="true" label="主é®" align="center" prop="id" /> |
| | | <el-table-column label="é¨é¨id" align="center" prop="deptId" /> |
| | | <el-table-column label="ç¨æ·id" align="center" prop="userId" /> |
| | | <el-table-column label="æåºå·" align="center" prop="orderNum" /> |
| | |
| | | <el-table-column label="æä½" align="center" class-name="small-padding fixed-width"> |
| | | <template #default="scope"> |
| | | <el-tooltip content="ä¿®æ¹" placement="top"> |
| | | <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['demo:demo:edit']"></el-button> |
| | | <el-button v-hasPermi="['demo:demo:edit']" link type="primary" icon="Edit" @click="handleUpdate(scope.row)"></el-button> |
| | | </el-tooltip> |
| | | <el-tooltip content="å é¤" placement="top"> |
| | | <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['demo:demo:remove']"></el-button> |
| | | <el-button v-hasPermi="['demo:demo:remove']" link type="primary" icon="Delete" @click="handleDelete(scope.row)"></el-button> |
| | | </el-tooltip> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | |
| | | <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" /> |
| | | <pagination v-show="total > 0" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" :total="total" @pagination="getList" /> |
| | | </el-card> |
| | | <!-- æ·»å æä¿®æ¹æµè¯åå¯¹è¯æ¡ --> |
| | | <el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body> |
| | | <el-dialog v-model="dialog.visible" :title="dialog.title" width="500px" append-to-body> |
| | | <el-form ref="demoFormRef" :model="form" :rules="rules" label-width="80px"> |
| | | <el-form-item label="é¨é¨id" prop="deptId"> |
| | | <el-input v-model="form.deptId" placeholder="请è¾å
¥é¨é¨id" /> |
| | |
| | | userId: undefined, |
| | | orderNum: undefined, |
| | | testKey: undefined, |
| | | value: undefined, |
| | | } |
| | | value: undefined |
| | | }; |
| | | const data = reactive<PageData<DemoForm, DemoQuery>>({ |
| | | form: { ...initFormData }, |
| | | queryParams: { |
| | |
| | | userId: undefined, |
| | | orderNum: undefined, |
| | | testKey: undefined, |
| | | value: undefined, |
| | | value: undefined |
| | | }, |
| | | rules: { |
| | | id: [ |
| | | { required: true, message: "主é®ä¸è½ä¸ºç©º", trigger: "blur" } |
| | | ], |
| | | deptId: [ |
| | | { required: true, message: "é¨é¨idä¸è½ä¸ºç©º", trigger: "blur" } |
| | | ], |
| | | userId: [ |
| | | { required: true, message: "ç¨æ·idä¸è½ä¸ºç©º", trigger: "blur" } |
| | | ], |
| | | orderNum: [ |
| | | { required: true, message: "æåºå·ä¸è½ä¸ºç©º", trigger: "blur" } |
| | | ], |
| | | testKey: [ |
| | | { required: true, message: "keyé®ä¸è½ä¸ºç©º", trigger: "blur" } |
| | | ], |
| | | value: [ |
| | | { required: true, message: "å¼ä¸è½ä¸ºç©º", trigger: "blur" } |
| | | ], |
| | | id: [{ required: true, message: '主é®ä¸è½ä¸ºç©º', trigger: 'blur' }], |
| | | deptId: [{ required: true, message: 'é¨é¨idä¸è½ä¸ºç©º', trigger: 'blur' }], |
| | | userId: [{ required: true, message: 'ç¨æ·idä¸è½ä¸ºç©º', trigger: 'blur' }], |
| | | orderNum: [{ required: true, message: 'æåºå·ä¸è½ä¸ºç©º', trigger: 'blur' }], |
| | | testKey: [{ required: true, message: 'keyé®ä¸è½ä¸ºç©º', trigger: 'blur' }], |
| | | value: [{ required: true, message: 'å¼ä¸è½ä¸ºç©º', trigger: 'blur' }] |
| | | } |
| | | }); |
| | | |
| | |
| | | demoList.value = res.rows; |
| | | total.value = res.total; |
| | | loading.value = false; |
| | | } |
| | | }; |
| | | |
| | | /** åæ¶æé® */ |
| | | const cancel = () => { |
| | | reset(); |
| | | dialog.visible = false; |
| | | } |
| | | }; |
| | | |
| | | /** 表åéç½® */ |
| | | const reset = () => { |
| | | form.value = { ...initFormData }; |
| | | demoFormRef.value?.resetFields(); |
| | | } |
| | | }; |
| | | |
| | | /** æç´¢æé®æä½ */ |
| | | const handleQuery = () => { |
| | | queryParams.value.pageNum = 1; |
| | | getList(); |
| | | } |
| | | }; |
| | | |
| | | /** éç½®æé®æä½ */ |
| | | const resetQuery = () => { |
| | | queryFormRef.value?.resetFields(); |
| | | handleQuery(); |
| | | } |
| | | }; |
| | | |
| | | /** å¤éæ¡é䏿°æ® */ |
| | | const handleSelectionChange = (selection: DemoVO[]) => { |
| | | ids.value = selection.map(item => item.id); |
| | | ids.value = selection.map((item) => item.id); |
| | | single.value = selection.length != 1; |
| | | multiple.value = !selection.length; |
| | | } |
| | | }; |
| | | |
| | | /** æ°å¢æé®æä½ */ |
| | | const handleAdd = () => { |
| | | reset(); |
| | | dialog.visible = true; |
| | | dialog.title = "æ·»å æµè¯å"; |
| | | } |
| | | dialog.title = 'æ·»å æµè¯å'; |
| | | }; |
| | | |
| | | /** ä¿®æ¹æé®æä½ */ |
| | | const handleUpdate = async (row?: DemoVO) => { |
| | | reset(); |
| | | const _id = row?.id || ids.value[0] |
| | | const _id = row?.id || ids.value[0]; |
| | | const res = await getDemo(_id); |
| | | Object.assign(form.value, res.data); |
| | | dialog.visible = true; |
| | | dialog.title = "ä¿®æ¹æµè¯å"; |
| | | } |
| | | dialog.title = 'ä¿®æ¹æµè¯å'; |
| | | }; |
| | | |
| | | /** æäº¤æé® */ |
| | | const submitForm = () => { |
| | |
| | | if (valid) { |
| | | buttonLoading.value = true; |
| | | if (form.value.id) { |
| | | await updateDemo(form.value).finally(() => buttonLoading.value = false); |
| | | await updateDemo(form.value).finally(() => (buttonLoading.value = false)); |
| | | } else { |
| | | await addDemo(form.value).finally(() => buttonLoading.value = false); |
| | | await addDemo(form.value).finally(() => (buttonLoading.value = false)); |
| | | } |
| | | proxy?.$modal.msgSuccess("ä¿®æ¹æå"); |
| | | proxy?.$modal.msgSuccess('ä¿®æ¹æå'); |
| | | dialog.visible = false; |
| | | await getList(); |
| | | } |
| | | }); |
| | | } |
| | | }; |
| | | |
| | | /** å é¤æé®æä½ */ |
| | | const handleDelete = async (row?: DemoVO) => { |
| | | const _ids = row?.id || ids.value; |
| | | await proxy?.$modal.confirm('æ¯å¦ç¡®è®¤å 餿µè¯åç¼å·ä¸º"' + _ids + '"çæ°æ®é¡¹ï¼').finally(() => loading.value = false); |
| | | await proxy?.$modal.confirm('æ¯å¦ç¡®è®¤å 餿µè¯åç¼å·ä¸º"' + _ids + '"çæ°æ®é¡¹ï¼').finally(() => (loading.value = false)); |
| | | await delDemo(_ids); |
| | | proxy?.$modal.msgSuccess("å 餿å"); |
| | | proxy?.$modal.msgSuccess('å 餿å'); |
| | | await getList(); |
| | | } |
| | | }; |
| | | |
| | | /** å¯¼åºæé®æä½ */ |
| | | const handleExport = () => { |
| | | proxy?.download('demo/demo/export', { |
| | | ...queryParams.value |
| | | }, `demo_${new Date().getTime()}.xlsx`) |
| | | } |
| | | proxy?.download( |
| | | 'demo/demo/export', |
| | | { |
| | | ...queryParams.value |
| | | }, |
| | | `demo_${new Date().getTime()}.xlsx` |
| | | ); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | getList(); |
| | |
| | | <template> |
| | | <div class="p-2"> |
| | | <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave"> |
| | | <div class="mb-[10px]" v-show="showSearch"> |
| | | <div v-show="showSearch" class="mb-[10px]"> |
| | | <el-card shadow="hover"> |
| | | <el-form :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px"> |
| | | <el-form ref="queryFormRef" :model="queryParams" :inline="true" label-width="68px"> |
| | | <el-form-item label="æ èç¹å" prop="treeName"> |
| | | <el-input v-model="queryParams.treeName" placeholder="请è¾å
¥æ èç¹å" clearable style="width: 240px" @keyup.enter="handleQuery" /> |
| | | </el-form-item> |
| | |
| | | <template #header> |
| | | <el-row :gutter="10" class="mb8"> |
| | | <el-col :span="1.5"> |
| | | <el-button type="primary" plain icon="Plus" @click="handleAdd()" v-hasPermi="['demo:tree:add']">æ°å¢</el-button> |
| | | <el-button v-hasPermi="['demo:tree:add']" type="primary" plain icon="Plus" @click="handleAdd()">æ°å¢</el-button> |
| | | </el-col> |
| | | <el-col :span="1.5"> |
| | | <el-button type="info" plain icon="Sort" @click="handleToggleExpandAll">å±å¼/æå </el-button> |
| | | </el-col> |
| | | <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar> |
| | | <right-toolbar v-model:showSearch="showSearch" @query-table="getList"></right-toolbar> |
| | | </el-row> |
| | | </template> |
| | | <el-table |
| | | ref="treeTableRef" |
| | | v-loading="loading" |
| | | :data="treeList" |
| | | row-key="id" |
| | | :default-expand-all="isExpandAll" |
| | | :tree-props="{children: 'children', hasChildren: 'hasChildren'}" |
| | | ref="treeTableRef" |
| | | :tree-props="{ children: 'children', hasChildren: 'hasChildren' }" |
| | | > |
| | | <el-table-column label="ç¶id" align="center" prop="parentId" /> |
| | | <el-table-column label="é¨é¨id" align="center" prop="deptId" /> |
| | |
| | | <el-table-column label="æä½" align="center" class-name="small-padding fixed-width"> |
| | | <template #default="scope"> |
| | | <el-tooltip content="ä¿®æ¹" placement="top"> |
| | | <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['demo:tree:edit']" /> |
| | | <el-button v-hasPermi="['demo:tree:edit']" link type="primary" icon="Edit" @click="handleUpdate(scope.row)" /> |
| | | </el-tooltip> |
| | | <el-tooltip content="æ°å¢" placement="top"> |
| | | <el-button link type="primary" icon="Plus" @click="handleAdd(scope.row)" v-hasPermi="['demo:tree:add']" /> |
| | | <el-button v-hasPermi="['demo:tree:add']" link type="primary" icon="Plus" @click="handleAdd(scope.row)" /> |
| | | </el-tooltip> |
| | | <el-tooltip content="å é¤" placement="top"> |
| | | <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['demo:tree:remove']" /> |
| | | <el-button v-hasPermi="['demo:tree:remove']" link type="primary" icon="Delete" @click="handleDelete(scope.row)" /> |
| | | </el-tooltip> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </el-card> |
| | | <!-- æ·»å æä¿®æ¹æµè¯æ å¯¹è¯æ¡ --> |
| | | <el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body> |
| | | <el-dialog v-model="dialog.visible" :title="dialog.title" width="500px" append-to-body> |
| | | <el-form ref="treeFormRef" :model="form" :rules="rules" label-width="80px"> |
| | | <el-form-item label="ç¶id" prop="parentId"> |
| | | <el-tree-select |
| | |
| | | </template> |
| | | |
| | | <script setup name="Tree" lang="ts"> |
| | | import { listTree, getTree, delTree, addTree, updateTree } from "@/api/demo/tree"; |
| | | import { listTree, getTree, delTree, addTree, updateTree } from '@/api/demo/tree'; |
| | | import { TreeVO, TreeQuery, TreeForm } from '@/api/demo/tree/types'; |
| | | |
| | | |
| | | type TreeOption = { |
| | | id: number; |
| | | treeName: string; |
| | | children?: TreeOption[]; |
| | | } |
| | | }; |
| | | |
| | | const { proxy } = getCurrentInstance() as ComponentInternalInstance;; |
| | | |
| | | const { proxy } = getCurrentInstance() as ComponentInternalInstance; |
| | | |
| | | const treeList = ref<TreeVO[]>([]); |
| | | const treeOptions = ref<TreeOption[]>([]); |
| | |
| | | |
| | | const queryFormRef = ref<ElFormInstance>(); |
| | | const treeFormRef = ref<ElFormInstance>(); |
| | | const treeTableRef = ref<ElTableInstance>() |
| | | const treeTableRef = ref<ElTableInstance>(); |
| | | |
| | | const dialog = reactive<DialogOption>({ |
| | | visible: false, |
| | | title: '' |
| | | visible: false, |
| | | title: '' |
| | | }); |
| | | |
| | | |
| | | const initFormData: TreeForm = { |
| | | id: undefined, |
| | | parentId: undefined, |
| | | deptId: undefined, |
| | | userId: undefined, |
| | | treeName: undefined, |
| | | } |
| | | id: undefined, |
| | | parentId: undefined, |
| | | deptId: undefined, |
| | | userId: undefined, |
| | | treeName: undefined |
| | | }; |
| | | |
| | | const data = reactive<PageData<TreeForm, TreeQuery>>({ |
| | | form: {...initFormData}, |
| | | form: { ...initFormData }, |
| | | queryParams: { |
| | | parentId: undefined, |
| | | deptId: undefined, |
| | | userId: undefined, |
| | | treeName: undefined, |
| | | treeName: undefined |
| | | }, |
| | | rules: { |
| | | id: [ |
| | | { required: true, message: "主é®ä¸è½ä¸ºç©º", trigger: "blur" } |
| | | ], |
| | | parentId: [ |
| | | { required: true, message: "ç¶idä¸è½ä¸ºç©º", trigger: "blur" } |
| | | ], |
| | | deptId: [ |
| | | { required: true, message: "é¨é¨idä¸è½ä¸ºç©º", trigger: "blur" } |
| | | ], |
| | | userId: [ |
| | | { required: true, message: "ç¨æ·idä¸è½ä¸ºç©º", trigger: "blur" } |
| | | ], |
| | | treeName: [ |
| | | { required: true, message: "å¼ä¸è½ä¸ºç©º", trigger: "blur" } |
| | | ], |
| | | id: [{ required: true, message: '主é®ä¸è½ä¸ºç©º', trigger: 'blur' }], |
| | | parentId: [{ required: true, message: 'ç¶idä¸è½ä¸ºç©º', trigger: 'blur' }], |
| | | deptId: [{ required: true, message: 'é¨é¨idä¸è½ä¸ºç©º', trigger: 'blur' }], |
| | | userId: [{ required: true, message: 'ç¨æ·idä¸è½ä¸ºç©º', trigger: 'blur' }], |
| | | treeName: [{ required: true, message: 'å¼ä¸è½ä¸ºç©º', trigger: 'blur' }] |
| | | } |
| | | }); |
| | | |
| | |
| | | const getList = async () => { |
| | | loading.value = true; |
| | | const res = await listTree(queryParams.value); |
| | | const data = proxy?.handleTree<TreeVO>(res.data, "id", "parentId"); |
| | | const data = proxy?.handleTree<TreeVO>(res.data, 'id', 'parentId'); |
| | | if (data) { |
| | | treeList.value = data; |
| | | loading.value = false; |
| | | } |
| | | } |
| | | }; |
| | | |
| | | /** æ¥è¯¢æµè¯æ 䏿æ ç»æ */ |
| | | const getTreeselect = async () => { |
| | | const res = await listTree(); |
| | | treeOptions.value = []; |
| | | const data: TreeOption = { id: 0, treeName: '顶级èç¹', children: [] }; |
| | | data.children = proxy?.handleTree<TreeOption>(res.data, "id", "parentId"); |
| | | data.children = proxy?.handleTree<TreeOption>(res.data, 'id', 'parentId'); |
| | | treeOptions.value.push(data); |
| | | } |
| | | }; |
| | | |
| | | // åæ¶æé® |
| | | const cancel = () => { |
| | | reset(); |
| | | dialog.visible = false; |
| | | } |
| | | }; |
| | | |
| | | // 表åéç½® |
| | | const reset = () => { |
| | | form.value = {...initFormData} |
| | | form.value = { ...initFormData }; |
| | | treeFormRef.value?.resetFields(); |
| | | } |
| | | }; |
| | | |
| | | /** æç´¢æé®æä½ */ |
| | | const handleQuery = () => { |
| | | getList(); |
| | | } |
| | | }; |
| | | |
| | | /** éç½®æé®æä½ */ |
| | | const resetQuery = () => { |
| | | queryFormRef.value?.resetFields(); |
| | | handleQuery(); |
| | | } |
| | | }; |
| | | |
| | | /** æ°å¢æé®æä½ */ |
| | | const handleAdd = (row?: TreeVO) => { |
| | |
| | | form.value.parentId = 0; |
| | | } |
| | | dialog.visible = true; |
| | | dialog.title = "æ·»å æµè¯æ "; |
| | | } |
| | | dialog.title = 'æ·»å æµè¯æ '; |
| | | }; |
| | | |
| | | /** å±å¼/æå æä½ */ |
| | | const handleToggleExpandAll = () => { |
| | | isExpandAll.value = !isExpandAll.value; |
| | | toggleExpandAll(treeList.value, isExpandAll.value) |
| | | } |
| | | toggleExpandAll(treeList.value, isExpandAll.value); |
| | | }; |
| | | |
| | | /** å±å¼/æå æä½ */ |
| | | const toggleExpandAll = (data: TreeVO[], status: boolean) => { |
| | | data.forEach((item) => { |
| | | treeTableRef.value?.toggleRowExpansion(item, status) |
| | | if (item.children && item.children.length > 0) toggleExpandAll(item.children, status) |
| | | }) |
| | | } |
| | | treeTableRef.value?.toggleRowExpansion(item, status); |
| | | if (item.children && item.children.length > 0) toggleExpandAll(item.children, status); |
| | | }); |
| | | }; |
| | | |
| | | /** ä¿®æ¹æé®æä½ */ |
| | | const handleUpdate = async (row: TreeVO) => { |
| | |
| | | const res = await getTree(row.id); |
| | | Object.assign(form.value, res.data); |
| | | dialog.visible = true; |
| | | dialog.title = "ä¿®æ¹æµè¯æ "; |
| | | } |
| | | dialog.title = 'ä¿®æ¹æµè¯æ '; |
| | | }; |
| | | |
| | | /** æäº¤æé® */ |
| | | const submitForm = () => { |
| | |
| | | if (valid) { |
| | | buttonLoading.value = true; |
| | | if (form.value.id) { |
| | | await updateTree(form.value).finally(() => buttonLoading.value = false); |
| | | await updateTree(form.value).finally(() => (buttonLoading.value = false)); |
| | | } else { |
| | | await addTree(form.value).finally(() => buttonLoading.value = false); |
| | | await addTree(form.value).finally(() => (buttonLoading.value = false)); |
| | | } |
| | | proxy?.$modal.msgSuccess("æä½æå"); |
| | | proxy?.$modal.msgSuccess('æä½æå'); |
| | | dialog.visible = false; |
| | | await getList(); |
| | | } |
| | | }); |
| | | } |
| | | }; |
| | | |
| | | /** å é¤æé®æä½ */ |
| | | const handleDelete = async (row: TreeVO) => { |
| | | await proxy?.$modal.confirm('æ¯å¦ç¡®è®¤å 餿µè¯æ ç¼å·ä¸º"' + row.id + '"çæ°æ®é¡¹ï¼'); |
| | | loading.value = true; |
| | | await delTree(row.id).finally(() => loading.value = false); |
| | | await delTree(row.id).finally(() => (loading.value = false)); |
| | | await getList(); |
| | | proxy?.$modal.msgSuccess("å 餿å"); |
| | | } |
| | | proxy?.$modal.msgSuccess('å 餿å'); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | getList(); |
| | |
| | | |
| | | let { proxy } = getCurrentInstance() as ComponentInternalInstance; |
| | | |
| | | const errGif = ref(errImage + "?" + +new Date()); |
| | | const errGif = ref(errImage + '?' + +new Date()); |
| | | |
| | | function back() { |
| | | if (proxy?.$route.query.noGoBack) { |
| | | proxy.$router.push({ path: "/" }); |
| | | proxy.$router.push({ path: '/' }); |
| | | } else { |
| | | proxy?.$router.go(-1); |
| | | } |
| | |
| | | |
| | | <script setup lang="ts"> |
| | | let message = computed(() => { |
| | | return 'æ¾ä¸å°ç½é¡µï¼' |
| | | }) |
| | | return 'æ¾ä¸å°ç½é¡µï¼'; |
| | | }); |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .wscn-http404-container{ |
| | | transform: translate(-50%,-50%); |
| | | .wscn-http404-container { |
| | | transform: translate(-50%, -50%); |
| | | position: absolute; |
| | | top: 40%; |
| | | left: 50%; |
| | |
| | | import { initWebSocket } from '@/utils/websocket'; |
| | | |
| | | onMounted(() => { |
| | | let protocol = window.location.protocol === 'https:' ? 'wss://' : 'ws://' |
| | | initWebSocket(protocol + window.location.host + import.meta.env.VITE_APP_BASE_API + "/resource/websocket"); |
| | | let protocol = window.location.protocol === 'https:' ? 'wss://' : 'ws://'; |
| | | initWebSocket(protocol + window.location.host + import.meta.env.VITE_APP_BASE_API + '/resource/websocket'); |
| | | }); |
| | | |
| | | const goTarget = (url:string) => { |
| | | window.open(url, '__blank') |
| | | } |
| | | const goTarget = (url: string) => { |
| | | window.open(url, '__blank'); |
| | | }; |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | |
| | | margin: 0; |
| | | } |
| | | |
| | | font-family: "open sans", "Helvetica Neue", Helvetica, Arial, sans-serif; |
| | | font-family: 'open sans', 'Helvetica Neue', Helvetica, Arial, sans-serif; |
| | | font-size: 13px; |
| | | color: #676a6c; |
| | | overflow-x: hidden; |
| | |
| | | <div class="login"> |
| | | <el-form ref="loginRef" :model="loginForm" :rules="loginRules" class="login-form"> |
| | | <h3 class="title">RuoYi-Vue-Pluså¤ç§æ·ç®¡çç³»ç»</h3> |
| | | <el-form-item prop="tenantId" v-if="tenantEnabled"> |
| | | <el-form-item v-if="tenantEnabled" prop="tenantId"> |
| | | <el-select v-model="loginForm.tenantId" filterable placeholder="è¯·éæ©/è¾å
¥å
¬å¸åç§°" style="width: 100%"> |
| | | <el-option v-for="item in tenantList" :key="item.tenantId" :label="item.companyName" :value="item.tenantId"></el-option> |
| | | <template #prefix><svg-icon icon-class="company" class="el-input__icon input-icon" /></template> |
| | |
| | | <template #prefix><svg-icon icon-class="password" class="el-input__icon input-icon" /></template> |
| | | </el-input> |
| | | </el-form-item> |
| | | <el-form-item prop="code" v-if="captchaEnabled"> |
| | | <el-form-item v-if="captchaEnabled" prop="code"> |
| | | <el-input v-model="loginForm.code" size="large" auto-complete="off" placeholder="éªè¯ç " style="width: 63%" @keyup.enter="handleLogin"> |
| | | <template #prefix><svg-icon icon-class="validCode" class="el-input__icon input-icon" /></template> |
| | | </el-input> |
| | | <div class="login-code"> |
| | | <img :src="codeUrl" @click="getCode" class="login-code-img" /> |
| | | <img :src="codeUrl" class="login-code-img" @click="getCode" /> |
| | | </div> |
| | | </el-form-item> |
| | | <el-checkbox v-model="loginForm.rememberMe" style="margin:0px 0px 25px 0px;">è®°ä½å¯ç </el-checkbox> |
| | | <el-form-item style="float: right;"> |
| | | <el-checkbox v-model="loginForm.rememberMe" style="margin: 0px 0px 25px 0px">è®°ä½å¯ç </el-checkbox> |
| | | <el-form-item style="float: right"> |
| | | <el-button circle title="微信ç»å½" @click="doSocialLogin('wechat')"> |
| | | <svg-icon icon-class="wechat" /> |
| | | </el-button> |
| | |
| | | <svg-icon icon-class="github" /> |
| | | </el-button> |
| | | </el-form-item> |
| | | <el-form-item style="width:100%;"> |
| | | <el-button :loading="loading" size="large" type="primary" style="width:100%;" @click.prevent="handleLogin"> |
| | | <el-form-item style="width: 100%"> |
| | | <el-button :loading="loading" size="large" type="primary" style="width: 100%" @click.prevent="handleLogin"> |
| | | <span v-if="!loading">ç» å½</span> |
| | | <span v-else>ç» å½ ä¸...</span> |
| | | </el-button> |
| | | <div style="float: right;" v-if="register"> |
| | | <div v-if="register" style="float: right"> |
| | | <router-link class="link-type" :to="'/register'">ç«å³æ³¨å</router-link> |
| | | </div> |
| | | </el-form-item> |
| | |
| | | import { useUserStore } from '@/store/modules/user'; |
| | | import { LoginData, TenantVO } from '@/api/types'; |
| | | import { to } from 'await-to-js'; |
| | | import { HttpStatus } from "@/enums/RespEnum"; |
| | | import { HttpStatus } from '@/enums/RespEnum'; |
| | | |
| | | const userStore = useUserStore(); |
| | | const router = useRouter(); |
| | |
| | | } as LoginData); |
| | | |
| | | const loginRules: ElFormRules = { |
| | | tenantId: [{ required: true, trigger: "blur", message: "请è¾å
¥æ¨çç§æ·ç¼å·" }], |
| | | tenantId: [{ required: true, trigger: 'blur', message: '请è¾å
¥æ¨çç§æ·ç¼å·' }], |
| | | username: [{ required: true, trigger: 'blur', message: '请è¾å
¥æ¨çè´¦å·' }], |
| | | password: [{ required: true, trigger: 'blur', message: '请è¾å
¥æ¨çå¯ç ' }], |
| | | code: [{ required: true, trigger: 'change', message: '请è¾å
¥éªè¯ç ' }] |
| | |
| | | // ç§æ·å¼å
³ |
| | | const tenantEnabled = ref(true); |
| | | |
| | | |
| | | // 注åå¼å
³ |
| | | const register = ref(false); |
| | | const redirect = ref(undefined); |
| | |
| | | // ç§æ·å表 |
| | | const tenantList = ref<TenantVO[]>([]); |
| | | |
| | | watch(() => router.currentRoute.value, (newRoute: any) => { |
| | | redirect.value = newRoute.query && newRoute.query.redirect; |
| | | }, { immediate: true }); |
| | | watch( |
| | | () => router.currentRoute.value, |
| | | (newRoute: any) => { |
| | | redirect.value = newRoute.query && newRoute.query.redirect; |
| | | }, |
| | | { immediate: true } |
| | | ); |
| | | |
| | | const handleLogin = () => { |
| | | loginRef.value?.validate(async (valid: boolean, fields: any) => { |
| | |
| | | loading.value = true; |
| | | // å¾éäºéè¦è®°ä½å¯ç è®¾ç½®å¨ localStorage ä¸è®¾ç½®è®°ä½ç¨æ·ååå¯ç |
| | | if (loginForm.value.rememberMe) { |
| | | localStorage.setItem("tenantId", String(loginForm.value.tenantId)); |
| | | localStorage.setItem('tenantId', String(loginForm.value.tenantId)); |
| | | localStorage.setItem('username', String(loginForm.value.username)); |
| | | localStorage.setItem('password', String(loginForm.value.password)); |
| | | localStorage.setItem('rememberMe', String(loginForm.value.rememberMe)); |
| | | } else { |
| | | // å¦åç§»é¤ |
| | | localStorage.removeItem("tenantId"); |
| | | localStorage.removeItem('tenantId'); |
| | | localStorage.removeItem('username'); |
| | | localStorage.removeItem('password'); |
| | | localStorage.removeItem('rememberMe'); |
| | |
| | | }; |
| | | |
| | | const getLoginData = () => { |
| | | const tenantId = localStorage.getItem("tenantId"); |
| | | const tenantId = localStorage.getItem('tenantId'); |
| | | const username = localStorage.getItem('username'); |
| | | const password = localStorage.getItem('password'); |
| | | const rememberMe = localStorage.getItem('rememberMe'); |
| | |
| | | password: password === null ? String(loginForm.value.password) : String(password), |
| | | rememberMe: rememberMe === null ? false : Boolean(rememberMe) |
| | | } as LoginData; |
| | | } |
| | | |
| | | }; |
| | | |
| | | /** |
| | | * è·åç§æ·å表 |
| | |
| | | loginForm.value.tenantId = tenantList.value[0].tenantId; |
| | | } |
| | | } |
| | | } |
| | | }; |
| | | |
| | | //æ£æµç§æ·éæ©æ¡çåå |
| | | watch(() => loginForm.value.tenantId, () => { |
| | | localStorage.setItem("tenantId", String(loginForm.value.tenantId)) |
| | | }); |
| | | watch( |
| | | () => loginForm.value.tenantId, |
| | | () => { |
| | | localStorage.setItem('tenantId', String(loginForm.value.tenantId)); |
| | | } |
| | | ); |
| | | |
| | | /** |
| | | * ç¬¬ä¸æ¹ç»å½ |
| | |
| | | }); |
| | | }; |
| | | |
| | | |
| | | |
| | | onMounted(() => { |
| | | getCode(); |
| | | initTenantList(); |
| | |
| | | justify-content: center; |
| | | align-items: center; |
| | | height: 100%; |
| | | background-image: url("../assets/images/login-background.jpg"); |
| | | background-image: url('../assets/images/login-background.jpg'); |
| | | background-size: cover; |
| | | } |
| | | |
| | |
| | | <el-col :span="24" class="card-box"> |
| | | <el-card shadow="hover"> |
| | | <template #header> |
| | | <Monitor style="width: 1em; height: 1em; vertical-align: middle;" /> |
| | | <span style="vertical-align: middle;">åºæ¬ä¿¡æ¯</span> |
| | | <Monitor style="width: 1em; height: 1em; vertical-align: middle" /> |
| | | <span style="vertical-align: middle">åºæ¬ä¿¡æ¯</span> |
| | | </template> |
| | | |
| | | <div class="el-table el-table--enable-row-hover el-table--medium"> |
| | |
| | | <div class="cell">Redisçæ¬</div> |
| | | </td> |
| | | <td class="el-table__cell is-leaf"> |
| | | <div class="cell" v-if="cache.info">{{ cache.info.redis_version }}</div> |
| | | <div v-if="cache.info" class="cell">{{ cache.info.redis_version }}</div> |
| | | </td> |
| | | <td class="el-table__cell is-leaf"> |
| | | <div class="cell">è¿è¡æ¨¡å¼</div> |
| | | </td> |
| | | <td class="el-table__cell is-leaf"> |
| | | <div class="cell" v-if="cache.info">{{ cache.info.redis_mode === "standalone" ? "åæº" : "é群" }}</div> |
| | | <div v-if="cache.info" class="cell">{{ cache.info.redis_mode === 'standalone' ? 'åæº' : 'é群' }}</div> |
| | | </td> |
| | | <td class="el-table__cell is-leaf"> |
| | | <div class="cell">端å£</div> |
| | | </td> |
| | | <td class="el-table__cell is-leaf"> |
| | | <div class="cell" v-if="cache.info">{{ cache.info.tcp_port }}</div> |
| | | <div v-if="cache.info" class="cell">{{ cache.info.tcp_port }}</div> |
| | | </td> |
| | | <td class="el-table__cell is-leaf"> |
| | | <div class="cell">客æ·ç«¯æ°</div> |
| | | </td> |
| | | <td class="el-table__cell is-leaf"> |
| | | <div class="cell" v-if="cache.info">{{ cache.info.connected_clients }}</div> |
| | | <div v-if="cache.info" class="cell">{{ cache.info.connected_clients }}</div> |
| | | </td> |
| | | </tr> |
| | | <tr> |
| | |
| | | <div class="cell">è¿è¡æ¶é´(天)</div> |
| | | </td> |
| | | <td class="el-table__cell is-leaf"> |
| | | <div class="cell" v-if="cache.info">{{ cache.info.uptime_in_days }}</div> |
| | | <div v-if="cache.info" class="cell">{{ cache.info.uptime_in_days }}</div> |
| | | </td> |
| | | <td class="el-table__cell is-leaf"> |
| | | <div class="cell">使ç¨å
å</div> |
| | | </td> |
| | | <td class="el-table__cell is-leaf"> |
| | | <div class="cell" v-if="cache.info">{{ cache.info.used_memory_human }}</div> |
| | | <div v-if="cache.info" class="cell">{{ cache.info.used_memory_human }}</div> |
| | | </td> |
| | | <td class="el-table__cell is-leaf"> |
| | | <div class="cell">使ç¨CPU</div> |
| | | </td> |
| | | <td class="el-table__cell is-leaf"> |
| | | <div class="cell" v-if="cache.info">{{ parseFloat(cache.info.used_cpu_user_children).toFixed(2) }}</div> |
| | | <div v-if="cache.info" class="cell">{{ parseFloat(cache.info.used_cpu_user_children).toFixed(2) }}</div> |
| | | </td> |
| | | <td class="el-table__cell is-leaf"> |
| | | <div class="cell">å
åé
ç½®</div> |
| | | </td> |
| | | <td class="el-table__cell is-leaf"> |
| | | <div class="cell" v-if="cache.info">{{ cache.info.maxmemory_human }}</div> |
| | | <div v-if="cache.info" class="cell">{{ cache.info.maxmemory_human }}</div> |
| | | </td> |
| | | </tr> |
| | | <tr> |
| | |
| | | <div class="cell">AOFæ¯å¦å¼å¯</div> |
| | | </td> |
| | | <td class="el-table__cell is-leaf"> |
| | | <div class="cell" v-if="cache.info">{{ cache.info.aof_enabled === "0" ? "å¦" : "æ¯" }}</div> |
| | | <div v-if="cache.info" class="cell">{{ cache.info.aof_enabled === '0' ? 'å¦' : 'æ¯' }}</div> |
| | | </td> |
| | | <td class="el-table__cell is-leaf"> |
| | | <div class="cell">RDBæ¯å¦æå</div> |
| | | </td> |
| | | <td class="el-table__cell is-leaf"> |
| | | <div class="cell" v-if="cache.info">{{ cache.info.rdb_last_bgsave_status }}</div> |
| | | <div v-if="cache.info" class="cell">{{ cache.info.rdb_last_bgsave_status }}</div> |
| | | </td> |
| | | <td class="el-table__cell is-leaf"> |
| | | <div class="cell">Keyæ°é</div> |
| | | </td> |
| | | <td class="el-table__cell is-leaf"> |
| | | <div class="cell" v-if="cache.dbSize">{{ cache.dbSize }}</div> |
| | | <div v-if="cache.dbSize" class="cell">{{ cache.dbSize }}</div> |
| | | </td> |
| | | <td class="el-table__cell is-leaf"> |
| | | <div class="cell">ç½ç»å
¥å£/åºå£</div> |
| | | </td> |
| | | <td class="el-table__cell is-leaf"> |
| | | <div class="cell" v-if="cache.info"> |
| | | <div v-if="cache.info" class="cell"> |
| | | {{ cache.info.instantaneous_input_kbps }}kps/{{ cache.info.instantaneous_output_kbps }}kps |
| | | </div> |
| | | </td> |
| | |
| | | <el-col :span="12" class="card-box"> |
| | | <el-card shadow="hover"> |
| | | <template #header> |
| | | <PieChart style="width: 1em; height: 1em; vertical-align: middle;" /> |
| | | <span style="vertical-align: middle;">å½ä»¤ç»è®¡</span> |
| | | <PieChart style="width: 1em; height: 1em; vertical-align: middle" /> |
| | | <span style="vertical-align: middle">å½ä»¤ç»è®¡</span> |
| | | </template> |
| | | <div class="el-table el-table--enable-row-hover el-table--medium"> |
| | | <div ref="commandstats" style="height: 420px" /> |
| | |
| | | <el-col :span="12" class="card-box"> |
| | | <el-card shadow="hover"> |
| | | <template #header> |
| | | <Odometer style="width: 1em; height: 1em; vertical-align: middle;" /> <span style="vertical-align: middle;">å
åä¿¡æ¯</span> |
| | | <Odometer style="width: 1em; height: 1em; vertical-align: middle" /> <span style="vertical-align: middle">å
åä¿¡æ¯</span> |
| | | </template> |
| | | <div class="el-table el-table--enable-row-hover el-table--medium"> |
| | | <div ref="usedmemory" style="height: 420px" /> |
| | |
| | | const { proxy } = getCurrentInstance() as ComponentInternalInstance; |
| | | |
| | | const getList = async () => { |
| | | proxy?.$modal.loading("æ£å¨å è½½ç¼åçæ§æ°æ®ï¼è¯·ç¨åï¼"); |
| | | proxy?.$modal.loading('æ£å¨å è½½ç¼åçæ§æ°æ®ï¼è¯·ç¨åï¼'); |
| | | const res = await getCache(); |
| | | proxy?.$modal.closeLoading(); |
| | | cache.value = res.data; |
| | | const commandstatsIntance = echarts.init(commandstats.value, "macarons"); |
| | | const commandstatsIntance = echarts.init(commandstats.value, 'macarons'); |
| | | commandstatsIntance.setOption({ |
| | | tooltip: { |
| | | trigger: "item", |
| | | formatter: "{a} <br/>{b} : {c} ({d}%)" |
| | | trigger: 'item', |
| | | formatter: '{a} <br/>{b} : {c} ({d}%)' |
| | | }, |
| | | series: [ |
| | | { |
| | | name: "å½ä»¤", |
| | | type: "pie", |
| | | roseType: "radius", |
| | | name: 'å½ä»¤', |
| | | type: 'pie', |
| | | roseType: 'radius', |
| | | radius: [15, 95], |
| | | center: ["50%", "38%"], |
| | | center: ['50%', '38%'], |
| | | data: res.data.commandStats, |
| | | animationEasing: "cubicInOut", |
| | | animationEasing: 'cubicInOut', |
| | | animationDuration: 1000 |
| | | } |
| | | ] |
| | | }); |
| | | const usedmemoryInstance = echarts.init(usedmemory.value, "macarons"); |
| | | const usedmemoryInstance = echarts.init(usedmemory.value, 'macarons'); |
| | | usedmemoryInstance.setOption({ |
| | | tooltip: { |
| | | formatter: "{b} <br/>{a} : " + cache.value.info.used_memory_human |
| | | formatter: '{b} <br/>{a} : ' + cache.value.info.used_memory_human |
| | | }, |
| | | series: [ |
| | | { |
| | | name: "å³°å¼", |
| | | type: "gauge", |
| | | name: 'å³°å¼', |
| | | type: 'gauge', |
| | | min: 0, |
| | | max: 1000, |
| | | detail: { |
| | |
| | | data: [ |
| | | { |
| | | value: parseFloat(cache.value.info.used_memory_human), |
| | | name: "å
åæ¶è" |
| | | name: 'å
åæ¶è' |
| | | } |
| | | ] |
| | | } |
| | | ] |
| | | }) |
| | | window.addEventListener("resize",()=>{ |
| | | commandstatsIntance.resize() |
| | | usedmemoryInstance.resize() |
| | | }); |
| | | } |
| | | window.addEventListener('resize', () => { |
| | | commandstatsIntance.resize(); |
| | | usedmemoryInstance.resize(); |
| | | }); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | getList(); |
| | | }) |
| | | }); |
| | | </script> |
| | |
| | | <template> |
| | | <div class="p-2"> |
| | | <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave"> |
| | | <div class="mb-[10px]" v-show="showSearch"> |
| | | <div v-show="showSearch" class="mb-[10px]"> |
| | | <el-card shadow="hover"> |
| | | <el-form :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px"> |
| | | <el-form ref="queryFormRef" :model="queryParams" :inline="true" label-width="68px"> |
| | | <el-form-item label="ç»å½å°å" prop="ipaddr"> |
| | | <el-input v-model="queryParams.ipaddr" placeholder="请è¾å
¥ç»å½å°å" clearable style="width: 240px;" @keyup.enter="handleQuery" /> |
| | | <el-input v-model="queryParams.ipaddr" placeholder="请è¾å
¥ç»å½å°å" clearable style="width: 240px" @keyup.enter="handleQuery" /> |
| | | </el-form-item> |
| | | <el-form-item label="ç¨æ·åç§°" prop="userName"> |
| | | <el-input v-model="queryParams.userName" placeholder="请è¾å
¥ç¨æ·åç§°" clearable style="width: 240px;" @keyup.enter="handleQuery" /> |
| | | <el-input v-model="queryParams.userName" placeholder="请è¾å
¥ç¨æ·åç§°" clearable style="width: 240px" @keyup.enter="handleQuery" /> |
| | | </el-form-item> |
| | | <el-form-item label="ç¶æ" prop="status"> |
| | | <el-select v-model="queryParams.status" placeholder="ç»å½ç¶æ" clearable style="width: 240px"> |
| | |
| | | <template #header> |
| | | <el-row :gutter="10" class="mb8"> |
| | | <el-col :span="1.5"> |
| | | <el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['monitor:logininfor:remove']"> |
| | | <el-button v-hasPermi="['monitor:logininfor:remove']" type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()"> |
| | | å é¤ |
| | | </el-button> |
| | | </el-col> |
| | | <el-col :span="1.5"> |
| | | <el-button type="danger" plain icon="Delete" @click="handleClean" v-hasPermi="['monitor:logininfor:remove']">æ¸
空</el-button> |
| | | <el-button v-hasPermi="['monitor:logininfor:remove']" type="danger" plain icon="Delete" @click="handleClean">æ¸
空</el-button> |
| | | </el-col> |
| | | <el-col :span="1.5"> |
| | | <el-button type="primary" plain icon="Unlock" :disabled="single" @click="handleUnlock" v-hasPermi="['monitor:logininfor:unlock']"> |
| | | <el-button v-hasPermi="['monitor:logininfor:unlock']" type="primary" plain icon="Unlock" :disabled="single" @click="handleUnlock"> |
| | | è§£é |
| | | </el-button> |
| | | </el-col> |
| | | <el-col :span="1.5"> |
| | | <el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['monitor:logininfor:export']">导åº</el-button> |
| | | <el-button v-hasPermi="['monitor:logininfor:export']" type="warning" plain icon="Download" @click="handleExport">导åº</el-button> |
| | | </el-col> |
| | | <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar> |
| | | <right-toolbar v-model:showSearch="showSearch" @query-table="getList"></right-toolbar> |
| | | </el-row> |
| | | </template> |
| | | |
| | |
| | | ref="loginInfoTableRef" |
| | | v-loading="loading" |
| | | :data="loginInfoList" |
| | | @selection-change="handleSelectionChange" |
| | | :default-sort="defaultSort" |
| | | @selection-change="handleSelectionChange" |
| | | @sort-change="handleSortChange" |
| | | > |
| | | <el-table-column type="selection" width="55" align="center" /> |
| | |
| | | </el-table-column> |
| | | </el-table> |
| | | |
| | | <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" /> |
| | | <pagination v-show="total > 0" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" :total="total" @pagination="getList" /> |
| | | </el-card> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup name="Logininfor" lang="ts"> |
| | | import { list, delLoginInfo, cleanLoginInfo, unlockLoginInfo } from "@/api/monitor/loginInfo"; |
| | | import { LoginInfoQuery, LoginInfoVO } from "@/api/monitor/loginInfo/types"; |
| | | import { list, delLoginInfo, cleanLoginInfo, unlockLoginInfo } from '@/api/monitor/loginInfo'; |
| | | import { LoginInfoQuery, LoginInfoVO } from '@/api/monitor/loginInfo/types'; |
| | | |
| | | const { proxy } = getCurrentInstance() as ComponentInternalInstance; |
| | | const { sys_device_type } = toRefs<any>(proxy?.useDict("sys_device_type")); |
| | | const { sys_common_status } = toRefs<any>(proxy?.useDict("sys_common_status")); |
| | | const { sys_device_type } = toRefs<any>(proxy?.useDict('sys_device_type')); |
| | | const { sys_common_status } = toRefs<any>(proxy?.useDict('sys_common_status')); |
| | | |
| | | const loginInfoList = ref<LoginInfoVO[]>([]); |
| | | const loading = ref(true); |
| | |
| | | const multiple = ref(true); |
| | | const selectName = ref<Array<string>>([]); |
| | | const total = ref(0); |
| | | const dateRange = ref<[DateModelType,DateModelType]>(['', '']); |
| | | const defaultSort = ref<any>({ prop: "loginTime", order: "descending" }); |
| | | const dateRange = ref<[DateModelType, DateModelType]>(['', '']); |
| | | const defaultSort = ref<any>({ prop: 'loginTime', order: 'descending' }); |
| | | |
| | | const queryFormRef = ref<ElFormInstance>(); |
| | | const loginInfoTableRef = ref<ElTableInstance>(); |
| | | // æ¥è¯¢åæ° |
| | | const queryParams = ref<LoginInfoQuery>({ |
| | | pageNum: 1, |
| | | pageSize: 10, |
| | | ipaddr: '', |
| | | userName: '', |
| | | status: '', |
| | | orderByColumn: defaultSort.value.prop, |
| | | isAsc: defaultSort.value.order |
| | | pageNum: 1, |
| | | pageSize: 10, |
| | | ipaddr: '', |
| | | userName: '', |
| | | status: '', |
| | | orderByColumn: defaultSort.value.prop, |
| | | isAsc: defaultSort.value.order |
| | | }); |
| | | |
| | | /** æ¥è¯¢ç»å½æ¥å¿å表 */ |
| | | const getList = async () => { |
| | | loading.value = true; |
| | | const res = await list(proxy?.addDateRange(queryParams.value, dateRange.value)); |
| | | loginInfoList.value = res.rows; |
| | | total.value = res.total; |
| | | loading.value = false; |
| | | } |
| | | loading.value = true; |
| | | const res = await list(proxy?.addDateRange(queryParams.value, dateRange.value)); |
| | | loginInfoList.value = res.rows; |
| | | total.value = res.total; |
| | | loading.value = false; |
| | | }; |
| | | /** æç´¢æé®æä½ */ |
| | | const handleQuery = () => { |
| | | queryParams.value.pageNum = 1; |
| | | getList(); |
| | | } |
| | | queryParams.value.pageNum = 1; |
| | | getList(); |
| | | }; |
| | | /** éç½®æé®æä½ */ |
| | | const resetQuery = () => { |
| | | dateRange.value = ['', '']; |
| | | queryFormRef.value?.resetFields(); |
| | | queryParams.value.pageNum = 1; |
| | | loginInfoTableRef.value?.sort(defaultSort.value.prop, defaultSort.value.order); |
| | | } |
| | | dateRange.value = ['', '']; |
| | | queryFormRef.value?.resetFields(); |
| | | queryParams.value.pageNum = 1; |
| | | loginInfoTableRef.value?.sort(defaultSort.value.prop, defaultSort.value.order); |
| | | }; |
| | | /** å¤éæ¡é䏿°æ® */ |
| | | const handleSelectionChange = (selection: LoginInfoVO[]) => { |
| | | ids.value = selection.map(item => item.infoId); |
| | | multiple.value = !selection.length; |
| | | single.value = selection.length != 1; |
| | | selectName.value = selection.map(item => item.userName); |
| | | } |
| | | ids.value = selection.map((item) => item.infoId); |
| | | multiple.value = !selection.length; |
| | | single.value = selection.length != 1; |
| | | selectName.value = selection.map((item) => item.userName); |
| | | }; |
| | | /** æåºè§¦åäºä»¶ */ |
| | | const handleSortChange = (column: any) => { |
| | | queryParams.value.orderByColumn = column.prop; |
| | | queryParams.value.isAsc = column.order; |
| | | getList(); |
| | | } |
| | | queryParams.value.orderByColumn = column.prop; |
| | | queryParams.value.isAsc = column.order; |
| | | getList(); |
| | | }; |
| | | /** å é¤æé®æä½ */ |
| | | const handleDelete = async (row?: LoginInfoVO) => { |
| | | const infoIds = row?.infoId || ids.value; |
| | | await proxy?.$modal.confirm('æ¯å¦ç¡®è®¤å é¤è®¿é®ç¼å·ä¸º"' + infoIds + '"çæ°æ®é¡¹?'); |
| | | await delLoginInfo(infoIds); |
| | | await getList(); |
| | | proxy?.$modal.msgSuccess("å 餿å"); |
| | | } |
| | | const infoIds = row?.infoId || ids.value; |
| | | await proxy?.$modal.confirm('æ¯å¦ç¡®è®¤å é¤è®¿é®ç¼å·ä¸º"' + infoIds + '"çæ°æ®é¡¹?'); |
| | | await delLoginInfo(infoIds); |
| | | await getList(); |
| | | proxy?.$modal.msgSuccess('å 餿å'); |
| | | }; |
| | | /** æ¸
空æé®æä½ */ |
| | | const handleClean = async () => { |
| | | await proxy?.$modal.confirm("æ¯å¦ç¡®è®¤æ¸
空ææç»å½æ¥å¿æ°æ®é¡¹?"); |
| | | await cleanLoginInfo(); |
| | | await getList(); |
| | | proxy?.$modal.msgSuccess("æ¸
空æå"); |
| | | } |
| | | await proxy?.$modal.confirm('æ¯å¦ç¡®è®¤æ¸
空ææç»å½æ¥å¿æ°æ®é¡¹?'); |
| | | await cleanLoginInfo(); |
| | | await getList(); |
| | | proxy?.$modal.msgSuccess('æ¸
空æå'); |
| | | }; |
| | | /** è§£éæé®æä½ */ |
| | | const handleUnlock = async () => { |
| | | const username = selectName.value; |
| | | await proxy?.$modal.confirm('æ¯å¦ç¡®è®¤è§£éç¨æ·"' + username + '"æ°æ®é¡¹?'); |
| | | await unlockLoginInfo(username); |
| | | proxy?.$modal.msgSuccess("ç¨æ·" + username + "è§£éæå"); |
| | | } |
| | | const username = selectName.value; |
| | | await proxy?.$modal.confirm('æ¯å¦ç¡®è®¤è§£éç¨æ·"' + username + '"æ°æ®é¡¹?'); |
| | | await unlockLoginInfo(username); |
| | | proxy?.$modal.msgSuccess('ç¨æ·' + username + 'è§£éæå'); |
| | | }; |
| | | /** å¯¼åºæé®æä½ */ |
| | | const handleExport = () => { |
| | | proxy?.download("monitor/logininfor/export", { |
| | | ...queryParams.value, |
| | | }, `config_${new Date().getTime()}.xlsx`); |
| | | } |
| | | proxy?.download( |
| | | 'monitor/logininfor/export', |
| | | { |
| | | ...queryParams.value |
| | | }, |
| | | `config_${new Date().getTime()}.xlsx` |
| | | ); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | getList(); |
| | | }) |
| | | getList(); |
| | | }); |
| | | </script> |
| | |
| | | <div class="p-2"> |
| | | <div class="mb-[10px]"> |
| | | <el-card shadow="hover"> |
| | | <el-form :model="queryParams" ref="queryFormRef" :inline="true"> |
| | | <el-form ref="queryFormRef" :model="queryParams" :inline="true"> |
| | | <el-form-item label="ç»å½å°å" prop="ipaddr"> |
| | | <el-input v-model="queryParams.ipaddr" placeholder="请è¾å
¥ç»å½å°å" clearable style="width: 200px" @keyup.enter="handleQuery" /> |
| | | </el-form-item> |
| | |
| | | <el-table |
| | | v-loading="loading" |
| | | :data="onlineList.slice((queryParams.pageNum - 1) * queryParams.pageSize, queryParams.pageNum * queryParams.pageSize)" |
| | | style="width: 100%;" |
| | | style="width: 100%" |
| | | > |
| | | <el-table-column label="åºå·" width="50" type="index" align="center"> |
| | | <template #default="scope"> |
| | |
| | | <el-table-column label="æä½" align="center" class-name="small-padding fixed-width"> |
| | | <template #default="scope"> |
| | | <el-tooltip content="强é" placement="top"> |
| | | <el-button link type="primary" icon="Delete" @click="handleForceLogout(scope.row)" v-hasPermi="['monitor:online:forceLogout']"> |
| | | <el-button v-hasPermi="['monitor:online:forceLogout']" link type="primary" icon="Delete" @click="handleForceLogout(scope.row)"> |
| | | </el-button> |
| | | </el-tooltip> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | |
| | | <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" /> |
| | | <pagination v-show="total > 0" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" :total="total" /> |
| | | </el-card> |
| | | </div> |
| | | </template> |
| | |
| | | import {to} from "await-to-js"; |
| | | |
| | | const { proxy } = getCurrentInstance() as ComponentInternalInstance; |
| | | const { sys_device_type } = toRefs<any>(proxy?.useDict("sys_device_type")); |
| | | const { sys_device_type } = toRefs<any>(proxy?.useDict('sys_device_type')); |
| | | |
| | | const onlineList = ref<OnlineVO[]>([]); |
| | | const loading = ref(true); |
| | |
| | | onlineList.value = res.rows; |
| | | total.value = res.total; |
| | | loading.value = false; |
| | | } |
| | | }; |
| | | /** æç´¢æé®æä½ */ |
| | | const handleQuery = () => { |
| | | queryParams.value.pageNum = 1; |
| | | getList(); |
| | | } |
| | | }; |
| | | /** éç½®æé®æä½ */ |
| | | const resetQuery = () => { |
| | | queryFormRef.value?.resetFields(); |
| | | handleQuery(); |
| | | } |
| | | }; |
| | | /** 强éæé®æä½ */ |
| | | const handleForceLogout = async (row: OnlineVO) => { |
| | | const [err] = await to(proxy?.$modal.confirm('æ¯å¦ç¡®è®¤å¼ºéå称为"' + row.userName + '"çç¨æ·?') as any); |
| | |
| | | |
| | | onMounted(() => { |
| | | getList(); |
| | | }) |
| | | }); |
| | | </script> |
| | |
| | | <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave"> |
| | | <div class="mb-[10px]"> |
| | | <el-card shadow="hover"> |
| | | <el-form :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px"> |
| | | <el-form ref="queryFormRef" :model="queryParams" :inline="true" label-width="68px"> |
| | | <el-form-item label="æä½å°å" prop="operIp"> |
| | | <el-input v-model="queryParams.operIp" placeholder="请è¾å
¥æä½å°å" clearable style="width: 240px;" @keyup.enter="handleQuery"/> |
| | | <el-input v-model="queryParams.operIp" placeholder="请è¾å
¥æä½å°å" clearable style="width: 240px" @keyup.enter="handleQuery" /> |
| | | </el-form-item> |
| | | <el-form-item label="ç³»ç»æ¨¡å" prop="title"> |
| | | <el-input v-model="queryParams.title" placeholder="请è¾å
¥ç³»ç»æ¨¡å" clearable style="width: 240px;" @keyup.enter="handleQuery" /> |
| | | <el-input v-model="queryParams.title" placeholder="请è¾å
¥ç³»ç»æ¨¡å" clearable style="width: 240px" @keyup.enter="handleQuery" /> |
| | | </el-form-item> |
| | | <el-form-item label="æä½äººå" prop="operName"> |
| | | <el-input v-model="queryParams.operName" placeholder="请è¾å
¥æä½äººå" clearable style="width: 240px;" @keyup.enter="handleQuery" /> |
| | | <el-input v-model="queryParams.operName" placeholder="请è¾å
¥æä½äººå" clearable style="width: 240px" @keyup.enter="handleQuery" /> |
| | | </el-form-item> |
| | | <el-form-item label="ç±»å" prop="businessType"> |
| | | <el-select v-model="queryParams.businessType" placeholder="æä½ç±»å" clearable style="width: 240px"> |
| | |
| | | <template #header> |
| | | <el-row :gutter="10" class="mb8"> |
| | | <el-col :span="1.5"> |
| | | <el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['monitor:operlog:remove']"> |
| | | <el-button v-hasPermi="['monitor:operlog:remove']" type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()"> |
| | | å é¤ |
| | | </el-button> |
| | | </el-col> |
| | | <el-col :span="1.5"> |
| | | <el-button type="danger" plain icon="WarnTriangleFilled" @click="handleClean" v-hasPermi="['monitor:operlog:remove']">æ¸
空</el-button> |
| | | <el-button v-hasPermi="['monitor:operlog:remove']" type="danger" plain icon="WarnTriangleFilled" @click="handleClean">æ¸
空</el-button> |
| | | </el-col> |
| | | <el-col :span="1.5"> |
| | | <el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['monitor:operlog:export']">导åº</el-button> |
| | | <el-button v-hasPermi="['monitor:operlog:export']" type="warning" plain icon="Download" @click="handleExport">导åº</el-button> |
| | | </el-col> |
| | | <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar> |
| | | <right-toolbar v-model:showSearch="showSearch" @query-table="getList"></right-toolbar> |
| | | </el-row> |
| | | </template> |
| | | |
| | |
| | | ref="operLogTableRef" |
| | | v-loading="loading" |
| | | :data="operlogList" |
| | | @selection-change="handleSelectionChange" |
| | | :default-sort="defaultSort" |
| | | @selection-change="handleSelectionChange" |
| | | @sort-change="handleSortChange" |
| | | > |
| | | <el-table-column type="selection" width="50" align="center" /> |
| | |
| | | <el-table-column label="æä½" fixed="right" align="center" class-name="small-padding fixed-width"> |
| | | <template #default="scope"> |
| | | <el-tooltip content="详ç»" placement="top"> |
| | | <el-button link type="primary" icon="View" @click="handleView(scope.row)" v-hasPermi="['monitor:operlog:query']"> </el-button> |
| | | <el-button v-hasPermi="['monitor:operlog:query']" link type="primary" icon="View" @click="handleView(scope.row)"> </el-button> |
| | | </el-tooltip> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | |
| | | <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" /> |
| | | <pagination v-show="total > 0" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" :total="total" @pagination="getList" /> |
| | | </el-card> |
| | | <!-- æä½æ¥å¿è¯¦ç» --> |
| | | <el-dialog title="æä½æ¥å¿è¯¦ç»" v-model="dialog.visible" width="700px" append-to-body> |
| | | <el-dialog v-model="dialog.visible" title="æä½æ¥å¿è¯¦ç»" width="700px" append-to-body> |
| | | <el-form :model="form" label-width="100px"> |
| | | <el-row> |
| | | <el-col :span="24"> |
| | | <el-form-item label="ç»å½ä¿¡æ¯ï¼">{{ form.operName }} / {{form.deptName}} / {{ form.operIp }} / {{ form.operLocation }}</el-form-item> |
| | | <el-form-item label="ç»å½ä¿¡æ¯ï¼">{{ form.operName }} / {{ form.deptName }} / {{ form.operIp }} / {{ form.operLocation }}</el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="请æ±ä¿¡æ¯ï¼">{{ form.requestMethod }} {{ form.operUrl }}</el-form-item> |
| | |
| | | <el-form-item label="æä½æ¶é´ï¼">{{ parseTime(form.operTime) }}</el-form-item> |
| | | </el-col> |
| | | <el-col :span="24"> |
| | | <el-form-item label="å¼å¸¸ä¿¡æ¯ï¼" v-if="form.status === 1">{{ form.errorMsg }}</el-form-item> |
| | | <el-form-item v-if="form.status === 1" label="å¼å¸¸ä¿¡æ¯ï¼">{{ form.errorMsg }}</el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | |
| | | import { OperLogForm, OperLogQuery, OperLogVO } from '@/api/monitor/operlog/types'; |
| | | |
| | | const { proxy } = getCurrentInstance() as ComponentInternalInstance; |
| | | const { sys_oper_type, sys_common_status } = toRefs<any>(proxy?.useDict("sys_oper_type", "sys_common_status")); |
| | | const { sys_oper_type, sys_common_status } = toRefs<any>(proxy?.useDict('sys_oper_type', 'sys_common_status')); |
| | | |
| | | const operlogList = ref<OperLogVO[]>([]); |
| | | const loading = ref(true); |
| | |
| | | const multiple = ref(true); |
| | | const total = ref(0); |
| | | const dateRange = ref<[DateModelType, DateModelType]>(['', '']); |
| | | const defaultSort = ref<any>({ prop: "operTime", order: "descending" }); |
| | | const defaultSort = ref<any>({ prop: 'operTime', order: 'descending' }); |
| | | |
| | | const operLogTableRef = ref<ElTableInstance>(); |
| | | const queryFormRef = ref<ElFormInstance>(); |
| | |
| | | visible: false, |
| | | title: '' |
| | | }); |
| | | |
| | | |
| | | const data = reactive<PageData<OperLogForm, OperLogQuery>>({ |
| | | form: { |
| | |
| | | operlogList.value = res.rows; |
| | | total.value = res.total; |
| | | loading.value = false; |
| | | } |
| | | }; |
| | | /** æä½æ¥å¿ç±»ååå
¸ç¿»è¯ */ |
| | | const typeFormat = (row: OperLogForm) => { |
| | | return proxy?.selectDictLabel(sys_oper_type.value, row.businessType); |
| | | } |
| | | }; |
| | | /** æç´¢æé®æä½ */ |
| | | const handleQuery = () => { |
| | | queryParams.value.pageNum = 1; |
| | | getList(); |
| | | } |
| | | }; |
| | | /** éç½®æé®æä½ */ |
| | | const resetQuery = () => { |
| | | dateRange.value = ['', '']; |
| | | queryFormRef.value?.resetFields(); |
| | | queryParams.value.pageNum = 1; |
| | | operLogTableRef.value?.sort(defaultSort.value.prop, defaultSort.value.order); |
| | | } |
| | | }; |
| | | /** å¤éæ¡é䏿°æ® */ |
| | | const handleSelectionChange = (selection: OperLogVO[]) => { |
| | | ids.value = selection.map(item => item.operId); |
| | | ids.value = selection.map((item) => item.operId); |
| | | multiple.value = !selection.length; |
| | | } |
| | | }; |
| | | /** æåºè§¦åäºä»¶ */ |
| | | const handleSortChange = (column: any) => { |
| | | queryParams.value.orderByColumn = column.prop; |
| | | queryParams.value.isAsc = column.order; |
| | | getList(); |
| | | } |
| | | }; |
| | | /** è¯¦ç»æé®æä½ */ |
| | | const handleView = (row: OperLogVO) => { |
| | | dialog.visible = true; |
| | | form.value = row; |
| | | } |
| | | }; |
| | | /** å é¤æé®æä½ */ |
| | | const handleDelete = async (row?: OperLogVO) => { |
| | | const operIds = row?.operId || ids.value; |
| | | await proxy?.$modal.confirm('æ¯å¦ç¡®è®¤å 餿¥å¿ç¼å·ä¸º"' + operIds + '"çæ°æ®é¡¹?'); |
| | | await delOperlog(operIds); |
| | | await getList(); |
| | | proxy?.$modal.msgSuccess("å 餿å"); |
| | | } |
| | | proxy?.$modal.msgSuccess('å 餿å'); |
| | | }; |
| | | |
| | | /** æ¸
空æé®æä½ */ |
| | | const handleClean = async () => { |
| | | await proxy?.$modal.confirm("æ¯å¦ç¡®è®¤æ¸
ç©ºæææä½æ¥å¿æ°æ®é¡¹?"); |
| | | await proxy?.$modal.confirm('æ¯å¦ç¡®è®¤æ¸
ç©ºæææä½æ¥å¿æ°æ®é¡¹?'); |
| | | await cleanOperlog(); |
| | | await getList(); |
| | | proxy?.$modal.msgSuccess("æ¸
空æå"); |
| | | } |
| | | proxy?.$modal.msgSuccess('æ¸
空æå'); |
| | | }; |
| | | |
| | | /** å¯¼åºæé®æä½ */ |
| | | const handleExport = () => { |
| | | proxy?.download("monitor/operlog/export", { |
| | | ...queryParams.value, |
| | | }, `config_${new Date().getTime()}.xlsx`); |
| | | } |
| | | proxy?.download( |
| | | 'monitor/operlog/export', |
| | | { |
| | | ...queryParams.value |
| | | }, |
| | | `config_${new Date().getTime()}.xlsx` |
| | | ); |
| | | }; |
| | | onMounted(() => { |
| | | getList(); |
| | | }) |
| | | }); |
| | | </script> |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { useRoute, useRouter } from 'vue-router' |
| | | import { useRoute, useRouter } from 'vue-router'; |
| | | |
| | | const route = useRoute(); |
| | | const router = useRouter(); |
| | | const { params, query } = route |
| | | const { path } = params |
| | | const { params, query } = route; |
| | | const { path } = params; |
| | | |
| | | router.replace({ path: '/' + path, query }) |
| | | router.replace({ path: '/' + path, query }); |
| | | </script> |
| | |
| | | <div class="register"> |
| | | <el-form ref="registerRef" :model="registerForm" :rules="registerRules" class="register-form"> |
| | | <h3 class="title">RuoYi-Vue-Pluså¤ç§æ·ç®¡çç³»ç»</h3> |
| | | <el-form-item prop="tenantId" v-if="tenantEnabled"> |
| | | <el-form-item v-if="tenantEnabled" prop="tenantId"> |
| | | <el-select v-model="registerForm.tenantId" filterable placeholder="è¯·éæ©/è¾å
¥å
¬å¸åç§°" style="width: 100%"> |
| | | <el-option v-for="item in tenantList" :key="item.tenantId" :label="item.companyName" :value="item.tenantId"> </el-option> |
| | | <template #prefix><svg-icon icon-class="company" class="el-input__icon input-icon" /></template> |
| | |
| | | <template #prefix><svg-icon icon-class="password" class="el-input__icon input-icon" /></template> |
| | | </el-input> |
| | | </el-form-item> |
| | | <el-form-item prop="code" v-if="captchaEnabled"> |
| | | <el-input size="large" v-model="registerForm.code" auto-complete="off" placeholder="éªè¯ç " style="width: 63%" @keyup.enter="handleRegister"> |
| | | <el-form-item v-if="captchaEnabled" prop="code"> |
| | | <el-input v-model="registerForm.code" size="large" auto-complete="off" placeholder="éªè¯ç " style="width: 63%" @keyup.enter="handleRegister"> |
| | | <template #prefix><svg-icon icon-class="validCode" class="el-input__icon input-icon" /></template> |
| | | </el-input> |
| | | <div class="register-code"> |
| | | <img :src="codeUrl" @click="getCode" class="register-code-img" /> |
| | | <img :src="codeUrl" class="register-code-img" @click="getCode" /> |
| | | </div> |
| | | </el-form-item> |
| | | <el-form-item style="width:100%;"> |
| | | <el-button :loading="loading" size="large" type="primary" style="width:100%;" @click.prevent="handleRegister"> |
| | | <el-form-item style="width: 100%"> |
| | | <el-button :loading="loading" size="large" type="primary" style="width: 100%" @click.prevent="handleRegister"> |
| | | <span v-if="!loading">注 å</span> |
| | | <span v-else>注 å ä¸...</span> |
| | | </el-button> |
| | | <div style="float: right;"> |
| | | <div style="float: right"> |
| | | <router-link class="link-type" :to="'/login'">使ç¨å·²æè´¦æ·ç»å½</router-link> |
| | | </div> |
| | | </el-form-item> |
| | |
| | | const router = useRouter(); |
| | | |
| | | const registerForm = ref<RegisterForm>({ |
| | | tenantId: "", |
| | | username: "", |
| | | password: "", |
| | | confirmPassword: "", |
| | | code: "", |
| | | uuid: "", |
| | | userType: "sys_user" |
| | | tenantId: '', |
| | | username: '', |
| | | password: '', |
| | | confirmPassword: '', |
| | | code: '', |
| | | uuid: '', |
| | | userType: 'sys_user' |
| | | }); |
| | | |
| | | // ç§æ·å¼å
³ |
| | | const tenantEnabled = ref(true); |
| | | |
| | | |
| | | const equalToPassword = (rule: any, value: string, callback: any) => { |
| | | if (registerForm.value.password !== value) { |
| | | callback(new Error("两次è¾å
¥çå¯ç ä¸ä¸è´")); |
| | | callback(new Error('两次è¾å
¥çå¯ç ä¸ä¸è´')); |
| | | } else { |
| | | callback(); |
| | | } |
| | | }; |
| | | |
| | | const registerRules: ElFormRules = { |
| | | tenantId: [ |
| | | { required: true, trigger: "blur", message: "请è¾å
¥æ¨çç§æ·ç¼å·" } |
| | | ], |
| | | tenantId: [{ required: true, trigger: 'blur', message: '请è¾å
¥æ¨çç§æ·ç¼å·' }], |
| | | username: [ |
| | | { required: true, trigger: "blur", message: "请è¾å
¥æ¨çè´¦å·" }, |
| | | { min: 2, max: 20, message: "ç¨æ·è´¦å·é¿åº¦å¿
é¡»ä»äº 2 å 20 ä¹é´", trigger: "blur" } |
| | | { required: true, trigger: 'blur', message: '请è¾å
¥æ¨çè´¦å·' }, |
| | | { min: 2, max: 20, message: 'ç¨æ·è´¦å·é¿åº¦å¿
é¡»ä»äº 2 å 20 ä¹é´', trigger: 'blur' } |
| | | ], |
| | | password: [ |
| | | { required: true, trigger: "blur", message: "请è¾å
¥æ¨çå¯ç " }, |
| | | { min: 5, max: 20, message: "ç¨æ·å¯ç é¿åº¦å¿
é¡»ä»äº 5 å 20 ä¹é´", trigger: "blur" } |
| | | { required: true, trigger: 'blur', message: '请è¾å
¥æ¨çå¯ç ' }, |
| | | { min: 5, max: 20, message: 'ç¨æ·å¯ç é¿åº¦å¿
é¡»ä»äº 5 å 20 ä¹é´', trigger: 'blur' } |
| | | ], |
| | | confirmPassword: [ |
| | | { required: true, trigger: "blur", message: "è¯·åæ¬¡è¾å
¥æ¨çå¯ç " }, |
| | | { required: true, validator: equalToPassword, trigger: "blur" } |
| | | { required: true, trigger: 'blur', message: 'è¯·åæ¬¡è¾å
¥æ¨çå¯ç ' }, |
| | | { required: true, validator: equalToPassword, trigger: 'blur' } |
| | | ], |
| | | code: [{ required: true, trigger: "change", message: "请è¾å
¥éªè¯ç " }] |
| | | code: [{ required: true, trigger: 'change', message: '请è¾å
¥éªè¯ç ' }] |
| | | }; |
| | | const codeUrl = ref(""); |
| | | const codeUrl = ref(''); |
| | | const loading = ref(false); |
| | | const captchaEnabled = ref(true); |
| | | const registerRef = ref<ElFormInstance>(); |
| | |
| | | const [err] = await to(register(registerForm.value)); |
| | | if (!err) { |
| | | const username = registerForm.value.username; |
| | | await ElMessageBox.alert("<font color='red'>æåä½ ï¼æ¨çè´¦å· " + username + " 注åæåï¼</font>", "ç³»ç»æç¤º", { |
| | | await ElMessageBox.alert("<font color='red'>æåä½ ï¼æ¨çè´¦å· " + username + ' 注åæåï¼</font>', 'ç³»ç»æç¤º', { |
| | | dangerouslyUseHTMLString: true, |
| | | type: "success", |
| | | type: 'success' |
| | | }); |
| | | await router.push("/login"); |
| | | await router.push('/login'); |
| | | } else { |
| | | loading.value = false; |
| | | if (captchaEnabled) { |
| | |
| | | } |
| | | } |
| | | }); |
| | | } |
| | | }; |
| | | |
| | | const getCode = async () => { |
| | | const res = await getCodeImg(); |
| | |
| | | registerForm.value.tenantId = tenantList.value[0].tenantId; |
| | | } |
| | | } |
| | | } |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | getCode(); |
| | | initTenantList(); |
| | | }) |
| | | }); |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | |
| | | justify-content: center; |
| | | align-items: center; |
| | | height: 100%; |
| | | background-image: url("../assets/images/login-background.jpg"); |
| | | background-image: url('../assets/images/login-background.jpg'); |
| | | background-size: cover; |
| | | } |
| | | |
| | |
| | | <template> |
| | | <div class="p-2"> |
| | | <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave"> |
| | | <div class="search" v-show="showSearch"> |
| | | <el-form :model="queryParams" ref="queryFormRef" :inline="true" label-width="100px"> |
| | | <div v-show="showSearch" class="search"> |
| | | <el-form ref="queryFormRef" :model="queryParams" :inline="true" label-width="100px"> |
| | | <el-form-item label="客æ·ç«¯key" prop="clientKey"> |
| | | <el-input v-model="queryParams.clientKey" placeholder="请è¾å
¥å®¢æ·ç«¯key" clearable style="width: 240px" @keyup.enter="handleQuery" /> |
| | | </el-form-item> |
| | |
| | | <template #header> |
| | | <el-row :gutter="10" class="mb8"> |
| | | <el-col :span="1.5"> |
| | | <el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['system:client:add']">æ°å¢</el-button> |
| | | <el-button v-hasPermi="['system:client:add']" type="primary" plain icon="Plus" @click="handleAdd">æ°å¢</el-button> |
| | | </el-col> |
| | | <el-col :span="1.5"> |
| | | <el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['system:client:edit']"> |
| | | <el-button v-hasPermi="['system:client:edit']" type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()"> |
| | | ä¿®æ¹ |
| | | </el-button> |
| | | </el-col> |
| | | <el-col :span="1.5"> |
| | | <el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['system:client:remove']"> |
| | | <el-button v-hasPermi="['system:client:remove']" type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()"> |
| | | å é¤ |
| | | </el-button> |
| | | </el-col> |
| | | <el-col :span="1.5"> |
| | | <el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['system:client:export']">导åº</el-button> |
| | | <el-button v-hasPermi="['system:client:export']" type="warning" plain icon="Download" @click="handleExport">导åº</el-button> |
| | | </el-col> |
| | | <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar> |
| | | <right-toolbar v-model:showSearch="showSearch" @query-table="getList"></right-toolbar> |
| | | </el-row> |
| | | </template> |
| | | |
| | | <el-table v-loading="loading" :data="clientList" @selection-change="handleSelectionChange"> |
| | | <el-table-column type="selection" width="55" align="center" /> |
| | | <el-table-column label="id" align="center" prop="id" v-if="true" /> |
| | | <el-table-column v-if="true" label="id" align="center" prop="id" /> |
| | | <el-table-column label="客æ·ç«¯id" align="center" prop="clientId" /> |
| | | <el-table-column label="客æ·ç«¯key" align="center" prop="clientKey" /> |
| | | <el-table-column label="客æ·ç«¯ç§é¥" align="center" prop="clientSecret" /> |
| | |
| | | </el-table-column> |
| | | <el-table-column label="Tokenæ´»è·è¶
æ¶æ¶é´" align="center" prop="activeTimeout" /> |
| | | <el-table-column label="Tokenåºå®è¶
æ¶æ¶é´" align="center" prop="timeout" /> |
| | | <el-table-column label="ç¶æ" align="center" key="status"> |
| | | <el-table-column key="status" label="ç¶æ" align="center"> |
| | | <template #default="scope"> |
| | | <el-switch v-model="scope.row.status" active-value="0" inactive-value="1" @change="handleStatusChange(scope.row)"></el-switch> |
| | | </template> |
| | |
| | | <el-table-column label="æä½" align="center" class-name="small-padding fixed-width"> |
| | | <template #default="scope"> |
| | | <el-tooltip content="ä¿®æ¹" placement="top"> |
| | | <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['system:client:edit']"></el-button> |
| | | <el-button v-hasPermi="['system:client:edit']" link type="primary" icon="Edit" @click="handleUpdate(scope.row)"></el-button> |
| | | </el-tooltip> |
| | | <el-tooltip content="å é¤" placement="top"> |
| | | <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['system:client:remove']"></el-button> |
| | | <el-button v-hasPermi="['system:client:remove']" link type="primary" icon="Delete" @click="handleDelete(scope.row)"></el-button> |
| | | </el-tooltip> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | |
| | | <pagination v-show="total>0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" /> |
| | | <pagination v-show="total > 0" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" :total="total" @pagination="getList" /> |
| | | </el-card> |
| | | <!-- æ·»å æä¿®æ¹å®¢æ·ç«¯ç®¡çå¯¹è¯æ¡ --> |
| | | <el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body> |
| | | <el-dialog v-model="dialog.visible" :title="dialog.title" width="500px" append-to-body> |
| | | <el-form ref="clientFormRef" :model="form" :rules="rules" label-width="100px"> |
| | | <el-form-item label="客æ·ç«¯key" prop="clientKey"> |
| | | <el-input v-model="form.clientKey" :disabled="form.id != null" placeholder="请è¾å
¥å®¢æ·ç«¯key" /> |
| | |
| | | import { ClientVO, ClientQuery, ClientForm } from '@/api/system/client/types'; |
| | | |
| | | const { proxy } = getCurrentInstance() as ComponentInternalInstance; |
| | | const { sys_normal_disable } = toRefs<any>(proxy?.useDict("sys_normal_disable")); |
| | | const { sys_grant_type } = toRefs<any>(proxy?.useDict("sys_grant_type")); |
| | | const { sys_device_type } = toRefs<any>(proxy?.useDict("sys_device_type")); |
| | | const { sys_normal_disable } = toRefs<any>(proxy?.useDict('sys_normal_disable')); |
| | | const { sys_grant_type } = toRefs<any>(proxy?.useDict('sys_grant_type')); |
| | | const { sys_device_type } = toRefs<any>(proxy?.useDict('sys_device_type')); |
| | | |
| | | const clientList = ref<ClientVO[]>([]); |
| | | const buttonLoading = ref(false); |
| | |
| | | deviceType: undefined, |
| | | activeTimeout: undefined, |
| | | timeout: undefined, |
| | | status: undefined, |
| | | } |
| | | status: undefined |
| | | }; |
| | | const data = reactive<PageData<ClientForm, ClientQuery>>({ |
| | | form: {...initFormData}, |
| | | form: { ...initFormData }, |
| | | queryParams: { |
| | | pageNum: 1, |
| | | pageSize: 10, |
| | |
| | | deviceType: undefined, |
| | | activeTimeout: undefined, |
| | | timeout: undefined, |
| | | status: undefined, |
| | | status: undefined |
| | | }, |
| | | rules: { |
| | | id: [ |
| | | { required: true, message: "idä¸è½ä¸ºç©º", trigger: "blur" } |
| | | ], |
| | | clientId: [ |
| | | { required: true, message: "客æ·ç«¯idä¸è½ä¸ºç©º", trigger: "blur" } |
| | | ], |
| | | clientKey: [ |
| | | { required: true, message: "客æ·ç«¯keyä¸è½ä¸ºç©º", trigger: "blur" } |
| | | ], |
| | | clientSecret: [ |
| | | { required: true, message: "客æ·ç«¯ç§é¥ä¸è½ä¸ºç©º", trigger: "blur" } |
| | | ], |
| | | grantTypeList: [ |
| | | { required: true, message: "ææç±»åä¸è½ä¸ºç©º", trigger: "change" } |
| | | ], |
| | | deviceType: [ |
| | | { required: true, message: "设å¤ç±»åä¸è½ä¸ºç©º", trigger: "change" } |
| | | ], |
| | | id: [{ required: true, message: 'idä¸è½ä¸ºç©º', trigger: 'blur' }], |
| | | clientId: [{ required: true, message: '客æ·ç«¯idä¸è½ä¸ºç©º', trigger: 'blur' }], |
| | | clientKey: [{ required: true, message: '客æ·ç«¯keyä¸è½ä¸ºç©º', trigger: 'blur' }], |
| | | clientSecret: [{ required: true, message: '客æ·ç«¯ç§é¥ä¸è½ä¸ºç©º', trigger: 'blur' }], |
| | | grantTypeList: [{ required: true, message: 'ææç±»åä¸è½ä¸ºç©º', trigger: 'change' }], |
| | | deviceType: [{ required: true, message: '设å¤ç±»åä¸è½ä¸ºç©º', trigger: 'change' }] |
| | | } |
| | | }); |
| | | |
| | |
| | | clientList.value = res.rows; |
| | | total.value = res.total; |
| | | loading.value = false; |
| | | } |
| | | }; |
| | | |
| | | /** åæ¶æé® */ |
| | | const cancel = () => { |
| | | reset(); |
| | | dialog.visible = false; |
| | | } |
| | | }; |
| | | |
| | | /** 表åéç½® */ |
| | | const reset = () => { |
| | | form.value = {...initFormData}; |
| | | form.value = { ...initFormData }; |
| | | clientFormRef.value?.resetFields(); |
| | | } |
| | | }; |
| | | |
| | | /** æç´¢æé®æä½ */ |
| | | const handleQuery = () => { |
| | | queryParams.value.pageNum = 1; |
| | | getList(); |
| | | } |
| | | }; |
| | | |
| | | /** éç½®æé®æä½ */ |
| | | const resetQuery = () => { |
| | | queryFormRef.value?.resetFields(); |
| | | handleQuery(); |
| | | } |
| | | }; |
| | | |
| | | /** å¤éæ¡é䏿°æ® */ |
| | | const handleSelectionChange = (selection: ClientVO[]) => { |
| | | ids.value = selection.map(item => item.id); |
| | | ids.value = selection.map((item) => item.id); |
| | | single.value = selection.length != 1; |
| | | multiple.value = !selection.length; |
| | | } |
| | | }; |
| | | |
| | | /** æ°å¢æé®æä½ */ |
| | | const handleAdd = () => { |
| | | reset(); |
| | | dialog.visible = true; |
| | | dialog.title = "æ·»å 客æ·ç«¯ç®¡ç"; |
| | | } |
| | | dialog.title = 'æ·»å 客æ·ç«¯ç®¡ç'; |
| | | }; |
| | | |
| | | /** ä¿®æ¹æé®æä½ */ |
| | | const handleUpdate = async (row?: ClientVO) => { |
| | | reset(); |
| | | const _id = row?.id || ids.value[0] |
| | | const _id = row?.id || ids.value[0]; |
| | | const res = await getClient(_id); |
| | | Object.assign(form.value, res.data); |
| | | dialog.visible = true; |
| | | dialog.title = "ä¿®æ¹å®¢æ·ç«¯ç®¡ç"; |
| | | } |
| | | dialog.title = 'ä¿®æ¹å®¢æ·ç«¯ç®¡ç'; |
| | | }; |
| | | |
| | | /** æäº¤æé® */ |
| | | const submitForm = () => { |
| | |
| | | if (valid) { |
| | | buttonLoading.value = true; |
| | | if (form.value.id) { |
| | | await updateClient(form.value).finally(() => buttonLoading.value = false); |
| | | await updateClient(form.value).finally(() => (buttonLoading.value = false)); |
| | | } else { |
| | | await addClient(form.value).finally(() => buttonLoading.value = false); |
| | | await addClient(form.value).finally(() => (buttonLoading.value = false)); |
| | | } |
| | | proxy?.$modal.msgSuccess("ä¿®æ¹æå"); |
| | | proxy?.$modal.msgSuccess('ä¿®æ¹æå'); |
| | | dialog.visible = false; |
| | | await getList(); |
| | | } |
| | | }); |
| | | } |
| | | }; |
| | | |
| | | /** å é¤æé®æä½ */ |
| | | const handleDelete = async (row?: ClientVO) => { |
| | | const _ids = row?.id || ids.value; |
| | | await proxy?.$modal.confirm('æ¯å¦ç¡®è®¤å é¤å®¢æ·ç«¯ç®¡çç¼å·ä¸º"' + _ids + '"çæ°æ®é¡¹ï¼').finally(() => loading.value = false); |
| | | await proxy?.$modal.confirm('æ¯å¦ç¡®è®¤å é¤å®¢æ·ç«¯ç®¡çç¼å·ä¸º"' + _ids + '"çæ°æ®é¡¹ï¼').finally(() => (loading.value = false)); |
| | | await delClient(_ids); |
| | | proxy?.$modal.msgSuccess("å 餿å"); |
| | | proxy?.$modal.msgSuccess('å 餿å'); |
| | | await getList(); |
| | | } |
| | | }; |
| | | |
| | | /** å¯¼åºæé®æä½ */ |
| | | const handleExport = () => { |
| | | proxy?.download('system/client/export', { |
| | | ...queryParams.value |
| | | }, `client_${new Date().getTime()}.xlsx`) |
| | | } |
| | | proxy?.download( |
| | | 'system/client/export', |
| | | { |
| | | ...queryParams.value |
| | | }, |
| | | `client_${new Date().getTime()}.xlsx` |
| | | ); |
| | | }; |
| | | |
| | | /** ç¶æä¿®æ¹ */ |
| | | const handleStatusChange = async (row: ClientVO) => { |
| | | let text = row.status === "0" ? "å¯ç¨" : "åç¨" |
| | | let text = row.status === '0' ? 'å¯ç¨' : 'åç¨'; |
| | | try { |
| | | await proxy?.$modal.confirm('确认è¦"' + text + '"å?'); |
| | | await changeStatus(row.id, row.status); |
| | | proxy?.$modal.msgSuccess(text + "æå"); |
| | | proxy?.$modal.msgSuccess(text + 'æå'); |
| | | } catch (err) { |
| | | row.status = row.status === "0" ? "1" : "0"; |
| | | row.status = row.status === '0' ? '1' : '0'; |
| | | } |
| | | } |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | getList(); |
| | |
| | | <template> |
| | | <div class="p-2"> |
| | | <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave"> |
| | | <div class="mb-[10px]" v-show="showSearch"> |
| | | <div v-show="showSearch" class="mb-[10px]"> |
| | | <el-card shadow="hover"> |
| | | <el-form :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px"> |
| | | <el-form ref="queryFormRef" :model="queryParams" :inline="true" label-width="68px"> |
| | | <el-form-item label="åæ°åç§°" prop="configName"> |
| | | <el-input v-model="queryParams.configName" placeholder="请è¾å
¥åæ°åç§°" clearable style="width: 240px" @keyup.enter="handleQuery" /> |
| | | </el-form-item> |
| | |
| | | <el-option v-for="dict in sys_yes_no" :key="dict.value" :label="dict.label" :value="dict.value" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="å建æ¶é´" style="width: 308px;"> |
| | | <el-form-item label="å建æ¶é´" style="width: 308px"> |
| | | <el-date-picker |
| | | v-model="dateRange" |
| | | value-format="YYYY-MM-DD HH:mm:ss" |
| | |
| | | <template #header> |
| | | <el-row :gutter="10" class="mb8"> |
| | | <el-col :span="1.5"> |
| | | <el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['system:config:add']">æ°å¢</el-button> |
| | | <el-button v-hasPermi="['system:config:add']" type="primary" plain icon="Plus" @click="handleAdd">æ°å¢</el-button> |
| | | </el-col> |
| | | <el-col :span="1.5"> |
| | | <el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['system:config:edit']"> |
| | | <el-button v-hasPermi="['system:config:edit']" type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()"> |
| | | ä¿®æ¹ |
| | | </el-button> |
| | | </el-col> |
| | | <el-col :span="1.5"> |
| | | <el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['system:config:remove']"> |
| | | <el-button v-hasPermi="['system:config:remove']" type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()"> |
| | | å é¤ |
| | | </el-button> |
| | | </el-col> |
| | | <el-col :span="1.5"> |
| | | <el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['system:config:export']">导åº</el-button> |
| | | <el-button v-hasPermi="['system:config:export']" type="warning" plain icon="Download" @click="handleExport">导åº</el-button> |
| | | </el-col> |
| | | <el-col :span="1.5"> |
| | | <el-button type="danger" plain icon="Refresh" @click="handleRefreshCache" v-hasPermi="['system:config:remove']">å·æ°ç¼å</el-button> |
| | | <el-button v-hasPermi="['system:config:remove']" type="danger" plain icon="Refresh" @click="handleRefreshCache">å·æ°ç¼å</el-button> |
| | | </el-col> |
| | | <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar> |
| | | <right-toolbar v-model:showSearch="showSearch" @query-table="getList"></right-toolbar> |
| | | </el-row> |
| | | </template> |
| | | |
| | | <el-table v-loading="loading" :data="configList" @selection-change="handleSelectionChange"> |
| | | <el-table-column type="selection" width="55" align="center" /> |
| | | <el-table-column label="忰䏻é®" align="center" prop="configId" v-if="false" /> |
| | | <el-table-column v-if="false" label="忰䏻é®" align="center" prop="configId" /> |
| | | <el-table-column label="åæ°åç§°" align="center" prop="configName" :show-overflow-tooltip="true" /> |
| | | <el-table-column label="åæ°é®å" align="center" prop="configKey" :show-overflow-tooltip="true" /> |
| | | <el-table-column label="åæ°é®å¼" align="center" prop="configValue" :show-overflow-tooltip="true" /> |
| | |
| | | <el-table-column label="æä½" align="center" width="150" class-name="small-padding fixed-width"> |
| | | <template #default="scope"> |
| | | <el-tooltip content="ä¿®æ¹" placement="top"> |
| | | <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['system:config:edit']"></el-button> |
| | | <el-button v-hasPermi="['system:config:edit']" link type="primary" icon="Edit" @click="handleUpdate(scope.row)"></el-button> |
| | | </el-tooltip> |
| | | <el-tooltip content="å é¤" placement="top"> |
| | | <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['system:config:remove']"></el-button> |
| | | <el-button v-hasPermi="['system:config:remove']" link type="primary" icon="Delete" @click="handleDelete(scope.row)"></el-button> |
| | | </el-tooltip> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" /> |
| | | <pagination v-show="total > 0" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" :total="total" @pagination="getList" /> |
| | | </el-card> |
| | | |
| | | <!-- æ·»å æä¿®æ¹åæ°é
ç½®å¯¹è¯æ¡ --> |
| | | <el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body> |
| | | <el-dialog v-model="dialog.visible" :title="dialog.title" width="500px" append-to-body> |
| | | <el-form ref="configFormRef" :model="form" :rules="rules" label-width="80px"> |
| | | <el-form-item label="åæ°åç§°" prop="configName"> |
| | | <el-input v-model="form.configName" placeholder="请è¾å
¥åæ°åç§°" /> |
| | |
| | | </template> |
| | | |
| | | <script setup name="Config" lang="ts"> |
| | | import { listConfig, getConfig, delConfig, addConfig, updateConfig, refreshCache } from "@/api/system/config"; |
| | | import { ConfigForm, ConfigQuery, ConfigVO } from "@/api/system/config/types"; |
| | | import { listConfig, getConfig, delConfig, addConfig, updateConfig, refreshCache } from '@/api/system/config'; |
| | | import { ConfigForm, ConfigQuery, ConfigVO } from '@/api/system/config/types'; |
| | | |
| | | const { proxy } = getCurrentInstance() as ComponentInternalInstance; |
| | | const { sys_yes_no } = toRefs<any>(proxy?.useDict("sys_yes_no")); |
| | | const { sys_yes_no } = toRefs<any>(proxy?.useDict('sys_yes_no')); |
| | | |
| | | const configList = ref<ConfigVO[]>([]); |
| | | const loading = ref(true); |
| | |
| | | configName: '', |
| | | configKey: '', |
| | | configValue: '', |
| | | configType: "Y", |
| | | configType: 'Y', |
| | | remark: '' |
| | | } |
| | | }; |
| | | const data = reactive<PageData<ConfigForm, ConfigQuery>>({ |
| | | form: { ...initFormData }, |
| | | queryParams: { |
| | |
| | | pageSize: 10, |
| | | configName: '', |
| | | configKey: '', |
| | | configType: '', |
| | | configType: '' |
| | | }, |
| | | rules: { |
| | | configName: [{ required: true, message: "åæ°åç§°ä¸è½ä¸ºç©º", trigger: "blur" }], |
| | | configKey: [{ required: true, message: "åæ°é®åä¸è½ä¸ºç©º", trigger: "blur" }], |
| | | configValue: [{ required: true, message: "åæ°é®å¼ä¸è½ä¸ºç©º", trigger: "blur" }] |
| | | configName: [{ required: true, message: 'åæ°åç§°ä¸è½ä¸ºç©º', trigger: 'blur' }], |
| | | configKey: [{ required: true, message: 'åæ°é®åä¸è½ä¸ºç©º', trigger: 'blur' }], |
| | | configValue: [{ required: true, message: 'åæ°é®å¼ä¸è½ä¸ºç©º', trigger: 'blur' }] |
| | | } |
| | | }); |
| | | |
| | |
| | | configList.value = res.rows; |
| | | total.value = res.total; |
| | | loading.value = false; |
| | | } |
| | | }; |
| | | /** åæ¶æé® */ |
| | | const cancel = () => { |
| | | reset(); |
| | | dialog.visible = false; |
| | | } |
| | | }; |
| | | /** 表åéç½® */ |
| | | const reset = () => { |
| | | form.value = { ...initFormData }; |
| | | configFormRef.value?.resetFields(); |
| | | } |
| | | }; |
| | | /** æç´¢æé®æä½ */ |
| | | const handleQuery = () => { |
| | | queryParams.value.pageNum = 1; |
| | | getList(); |
| | | } |
| | | }; |
| | | /** éç½®æé®æä½ */ |
| | | const resetQuery = () => { |
| | | dateRange.value = ['', '']; |
| | | queryFormRef.value?.resetFields(); |
| | | handleQuery(); |
| | | } |
| | | }; |
| | | /** å¤éæ¡é䏿°æ® */ |
| | | const handleSelectionChange = (selection: ConfigVO[]) => { |
| | | ids.value = selection.map(item => item.configId); |
| | | ids.value = selection.map((item) => item.configId); |
| | | single.value = selection.length != 1; |
| | | multiple.value = !selection.length; |
| | | } |
| | | }; |
| | | /** æ°å¢æé®æä½ */ |
| | | const handleAdd = () => { |
| | | reset(); |
| | | dialog.visible = true; |
| | | dialog.title = "æ·»å åæ°"; |
| | | } |
| | | dialog.title = 'æ·»å åæ°'; |
| | | }; |
| | | /** ä¿®æ¹æé®æä½ */ |
| | | const handleUpdate = async (row?: ConfigVO) => { |
| | | reset(); |
| | |
| | | const res = await getConfig(configId); |
| | | Object.assign(form.value, res.data); |
| | | dialog.visible = true; |
| | | dialog.title = "ä¿®æ¹åæ°"; |
| | | } |
| | | dialog.title = 'ä¿®æ¹åæ°'; |
| | | }; |
| | | /** æäº¤æé® */ |
| | | const submitForm = () => { |
| | | configFormRef.value?.validate(async (valid: boolean) => { |
| | | if (valid) { |
| | | form.value.configId ? await updateConfig(form.value) : await addConfig(form.value); |
| | | proxy?.$modal.msgSuccess("æä½æå"); |
| | | proxy?.$modal.msgSuccess('æä½æå'); |
| | | dialog.visible = false; |
| | | await getList(); |
| | | } |
| | | }); |
| | | } |
| | | }; |
| | | /** å é¤æé®æä½ */ |
| | | const handleDelete = async (row?: ConfigVO) => { |
| | | const configIds = row?.configId || ids.value; |
| | | await proxy?.$modal.confirm('æ¯å¦ç¡®è®¤å é¤åæ°ç¼å·ä¸º"' + configIds + '"çæ°æ®é¡¹ï¼'); |
| | | await delConfig(configIds); |
| | | await getList(); |
| | | proxy?.$modal.msgSuccess("å 餿å"); |
| | | } |
| | | proxy?.$modal.msgSuccess('å 餿å'); |
| | | }; |
| | | /** å¯¼åºæé®æä½ */ |
| | | const handleExport = () => { |
| | | proxy?.download("system/config/export", { |
| | | ...queryParams.value |
| | | }, `config_${new Date().getTime()}.xlsx`); |
| | | } |
| | | proxy?.download( |
| | | 'system/config/export', |
| | | { |
| | | ...queryParams.value |
| | | }, |
| | | `config_${new Date().getTime()}.xlsx` |
| | | ); |
| | | }; |
| | | /** å·æ°ç¼åæé®æä½ */ |
| | | const handleRefreshCache = async () => { |
| | | await refreshCache(); |
| | | proxy?.$modal.msgSuccess("å·æ°ç¼åæå"); |
| | | } |
| | | proxy?.$modal.msgSuccess('å·æ°ç¼åæå'); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | getList(); |
| | | }) |
| | | }); |
| | | </script> |
| | |
| | | <template> |
| | | <div class="p-2"> |
| | | <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave"> |
| | | <div class="mb-[10px]" v-show="showSearch"> |
| | | <div v-show="showSearch" class="mb-[10px]"> |
| | | <el-card shadow="hover"> |
| | | <el-form ref="queryFormRef" :model="queryParams" :inline="true" label-width="68px"> |
| | | <el-form-item label="é¨é¨åç§°" prop="deptName"> |
| | |
| | | <template #header> |
| | | <el-row :gutter="10"> |
| | | <el-col :span="1.5"> |
| | | <el-button type="primary" plain icon="Plus" @click="handleAdd()" v-hasPermi="['system:dept:add']">æ°å¢ </el-button> |
| | | <el-button v-hasPermi="['system:dept:add']" type="primary" plain icon="Plus" @click="handleAdd()">æ°å¢ </el-button> |
| | | </el-col> |
| | | <el-col :span="1.5"> |
| | | <el-button type="info" plain icon="Sort" @click="handleToggleExpandAll">å±å¼/æå </el-button> |
| | | </el-col> |
| | | <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar> |
| | | <right-toolbar v-model:showSearch="showSearch" @query-table="getList"></right-toolbar> |
| | | </el-row> |
| | | </template> |
| | | |
| | | <el-table |
| | | ref="deptTableRef" |
| | | v-loading="loading" |
| | | :data="deptList" |
| | | row-key="deptId" |
| | | :tree-props="{ children: 'children', hasChildren: 'hasChildren' }" |
| | | ref="deptTableRef" |
| | | :default-expand-all="isExpandAll" |
| | | > |
| | | <el-table-column prop="deptName" label="é¨é¨åç§°" width="260"></el-table-column> |
| | |
| | | <el-table-column fixed="right" align="center" label="æä½"> |
| | | <template #default="scope"> |
| | | <el-tooltip content="ä¿®æ¹" placement="top"> |
| | | <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['system:dept:edit']" /> |
| | | <el-button v-hasPermi="['system:dept:edit']" link type="primary" icon="Edit" @click="handleUpdate(scope.row)" /> |
| | | </el-tooltip> |
| | | <el-tooltip content="æ°å¢" placement="top"> |
| | | <el-button link type="primary" icon="Plus" @click="handleAdd(scope.row)" v-hasPermi="['system:dept:add']" /> |
| | | <el-button v-hasPermi="['system:dept:add']" link type="primary" icon="Plus" @click="handleAdd(scope.row)" /> |
| | | </el-tooltip> |
| | | <el-tooltip content="å é¤" placement="top"> |
| | | <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['system:dept:remove']" /> |
| | | <el-button v-hasPermi="['system:dept:remove']" link type="primary" icon="Delete" @click="handleDelete(scope.row)" /> |
| | | </el-tooltip> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </el-card> |
| | | |
| | | <el-dialog :title="dialog.title" v-model="dialog.visible" destroy-on-close append-to-bod width="600px"> |
| | | <el-dialog v-model="dialog.visible" :title="dialog.title" destroy-on-close append-to-bod width="600px"> |
| | | <el-form ref="deptFormRef" :model="form" :rules="rules" label-width="80px"> |
| | | <el-row> |
| | | <el-col :span="24" v-if="form.parentId !== 0"> |
| | | <el-col v-if="form.parentId !== 0" :span="24"> |
| | | <el-form-item label="ä¸çº§é¨é¨" prop="parentId"> |
| | | <el-tree-select |
| | | v-model="form.parentId" |
| | |
| | | <el-col :span="12"> |
| | | <el-form-item label="é¨é¨ç¶æ"> |
| | | <el-radio-group v-model="form.status"> |
| | | <el-radio v-for="dict in sys_normal_disable" :key="dict.value" :label="dict.value">{{ dict.label |
| | | }}</el-radio> |
| | | <el-radio v-for="dict in sys_normal_disable" :key="dict.value" :label="dict.value">{{ dict.label }}</el-radio> |
| | | </el-radio-group> |
| | | </el-form-item> |
| | | </el-col> |
| | |
| | | </template> |
| | | |
| | | <script setup name="Dept" lang="ts"> |
| | | import { listDept, getDept, delDept, addDept, updateDept, listDeptExcludeChild } from "@/api/system/dept" |
| | | import { DeptForm, DeptQuery, DeptVO } from "@/api/system/dept/types"; |
| | | import {UserVO} from "@/api/system/user/types"; |
| | | import {listUserByDeptId} from "@/api/system/user"; |
| | | import { listDept, getDept, delDept, addDept, updateDept, listDeptExcludeChild } from '@/api/system/dept'; |
| | | import { DeptForm, DeptQuery, DeptVO } from '@/api/system/dept/types'; |
| | | import { UserVO } from '@/api/system/user/types'; |
| | | import { listUserByDeptId } from '@/api/system/user'; |
| | | |
| | | interface DeptOptionsType { |
| | | deptId: number | string; |
| | | deptName: string; |
| | | children: DeptOptionsType[]; |
| | | |
| | | } |
| | | |
| | | const { proxy } = getCurrentInstance() as ComponentInternalInstance |
| | | const { sys_normal_disable } = toRefs<any>(proxy?.useDict("sys_normal_disable")); |
| | | const { proxy } = getCurrentInstance() as ComponentInternalInstance; |
| | | const { sys_normal_disable } = toRefs<any>(proxy?.useDict('sys_normal_disable')); |
| | | |
| | | const deptList = ref<DeptVO[]>([]) |
| | | const loading = ref(true) |
| | | const showSearch = ref(true) |
| | | const deptOptions = ref<DeptOptionsType[]>([]) |
| | | const isExpandAll = ref(true) |
| | | const deptList = ref<DeptVO[]>([]); |
| | | const loading = ref(true); |
| | | const showSearch = ref(true); |
| | | const deptOptions = ref<DeptOptionsType[]>([]); |
| | | const isExpandAll = ref(true); |
| | | const deptUserList = ref<UserVO[]>([]); |
| | | |
| | | const dialog = reactive<DialogOption>({ |
| | |
| | | leader: undefined, |
| | | phone: undefined, |
| | | email: undefined, |
| | | status: "0" |
| | | } |
| | | status: '0' |
| | | }; |
| | | const data = reactive<PageData<DeptForm, DeptQuery>>({ |
| | | form: { ...initFormData }, |
| | | queryParams: { |
| | |
| | | status: undefined |
| | | }, |
| | | rules: { |
| | | parentId: [{ required: true, message: "ä¸çº§é¨é¨ä¸è½ä¸ºç©º", trigger: "blur" }], |
| | | deptName: [{ required: true, message: "é¨é¨åç§°ä¸è½ä¸ºç©º", trigger: "blur" }], |
| | | orderNum: [{ required: true, message: "æ¾ç¤ºæåºä¸è½ä¸ºç©º", trigger: "blur" }], |
| | | email: [{ type: "email", message: "请è¾å
¥æ£ç¡®çé®ç®±å°å", trigger: ["blur", "change"] }], |
| | | phone: [{ pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/, message: "请è¾å
¥æ£ç¡®çææºå·ç ", trigger: "blur" }] |
| | | }, |
| | | }) |
| | | parentId: [{ required: true, message: 'ä¸çº§é¨é¨ä¸è½ä¸ºç©º', trigger: 'blur' }], |
| | | deptName: [{ required: true, message: 'é¨é¨åç§°ä¸è½ä¸ºç©º', trigger: 'blur' }], |
| | | orderNum: [{ required: true, message: 'æ¾ç¤ºæåºä¸è½ä¸ºç©º', trigger: 'blur' }], |
| | | email: [{ type: 'email', message: '请è¾å
¥æ£ç¡®çé®ç®±å°å', trigger: ['blur', 'change'] }], |
| | | phone: [{ pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/, message: '请è¾å
¥æ£ç¡®çææºå·ç ', trigger: 'blur' }] |
| | | } |
| | | }); |
| | | |
| | | const { queryParams, form, rules } = toRefs<PageData<DeptForm, DeptQuery>>(data) |
| | | const { queryParams, form, rules } = toRefs<PageData<DeptForm, DeptQuery>>(data); |
| | | |
| | | /** æ¥è¯¢èåå表 */ |
| | | const getList = async () => { |
| | | loading.value = true; |
| | | const res = await listDept(queryParams.value); |
| | | const data = proxy?.handleTree<DeptVO>(res.data, "deptId") |
| | | const data = proxy?.handleTree<DeptVO>(res.data, 'deptId'); |
| | | if (data) { |
| | | deptList.value = data |
| | | deptList.value = data; |
| | | } |
| | | loading.value = false |
| | | } |
| | | loading.value = false; |
| | | }; |
| | | |
| | | /** æ¥è¯¢å½åé¨é¨çææç¨æ· */ |
| | | async function getDeptAllUser(deptId: any) { |
| | | if (deptId !== null && deptId !== "" && deptId !== undefined) { |
| | | if (deptId !== null && deptId !== '' && deptId !== undefined) { |
| | | const res = await listUserByDeptId(deptId); |
| | | deptUserList.value = res.data; |
| | | } |
| | |
| | | |
| | | /** åæ¶æé® */ |
| | | const cancel = () => { |
| | | reset() |
| | | dialog.visible = false |
| | | } |
| | | reset(); |
| | | dialog.visible = false; |
| | | }; |
| | | /** 表åéç½® */ |
| | | const reset = () => { |
| | | form.value = { ...initFormData }; |
| | | deptFormRef.value?.resetFields(); |
| | | } |
| | | }; |
| | | |
| | | /** æç´¢æé®æä½ */ |
| | | const handleQuery = () => { |
| | | getList(); |
| | | } |
| | | }; |
| | | /** éç½®æé®æä½ */ |
| | | const resetQuery = () => { |
| | | queryFormRef.value?.resetFields(); |
| | | handleQuery() |
| | | } |
| | | handleQuery(); |
| | | }; |
| | | |
| | | /** å±å¼/æå æä½ */ |
| | | const handleToggleExpandAll = () => { |
| | | isExpandAll.value = !isExpandAll.value; |
| | | toggleExpandAll(deptList.value, isExpandAll.value) |
| | | } |
| | | toggleExpandAll(deptList.value, isExpandAll.value); |
| | | }; |
| | | /** å±å¼/æå ææ */ |
| | | const toggleExpandAll = (data: DeptVO[], status: boolean) => { |
| | | data.forEach((item) => { |
| | | deptTableRef.value?.toggleRowExpansion(item, status) |
| | | if (item.children && item.children.length > 0) toggleExpandAll(item.children, status) |
| | | }) |
| | | } |
| | | deptTableRef.value?.toggleRowExpansion(item, status); |
| | | if (item.children && item.children.length > 0) toggleExpandAll(item.children, status); |
| | | }); |
| | | }; |
| | | |
| | | /** æ°å¢æé®æä½ */ |
| | | const handleAdd = async (row?: DeptVO) => { |
| | | reset(); |
| | | const res = await listDept(); |
| | | const data = proxy?.handleTree<DeptOptionsType>(res.data, "deptId"); |
| | | const data = proxy?.handleTree<DeptOptionsType>(res.data, 'deptId'); |
| | | if (data) { |
| | | deptOptions.value = data |
| | | deptOptions.value = data; |
| | | if (row && row.deptId) { |
| | | form.value.parentId = row?.deptId; |
| | | } |
| | | dialog.visible = true; |
| | | dialog.title = "æ·»å é¨é¨"; |
| | | dialog.title = 'æ·»å é¨é¨'; |
| | | } |
| | | } |
| | | }; |
| | | |
| | | /** ä¿®æ¹æé®æä½ */ |
| | | const handleUpdate = async (row: DeptVO) => { |
| | |
| | | //æ¥è¯¢å½åé¨é¨ææç¨æ· |
| | | getDeptAllUser(row.deptId); |
| | | const res = await getDept(row.deptId); |
| | | form.value = res.data |
| | | form.value = res.data; |
| | | const response = await listDeptExcludeChild(row.deptId); |
| | | const data = proxy?.handleTree<DeptOptionsType>(response.data, "deptId") |
| | | const data = proxy?.handleTree<DeptOptionsType>(response.data, 'deptId'); |
| | | if (data) { |
| | | deptOptions.value = data; |
| | | if (data.length === 0) { |
| | |
| | | } |
| | | } |
| | | dialog.visible = true; |
| | | dialog.title = "ä¿®æ¹é¨é¨"; |
| | | } |
| | | dialog.title = 'ä¿®æ¹é¨é¨'; |
| | | }; |
| | | /** æäº¤æé® */ |
| | | const submitForm = () => { |
| | | deptFormRef.value?.validate(async (valid: boolean) => { |
| | | if (valid) { |
| | | form.value.deptId ? await updateDept(form.value) : await addDept(form.value); |
| | | proxy?.$modal.msgSuccess("æä½æå"); |
| | | proxy?.$modal.msgSuccess('æä½æå'); |
| | | dialog.visible = false; |
| | | await getList(); |
| | | } |
| | | }) |
| | | } |
| | | }); |
| | | }; |
| | | /** å é¤æé®æä½ */ |
| | | const handleDelete = async (row: DeptVO) => { |
| | | await proxy?.$modal.confirm('æ¯å¦ç¡®è®¤å é¤å称为"' + row.deptName + '"çæ°æ®é¡¹?'); |
| | | await delDept(row.deptId); |
| | | await getList(); |
| | | proxy?.$modal.msgSuccess("å 餿å"); |
| | | } |
| | | proxy?.$modal.msgSuccess('å 餿å'); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | getList(); |
| | |
| | | <template> |
| | | <div class="p-2"> |
| | | <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave"> |
| | | <div class="mb-[10px]" v-show="showSearch"> |
| | | <div v-show="showSearch" class="mb-[10px]"> |
| | | <el-card shadow="hover"> |
| | | <el-form :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px"> |
| | | <el-form ref="queryFormRef" :model="queryParams" :inline="true" label-width="68px"> |
| | | <el-form-item label="åå
¸åç§°" prop="dictType"> |
| | | <el-select v-model="queryParams.dictType" style="width: 200px"> |
| | | <el-option v-for="item in typeOptions" :key="item.dictId" :label="item.dictName" :value="item.dictType" /> |
| | |
| | | <template #header> |
| | | <el-row :gutter="10" class="mb8"> |
| | | <el-col :span="1.5"> |
| | | <el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['system:dict:add']">æ°å¢</el-button> |
| | | <el-button v-hasPermi="['system:dict:add']" type="primary" plain icon="Plus" @click="handleAdd">æ°å¢</el-button> |
| | | </el-col> |
| | | <el-col :span="1.5"> |
| | | <el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['system:dict:edit']">ä¿®æ¹</el-button> |
| | | <el-button v-hasPermi="['system:dict:edit']" type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()">ä¿®æ¹</el-button> |
| | | </el-col> |
| | | <el-col :span="1.5"> |
| | | <el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['system:dict:remove']"> |
| | | <el-button v-hasPermi="['system:dict:remove']" type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()"> |
| | | å é¤ |
| | | </el-button> |
| | | </el-col> |
| | | <el-col :span="1.5"> |
| | | <el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['system:dict:export']">导åº</el-button> |
| | | <el-button v-hasPermi="['system:dict:export']" type="warning" plain icon="Download" @click="handleExport">导åº</el-button> |
| | | </el-col> |
| | | <el-col :span="1.5"> |
| | | <el-button type="warning" plain icon="Close" @click="handleClose">å
³é</el-button> |
| | | </el-col> |
| | | <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar> |
| | | <right-toolbar v-model:showSearch="showSearch" @query-table="getList"></right-toolbar> |
| | | </el-row> |
| | | </template> |
| | | |
| | | <el-table v-loading="loading" :data="dataList" @selection-change="handleSelectionChange"> |
| | | <el-table-column type="selection" width="55" align="center" /> |
| | | <el-table-column label="åå
¸ç¼ç " align="center" prop="dictCode" v-if="false" /> |
| | | <el-table-column v-if="false" label="åå
¸ç¼ç " align="center" prop="dictCode" /> |
| | | <el-table-column label="åå
¸æ ç¾" align="center" prop="dictLabel"> |
| | | <template #default="scope"> |
| | | <span v-if="(scope.row.listClass === '' || scope.row.listClass === 'default') && (scope.row.cssClass === '' || scope.row.cssClass == null)">{{ scope.row.dictLabel }}</span> |
| | |
| | | <el-table-column label="æä½" align="center" width="160" class-name="small-padding fixed-width"> |
| | | <template #default="scope"> |
| | | <el-tooltip content="ä¿®æ¹" placement="top"> |
| | | <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['system:dict:edit']"></el-button> |
| | | <el-button v-hasPermi="['system:dict:edit']" link type="primary" icon="Edit" @click="handleUpdate(scope.row)"></el-button> |
| | | </el-tooltip> |
| | | <el-tooltip content="å é¤" placement="top"> |
| | | <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['system:dict:remove']"></el-button> |
| | | <el-button v-hasPermi="['system:dict:remove']" link type="primary" icon="Delete" @click="handleDelete(scope.row)"></el-button> |
| | | </el-tooltip> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | |
| | | <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" /> |
| | | <pagination v-show="total > 0" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" :total="total" @pagination="getList" /> |
| | | </el-card> |
| | | <!-- æ·»å æä¿®æ¹åæ°é
ç½®å¯¹è¯æ¡ --> |
| | | <el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body> |
| | | <el-dialog v-model="dialog.visible" :title="dialog.title" width="500px" append-to-body> |
| | | <el-form ref="dataFormRef" :model="form" :rules="rules" label-width="80px"> |
| | | <el-form-item label="åå
¸ç±»å"> |
| | | <el-input v-model="form.dictType" :disabled="true" /> |
| | |
| | | </template> |
| | | |
| | | <script setup name="Data" lang="ts"> |
| | | 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 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'; |
| | | import { DictDataForm, DictDataQuery, DictDataVO } from "@/api/system/dict/data/types"; |
| | | import { DictDataForm, DictDataQuery, DictDataVO } from '@/api/system/dict/data/types'; |
| | | |
| | | const { proxy } = getCurrentInstance() as ComponentInternalInstance |
| | | const { proxy } = getCurrentInstance() as ComponentInternalInstance; |
| | | const route = useRoute(); |
| | | |
| | | const dataList = ref<DictDataVO[]>([]); |
| | |
| | | const single = ref(true); |
| | | const multiple = ref(true); |
| | | const total = ref(0); |
| | | const defaultDictType = ref(""); |
| | | const defaultDictType = ref(''); |
| | | const typeOptions = ref<DictTypeVO[]>([]); |
| | | |
| | | const dataFormRef = ref<ElFormInstance>(); |
| | | const queryFormRef = ref<ElFormInstance>(); |
| | | |
| | | |
| | | const dialog = reactive<DialogOption>({ |
| | | visible: false, |
| | |
| | | }); |
| | | |
| | | // æ°æ®æ ç¾åæ¾æ ·å¼ |
| | | const listClassOptions = ref<Array<{ value: string, label: string }>>([ |
| | | { value: "default", label: "é»è®¤" }, |
| | | { value: "primary", label: "主è¦" }, |
| | | { value: "success", label: "æå" }, |
| | | { value: "info", label: "ä¿¡æ¯" }, |
| | | { value: "warning", label: "è¦å" }, |
| | | { value: "danger", label: "å±é©" } |
| | | const listClassOptions = ref<Array<{ value: string; label: string }>>([ |
| | | { value: 'default', label: 'é»è®¤' }, |
| | | { value: 'primary', label: '主è¦' }, |
| | | { value: 'success', label: 'æå' }, |
| | | { value: 'info', label: 'ä¿¡æ¯' }, |
| | | { value: 'warning', label: 'è¦å' }, |
| | | { value: 'danger', label: 'å±é©' } |
| | | ]); |
| | | |
| | | const initFormData: DictDataForm = { |
| | |
| | | dictLabel: '', |
| | | dictValue: '', |
| | | cssClass: '', |
| | | listClass: "default", |
| | | listClass: 'default', |
| | | dictSort: 0, |
| | | remark: '' |
| | | } |
| | | }; |
| | | const data = reactive<PageData<DictDataForm, DictDataQuery>>({ |
| | | form: { ...initFormData }, |
| | | queryParams: { |
| | |
| | | dictLabel: '' |
| | | }, |
| | | rules: { |
| | | dictLabel: [{ required: true, message: "æ°æ®æ ç¾ä¸è½ä¸ºç©º", trigger: "blur" }], |
| | | dictValue: [{ required: true, message: "æ°æ®é®å¼ä¸è½ä¸ºç©º", trigger: "blur" }], |
| | | dictSort: [{ required: true, message: "æ°æ®é¡ºåºä¸è½ä¸ºç©º", trigger: "blur" }] |
| | | dictLabel: [{ required: true, message: 'æ°æ®æ ç¾ä¸è½ä¸ºç©º', trigger: 'blur' }], |
| | | dictValue: [{ required: true, message: 'æ°æ®é®å¼ä¸è½ä¸ºç©º', trigger: 'blur' }], |
| | | dictSort: [{ required: true, message: 'æ°æ®é¡ºåºä¸è½ä¸ºç©º', trigger: 'blur' }] |
| | | } |
| | | }); |
| | | |
| | |
| | | queryParams.value.dictType = data.dictType; |
| | | defaultDictType.value = data.dictType; |
| | | getList(); |
| | | } |
| | | }; |
| | | |
| | | /** æ¥è¯¢åå
¸ç±»åå表 */ |
| | | const getTypeList = async () => { |
| | | const res = await getDictOptionselect() |
| | | const res = await getDictOptionselect(); |
| | | typeOptions.value = res.data; |
| | | } |
| | | }; |
| | | /** æ¥è¯¢åå
¸æ°æ®å表 */ |
| | | const getList = async () => { |
| | | loading.value = true; |
| | |
| | | dataList.value = res.rows; |
| | | total.value = res.total; |
| | | loading.value = false; |
| | | } |
| | | }; |
| | | /** åæ¶æé® */ |
| | | const cancel = () => { |
| | | dialog.visible = false; |
| | | reset(); |
| | | } |
| | | }; |
| | | /** 表åéç½® */ |
| | | const reset = () => { |
| | | form.value = { ...initFormData }; |
| | | dataFormRef.value?.resetFields(); |
| | | } |
| | | }; |
| | | /** æç´¢æé®æä½ */ |
| | | const handleQuery = () => { |
| | | queryParams.value.pageNum = 1; |
| | | getList(); |
| | | } |
| | | }; |
| | | /** è¿åæé®æä½ */ |
| | | const handleClose = () => { |
| | | const obj = { path: "/system/dict" }; |
| | | const obj = { path: '/system/dict' }; |
| | | proxy?.$tab.closeOpenPage(obj); |
| | | } |
| | | }; |
| | | /** éç½®æé®æä½ */ |
| | | const resetQuery = () => { |
| | | queryFormRef.value?.resetFields(); |
| | | queryParams.value.dictType = defaultDictType.value; |
| | | handleQuery(); |
| | | } |
| | | }; |
| | | /** æ°å¢æé®æä½ */ |
| | | const handleAdd = () => { |
| | | reset(); |
| | | form.value.dictType = queryParams.value.dictType; |
| | | dialog.visible = true; |
| | | dialog.title = "æ·»å åå
¸æ°æ®"; |
| | | } |
| | | dialog.title = 'æ·»å åå
¸æ°æ®'; |
| | | }; |
| | | /** å¤éæ¡é䏿°æ® */ |
| | | const handleSelectionChange = (selection: DictDataVO[]) => { |
| | | ids.value = selection.map(item => item.dictCode); |
| | | ids.value = selection.map((item) => item.dictCode); |
| | | single.value = selection.length != 1; |
| | | multiple.value = !selection.length; |
| | | } |
| | | }; |
| | | /** ä¿®æ¹æé®æä½ */ |
| | | const handleUpdate = async (row?: DictDataVO) => { |
| | | reset(); |
| | |
| | | const res = await getData(dictCode); |
| | | Object.assign(form.value, res.data); |
| | | dialog.visible = true; |
| | | dialog.title = "ä¿®æ¹åå
¸æ°æ®"; |
| | | } |
| | | dialog.title = 'ä¿®æ¹åå
¸æ°æ®'; |
| | | }; |
| | | /** æäº¤æé® */ |
| | | const submitForm = () => { |
| | | dataFormRef.value?.validate(async (valid: boolean) => { |
| | | if (valid) { |
| | | form.value.dictCode ? await updateData(form.value) : await addData(form.value); |
| | | useDictStore().removeDict(queryParams.value.dictType); |
| | | proxy?.$modal.msgSuccess("æä½æå"); |
| | | proxy?.$modal.msgSuccess('æä½æå'); |
| | | dialog.visible = false; |
| | | await getList(); |
| | | |
| | | } |
| | | }); |
| | | } |
| | | }; |
| | | /** å é¤æé®æä½ */ |
| | | const handleDelete = async (row?: DictDataVO) => { |
| | | const dictCodes = row?.dictCode || ids.value; |
| | | await proxy?.$modal.confirm('æ¯å¦ç¡®è®¤å é¤åå
¸ç¼ç 为"' + dictCodes + '"çæ°æ®é¡¹ï¼'); |
| | | await delData(dictCodes); |
| | | await getList(); |
| | | proxy?.$modal.msgSuccess("å 餿å"); |
| | | proxy?.$modal.msgSuccess('å 餿å'); |
| | | useDictStore().removeDict(queryParams.value.dictType); |
| | | |
| | | } |
| | | }; |
| | | /** å¯¼åºæé®æä½ */ |
| | | const handleExport = () => { |
| | | proxy?.download("system/dict/data/export", { |
| | | ...queryParams.value |
| | | }, `dict_data_${new Date().getTime()}.xlsx`); |
| | | } |
| | | proxy?.download( |
| | | 'system/dict/data/export', |
| | | { |
| | | ...queryParams.value |
| | | }, |
| | | `dict_data_${new Date().getTime()}.xlsx` |
| | | ); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | getTypes(route.params && route.params.dictId as string); |
| | | getTypes(route.params && (route.params.dictId as string)); |
| | | getTypeList(); |
| | | }) |
| | | }); |
| | | </script> |
| | |
| | | <template> |
| | | <div class="p-2"> |
| | | <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave"> |
| | | <div class="mb-[10px]" v-show="showSearch"> |
| | | <div v-show="showSearch" class="mb-[10px]"> |
| | | <el-card shadow="hover"> |
| | | <el-form :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px"> |
| | | <el-form ref="queryFormRef" :model="queryParams" :inline="true" label-width="68px"> |
| | | <el-form-item label="åå
¸åç§°" prop="dictName"> |
| | | <el-input v-model="queryParams.dictName" placeholder="请è¾å
¥åå
¸åç§°" clearable style="width: 240px" @keyup.enter="handleQuery" /> |
| | | </el-form-item> |
| | |
| | | <template #header> |
| | | <el-row :gutter="10" class="mb8"> |
| | | <el-col :span="1.5"> |
| | | <el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['system:dict:add']">æ°å¢</el-button> |
| | | <el-button v-hasPermi="['system:dict:add']" type="primary" plain icon="Plus" @click="handleAdd">æ°å¢</el-button> |
| | | </el-col> |
| | | <el-col :span="1.5"> |
| | | <el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['system:dict:edit']">ä¿®æ¹</el-button> |
| | | <el-button v-hasPermi="['system:dict:edit']" type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()">ä¿®æ¹</el-button> |
| | | </el-col> |
| | | <el-col :span="1.5"> |
| | | <el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['system:dict:remove']"> |
| | | <el-button v-hasPermi="['system:dict:remove']" type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()"> |
| | | å é¤ |
| | | </el-button> |
| | | </el-col> |
| | | <el-col :span="1.5"> |
| | | <el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['system:dict:export']">导åº</el-button> |
| | | <el-button v-hasPermi="['system:dict:export']" type="warning" plain icon="Download" @click="handleExport">导åº</el-button> |
| | | </el-col> |
| | | <el-col :span="1.5"> |
| | | <el-button type="danger" plain icon="Refresh" @click="handleRefreshCache" v-hasPermi="['system:dict:remove']">å·æ°ç¼å</el-button> |
| | | <el-button v-hasPermi="['system:dict:remove']" type="danger" plain icon="Refresh" @click="handleRefreshCache">å·æ°ç¼å</el-button> |
| | | </el-col> |
| | | <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar> |
| | | <right-toolbar v-model:showSearch="showSearch" @query-table="getList"></right-toolbar> |
| | | </el-row> |
| | | </template> |
| | | |
| | | <el-table v-loading="loading" :data="typeList" @selection-change="handleSelectionChange"> |
| | | <el-table-column type="selection" width="55" align="center" /> |
| | | <el-table-column label="åå
¸ç¼å·" align="center" prop="dictId" v-if="false" /> |
| | | <el-table-column v-if="false" label="åå
¸ç¼å·" align="center" prop="dictId" /> |
| | | <el-table-column label="åå
¸åç§°" align="center" prop="dictName" :show-overflow-tooltip="true" /> |
| | | <el-table-column label="åå
¸ç±»å" align="center" :show-overflow-tooltip="true"> |
| | | <template #default="scope"> |
| | |
| | | <el-table-column label="æä½" align="center" width="160" class-name="small-padding fixed-width"> |
| | | <template #default="scope"> |
| | | <el-tooltip content="ä¿®æ¹" placement="top"> |
| | | <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['system:dict:edit']"></el-button> |
| | | <el-button v-hasPermi="['system:dict:edit']" link type="primary" icon="Edit" @click="handleUpdate(scope.row)"></el-button> |
| | | </el-tooltip> |
| | | <el-tooltip content="å é¤" placement="top"> |
| | | <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['system:dict:remove']"></el-button> |
| | | <el-button v-hasPermi="['system:dict:remove']" link type="primary" icon="Delete" @click="handleDelete(scope.row)"></el-button> |
| | | </el-tooltip> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | |
| | | <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" /> |
| | | <pagination v-show="total > 0" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" :total="total" @pagination="getList" /> |
| | | </el-card> |
| | | <!-- æ·»å æä¿®æ¹åæ°é
ç½®å¯¹è¯æ¡ --> |
| | | <el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body> |
| | | <el-dialog v-model="dialog.visible" :title="dialog.title" width="500px" append-to-body> |
| | | <el-form ref="dictFormRef" :model="form" :rules="rules" label-width="80px"> |
| | | <el-form-item label="åå
¸åç§°" prop="dictName"> |
| | | <el-input v-model="form.dictName" placeholder="请è¾å
¥åå
¸åç§°" /> |
| | |
| | | </template> |
| | | |
| | | <script setup name="Dict" lang="ts"> |
| | | 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"; |
| | | 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'; |
| | | |
| | | const { proxy } = getCurrentInstance() as ComponentInternalInstance; |
| | | |
| | |
| | | const dictFormRef = ref<ElFormInstance>(); |
| | | const queryFormRef = ref<ElFormInstance>(); |
| | | |
| | | |
| | | const dialog = reactive<DialogOption>({ |
| | | visible: false, |
| | | title: '' |
| | |
| | | dictName: '', |
| | | dictType: '', |
| | | remark: '' |
| | | } |
| | | }; |
| | | const data = reactive<PageData<DictTypeForm, DictTypeQuery>>({ |
| | | form: { ...initFormData }, |
| | | queryParams: { |
| | |
| | | dictType: '' |
| | | }, |
| | | rules: { |
| | | dictName: [{ required: true, message: "åå
¸åç§°ä¸è½ä¸ºç©º", trigger: "blur" }], |
| | | dictType: [{ required: true, message: "åå
¸ç±»åä¸è½ä¸ºç©º", trigger: "blur" }] |
| | | }, |
| | | dictName: [{ required: true, message: 'åå
¸åç§°ä¸è½ä¸ºç©º', trigger: 'blur' }], |
| | | dictType: [{ required: true, message: 'åå
¸ç±»åä¸è½ä¸ºç©º', trigger: 'blur' }] |
| | | } |
| | | }); |
| | | |
| | | const { queryParams, form, rules } = toRefs(data); |
| | |
| | | /** æ¥è¯¢åå
¸ç±»åå表 */ |
| | | const getList = () => { |
| | | loading.value = true; |
| | | listType(proxy?.addDateRange(queryParams.value, dateRange.value)).then(res => { |
| | | listType(proxy?.addDateRange(queryParams.value, dateRange.value)).then((res) => { |
| | | typeList.value = res.rows; |
| | | total.value = res.total; |
| | | loading.value = false; |
| | | }); |
| | | } |
| | | }; |
| | | /** åæ¶æé® */ |
| | | const cancel = () => { |
| | | reset(); |
| | | dialog.visible = false; |
| | | } |
| | | }; |
| | | /** 表åéç½® */ |
| | | const reset = () => { |
| | | form.value = { ...initFormData }; |
| | | dictFormRef.value?.resetFields(); |
| | | } |
| | | }; |
| | | /** æç´¢æé®æä½ */ |
| | | const handleQuery = () => { |
| | | queryParams.value.pageNum = 1; |
| | | getList(); |
| | | } |
| | | }; |
| | | /** éç½®æé®æä½ */ |
| | | const resetQuery = () => { |
| | | dateRange.value = ['', '']; |
| | | queryFormRef.value?.resetFields(); |
| | | handleQuery(); |
| | | } |
| | | }; |
| | | /** æ°å¢æé®æä½ */ |
| | | const handleAdd = () => { |
| | | reset(); |
| | | dialog.visible = true; |
| | | dialog.title = "æ·»å åå
¸ç±»å"; |
| | | } |
| | | dialog.title = 'æ·»å åå
¸ç±»å'; |
| | | }; |
| | | /** å¤éæ¡é䏿°æ® */ |
| | | const handleSelectionChange = (selection: DictTypeVO[]) => { |
| | | ids.value = selection.map(item => item.dictId); |
| | | ids.value = selection.map((item) => item.dictId); |
| | | single.value = selection.length != 1; |
| | | multiple.value = !selection.length; |
| | | } |
| | | }; |
| | | /** ä¿®æ¹æé®æä½ */ |
| | | const handleUpdate = async (row?: DictTypeVO) => { |
| | | reset(); |
| | |
| | | const res = await getType(dictId); |
| | | Object.assign(form.value, res.data); |
| | | dialog.visible = true; |
| | | dialog.title = "ä¿®æ¹åå
¸ç±»å"; |
| | | } |
| | | dialog.title = 'ä¿®æ¹åå
¸ç±»å'; |
| | | }; |
| | | /** æäº¤æé® */ |
| | | const submitForm = () => { |
| | | dictFormRef.value?.validate(async (valid: boolean) => { |
| | | if (valid) { |
| | | form.value.dictId ? await updateType(form.value) : await addType(form.value); |
| | | proxy?.$modal.msgSuccess("æä½æå"); |
| | | proxy?.$modal.msgSuccess('æä½æå'); |
| | | dialog.visible = false; |
| | | getList(); |
| | | } |
| | | }); |
| | | } |
| | | }; |
| | | /** å é¤æé®æä½ */ |
| | | const handleDelete = async (row?: DictTypeVO) => { |
| | | const dictIds = row?.dictId || ids.value; |
| | | await proxy?.$modal.confirm('æ¯å¦ç¡®è®¤å é¤åå
¸ç¼å·ä¸º"' + dictIds + '"çæ°æ®é¡¹ï¼'); |
| | | await delType(dictIds); |
| | | getList(); |
| | | proxy?.$modal.msgSuccess("å 餿å"); |
| | | } |
| | | proxy?.$modal.msgSuccess('å 餿å'); |
| | | }; |
| | | /** å¯¼åºæé®æä½ */ |
| | | const handleExport = () => { |
| | | proxy?.download("system/dict/type/export", { |
| | | ...queryParams.value |
| | | }, `dict_${new Date().getTime()}.xlsx`); |
| | | } |
| | | proxy?.download( |
| | | 'system/dict/type/export', |
| | | { |
| | | ...queryParams.value |
| | | }, |
| | | `dict_${new Date().getTime()}.xlsx` |
| | | ); |
| | | }; |
| | | /** å·æ°ç¼åæé®æä½ */ |
| | | const handleRefreshCache = async () => { |
| | | await refreshCache(); |
| | | proxy?.$modal.msgSuccess("å·æ°æå"); |
| | | proxy?.$modal.msgSuccess('å·æ°æå'); |
| | | useDictStore().cleanDict(); |
| | | } |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | getList(); |
| | | }) |
| | | }); |
| | | </script> |
| | |
| | | <template> |
| | | <div class="p-2"> |
| | | <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave"> |
| | | <div class="mb-[10px]" v-show="showSearch"> |
| | | <div v-show="showSearch" class="mb-[10px]"> |
| | | <el-card shadow="hover"> |
| | | <el-form ref="queryFormRef" :model="queryParams" :inline="true" label-width="68px"> |
| | | <el-form-item label="èååç§°" prop="menuName"> |
| | |
| | | <template #header> |
| | | <el-row :gutter="10"> |
| | | <el-col :span="1.5"> |
| | | <el-button type="primary" plain icon="Plus" @click="handleAdd()" v-hasPermi="['system:menu:add']">æ°å¢ </el-button> |
| | | <el-button v-hasPermi="['system:menu:add']" type="primary" plain icon="Plus" @click="handleAdd()">æ°å¢ </el-button> |
| | | </el-col> |
| | | <el-col :span="1.5"> |
| | | <el-button type="info" plain icon="Sort" @click="handleToggleExpandAll">å±å¼/æå </el-button> |
| | | </el-col> |
| | | <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar> |
| | | <right-toolbar v-model:showSearch="showSearch" @query-table="getList"></right-toolbar> |
| | | </el-row> |
| | | </template> |
| | | |
| | | <el-table |
| | | ref="menuTableRef" |
| | | v-loading="loading" |
| | | :data="menuList" |
| | | row-key="menuId" |
| | | :tree-props="{ children: 'children', hasChildren: 'hasChildren' }" |
| | | ref="menuTableRef" |
| | | :default-expand-all="isExpandAll" |
| | | > |
| | | <el-table-column prop="menuName" label="èååç§°" :show-overflow-tooltip="true" width="160"></el-table-column> |
| | |
| | | <el-table-column fixed="right" label="æä½" width="180"> |
| | | <template #default="scope"> |
| | | <el-tooltip content="ä¿®æ¹" placement="top"> |
| | | <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['system:menu:edit']" /> |
| | | <el-button v-hasPermi="['system:menu:edit']" link type="primary" icon="Edit" @click="handleUpdate(scope.row)" /> |
| | | </el-tooltip> |
| | | <el-tooltip content="æ°å¢" placement="top"> |
| | | <el-button link type="primary" icon="Plus" @click="handleAdd(scope.row)" v-hasPermi="['system:menu:add']" /> |
| | | <el-button v-hasPermi="['system:menu:add']" link type="primary" icon="Plus" @click="handleAdd(scope.row)" /> |
| | | </el-tooltip> |
| | | <el-tooltip content="å é¤" placement="top"> |
| | | <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['system:menu:remove']" /> |
| | | <el-button v-hasPermi="['system:menu:remove']" link type="primary" icon="Delete" @click="handleDelete(scope.row)" /> |
| | | </el-tooltip> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </el-card> |
| | | |
| | | <el-dialog :title="dialog.title" v-model="dialog.visible" destroy-on-close append-to-bod width="750px"> |
| | | <el-dialog v-model="dialog.visible" :title="dialog.title" destroy-on-close append-to-bod width="750px"> |
| | | <el-form ref="menuFormRef" :model="form" :rules="rules" label-width="100px"> |
| | | <el-row> |
| | | <el-col :span="24"> |
| | |
| | | </el-radio-group> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="24" v-if="form.menuType !== 'F'"> |
| | | <el-col v-if="form.menuType !== 'F'" :span="24"> |
| | | <el-form-item label="èå徿 " prop="icon"> |
| | | <!-- 徿 éæ©å¨ --> |
| | | <icon-select v-model="form.icon" /> |
| | |
| | | <el-input-number v-model="form.orderNum" controls-position="right" :min="0" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12" v-if="form.menuType !== 'F'"> |
| | | <el-col v-if="form.menuType !== 'F'" :span="12"> |
| | | <el-form-item> |
| | | <template #label> |
| | | <span> |
| | |
| | | </el-radio-group> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12" v-if="form.menuType !== 'F'"> |
| | | <el-col v-if="form.menuType !== 'F'" :span="12"> |
| | | <el-form-item prop="path"> |
| | | <template #label> |
| | | <span> |
| | |
| | | <el-input v-model="form.path" placeholder="请è¾å
¥è·¯ç±å°å" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12" v-if="form.menuType === 'C'"> |
| | | <el-col v-if="form.menuType === 'C'" :span="12"> |
| | | <el-form-item prop="component"> |
| | | <template #label> |
| | | <span> |
| | |
| | | <el-input v-model="form.component" placeholder="请è¾å
¥ç»ä»¶è·¯å¾" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12" v-if="form.menuType !== 'M'"> |
| | | <el-col v-if="form.menuType !== 'M'" :span="12"> |
| | | <el-form-item> |
| | | <el-input v-model="form.perms" placeholder="请è¾å
¥æéæ è¯" maxlength="100" /> |
| | | <template #label> |
| | |
| | | </template> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12" v-if="form.menuType === 'C'"> |
| | | <el-col v-if="form.menuType === 'C'" :span="12"> |
| | | <el-form-item> |
| | | <el-input v-model="form.queryParam" placeholder="请è¾å
¥è·¯ç±åæ°" maxlength="255" /> |
| | | <template #label> |
| | |
| | | </template> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12" v-if="form.menuType === 'C'"> |
| | | <el-col v-if="form.menuType === 'C'" :span="12"> |
| | | <el-form-item> |
| | | <template #label> |
| | | <span> |
| | |
| | | </el-radio-group> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12" v-if="form.menuType !== 'F'"> |
| | | <el-col v-if="form.menuType !== 'F'" :span="12"> |
| | | <el-form-item> |
| | | <template #label> |
| | | <span> |
| | |
| | | children: MenuOptionsType[] | undefined; |
| | | } |
| | | |
| | | const { proxy } = getCurrentInstance() as ComponentInternalInstance |
| | | const { sys_show_hide, sys_normal_disable } = toRefs<any>(proxy?.useDict("sys_show_hide", "sys_normal_disable")); |
| | | const { proxy } = getCurrentInstance() as ComponentInternalInstance; |
| | | const { sys_show_hide, sys_normal_disable } = toRefs<any>(proxy?.useDict('sys_show_hide', 'sys_normal_disable')); |
| | | |
| | | const menuList = ref<MenuVO[]>([]) |
| | | const loading = ref(true) |
| | | const showSearch = ref(true) |
| | | const menuOptions = ref<MenuOptionsType[]>([]) |
| | | const isExpandAll = ref(false) |
| | | const menuList = ref<MenuVO[]>([]); |
| | | const loading = ref(true); |
| | | const showSearch = ref(true); |
| | | const menuOptions = ref<MenuOptionsType[]>([]); |
| | | const isExpandAll = ref(false); |
| | | |
| | | const dialog = reactive<DialogOption>({ |
| | | visible: false, |
| | |
| | | icon: '', |
| | | menuType: MenuTypeEnum.M, |
| | | orderNum: 1, |
| | | isFrame: "1", |
| | | isCache: "0", |
| | | visible: "0", |
| | | status: "0" |
| | | } |
| | | isFrame: '1', |
| | | isCache: '0', |
| | | visible: '0', |
| | | status: '0' |
| | | }; |
| | | const data = reactive<PageData<MenuForm, MenuQuery>>({ |
| | | form: { ...initFormData }, |
| | | queryParams: { |
| | |
| | | status: undefined |
| | | }, |
| | | rules: { |
| | | menuName: [{ required: true, message: "èååç§°ä¸è½ä¸ºç©º", trigger: "blur" }], |
| | | orderNum: [{ required: true, message: "èå顺åºä¸è½ä¸ºç©º", trigger: "blur" }], |
| | | path: [{ required: true, message: "è·¯ç±å°åä¸è½ä¸ºç©º", trigger: "blur" }] |
| | | }, |
| | | }) |
| | | menuName: [{ required: true, message: 'èååç§°ä¸è½ä¸ºç©º', trigger: 'blur' }], |
| | | orderNum: [{ required: true, message: 'èå顺åºä¸è½ä¸ºç©º', trigger: 'blur' }], |
| | | path: [{ required: true, message: 'è·¯ç±å°åä¸è½ä¸ºç©º', trigger: 'blur' }] |
| | | } |
| | | }); |
| | | |
| | | const menuTableRef = ref<ElTableInstance>(); |
| | | |
| | | const { queryParams, form, rules } = toRefs<PageData<MenuForm, MenuQuery>>(data) |
| | | const { queryParams, form, rules } = toRefs<PageData<MenuForm, MenuQuery>>(data); |
| | | /** æ¥è¯¢èåå表 */ |
| | | const getList = async () => { |
| | | loading.value = true |
| | | loading.value = true; |
| | | const res = await listMenu(queryParams.value); |
| | | const data = proxy?.handleTree<MenuVO>(res.data, "menuId") |
| | | const data = proxy?.handleTree<MenuVO>(res.data, 'menuId'); |
| | | if (data) { |
| | | menuList.value = data |
| | | menuList.value = data; |
| | | } |
| | | loading.value = false |
| | | } |
| | | loading.value = false; |
| | | }; |
| | | /** æ¥è¯¢èå䏿æ ç»æ */ |
| | | const getTreeselect = async () => { |
| | | menuOptions.value = [] |
| | | menuOptions.value = []; |
| | | const response = await listMenu(); |
| | | const menu: MenuOptionsType = { menuId: 0, menuName: "主类ç®", children: [] } |
| | | menu.children = proxy?.handleTree<MenuOptionsType>(response.data, "menuId") |
| | | menuOptions.value.push(menu) |
| | | } |
| | | const menu: MenuOptionsType = { menuId: 0, menuName: '主类ç®', children: [] }; |
| | | menu.children = proxy?.handleTree<MenuOptionsType>(response.data, 'menuId'); |
| | | menuOptions.value.push(menu); |
| | | }; |
| | | /** åæ¶æé® */ |
| | | const cancel = () => { |
| | | reset() |
| | | dialog.visible = false |
| | | } |
| | | reset(); |
| | | dialog.visible = false; |
| | | }; |
| | | /** 表åéç½® */ |
| | | const reset = () => { |
| | | form.value = { ...initFormData }; |
| | | menuFormRef.value?.resetFields(); |
| | | } |
| | | }; |
| | | |
| | | /** æç´¢æé®æä½ */ |
| | | const handleQuery = () => { |
| | | getList(); |
| | | } |
| | | }; |
| | | /** éç½®æé®æä½ */ |
| | | const resetQuery = () => { |
| | | queryFormRef.value?.resetFields(); |
| | | handleQuery(); |
| | | } |
| | | }; |
| | | /** æ°å¢æé®æä½ */ |
| | | const handleAdd = (row?: MenuVO) => { |
| | | reset(); |
| | | getTreeselect(); |
| | | row && row.menuId ? form.value.parentId = row.menuId : form.value.parentId = 0; |
| | | row && row.menuId ? (form.value.parentId = row.menuId) : (form.value.parentId = 0); |
| | | dialog.visible = true; |
| | | dialog.title = "æ·»å èå"; |
| | | } |
| | | dialog.title = 'æ·»å èå'; |
| | | }; |
| | | /** å±å¼/æå æä½ */ |
| | | const handleToggleExpandAll = () => { |
| | | isExpandAll.value = !isExpandAll.value; |
| | | toggleExpandAll(menuList.value, isExpandAll.value) |
| | | } |
| | | toggleExpandAll(menuList.value, isExpandAll.value); |
| | | }; |
| | | /** å±å¼/æå ææ */ |
| | | const toggleExpandAll = (data: MenuVO[], status: boolean) => { |
| | | data.forEach((item: MenuVO) => { |
| | | menuTableRef.value?.toggleRowExpansion(item, status) |
| | | if (item.children && item.children.length > 0) toggleExpandAll(item.children, status) |
| | | }) |
| | | } |
| | | menuTableRef.value?.toggleRowExpansion(item, status); |
| | | if (item.children && item.children.length > 0) toggleExpandAll(item.children, status); |
| | | }); |
| | | }; |
| | | /** ä¿®æ¹æé®æä½ */ |
| | | const handleUpdate = async (row: MenuVO) => { |
| | | reset(); |
| | |
| | | form.value = data; |
| | | } |
| | | dialog.visible = true; |
| | | dialog.title = "ä¿®æ¹èå"; |
| | | } |
| | | dialog.title = 'ä¿®æ¹èå'; |
| | | }; |
| | | /** æäº¤æé® */ |
| | | const submitForm = () => { |
| | | menuFormRef.value?.validate(async (valid: boolean) => { |
| | | if (valid) { |
| | | form.value.menuId ? await updateMenu(form.value) : await addMenu(form.value); |
| | | proxy?.$modal.msgSuccess("æä½æå"); |
| | | proxy?.$modal.msgSuccess('æä½æå'); |
| | | dialog.visible = false; |
| | | await getList(); |
| | | } |
| | | }) |
| | | } |
| | | }); |
| | | }; |
| | | /** å é¤æé®æä½ */ |
| | | const handleDelete = async (row: MenuVO) => { |
| | | await proxy?.$modal.confirm('æ¯å¦ç¡®è®¤å é¤å称为"' + row.menuName + '"çæ°æ®é¡¹?'); |
| | | await delMenu(row.menuId); |
| | | await getList(); |
| | | proxy?.$modal.msgSuccess("å 餿å"); |
| | | } |
| | | proxy?.$modal.msgSuccess('å 餿å'); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | getList(); |
| | |
| | | <template> |
| | | <div class="p-2"> |
| | | <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave"> |
| | | <div class="mb-[10px]" v-show="showSearch"> |
| | | <div v-show="showSearch" class="mb-[10px]"> |
| | | <el-card shadow="hover"> |
| | | <el-form :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px"> |
| | | <el-form ref="queryFormRef" :model="queryParams" :inline="true" label-width="68px"> |
| | | <el-form-item label="å
¬åæ é¢" prop="noticeTitle"> |
| | | <el-input v-model="queryParams.noticeTitle" placeholder="请è¾å
¥å
¬åæ é¢" clearable style="width: 200px" @keyup.enter="handleQuery" /> |
| | | </el-form-item> |
| | |
| | | <template #header> |
| | | <el-row :gutter="10" class="mb8"> |
| | | <el-col :span="1.5"> |
| | | <el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['system:notice:add']">æ°å¢</el-button> |
| | | <el-button v-hasPermi="['system:notice:add']" type="primary" plain icon="Plus" @click="handleAdd">æ°å¢</el-button> |
| | | </el-col> |
| | | <el-col :span="1.5"> |
| | | <el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['system:notice:edit']" |
| | | <el-button v-hasPermi="['system:notice:edit']" type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" |
| | | >ä¿®æ¹</el-button |
| | | > |
| | | </el-col> |
| | | <el-col :span="1.5"> |
| | | <el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['system:notice:remove']"> |
| | | <el-button v-hasPermi="['system:notice:remove']" type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()"> |
| | | å é¤ |
| | | </el-button> |
| | | </el-col> |
| | | <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar> |
| | | <right-toolbar v-model:showSearch="showSearch" @query-table="getList"></right-toolbar> |
| | | </el-row> |
| | | </template> |
| | | |
| | | <el-table v-loading="loading" :data="noticeList" @selection-change="handleSelectionChange"> |
| | | <el-table-column type="selection" width="55" align="center" /> |
| | | <el-table-column label="åºå·" align="center" prop="noticeId" width="100" v-if="false" /> |
| | | <el-table-column v-if="false" label="åºå·" align="center" prop="noticeId" width="100" /> |
| | | <el-table-column label="å
¬åæ é¢" align="center" prop="noticeTitle" :show-overflow-tooltip="true" /> |
| | | <el-table-column label="å
¬åç±»å" align="center" prop="noticeType" width="100"> |
| | | <template #default="scope"> |
| | |
| | | <el-table-column label="æä½" align="center" class-name="small-padding fixed-width"> |
| | | <template #default="scope"> |
| | | <el-tooltip content="ä¿®æ¹" placement="top"> |
| | | <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['system:notice:edit']"></el-button> |
| | | <el-button v-hasPermi="['system:notice:edit']" link type="primary" icon="Edit" @click="handleUpdate(scope.row)"></el-button> |
| | | </el-tooltip> |
| | | <el-tooltip content="å é¤" placement="top"> |
| | | <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['system:notice:remove']"></el-button> |
| | | <el-button v-hasPermi="['system:notice:remove']" link type="primary" icon="Delete" @click="handleDelete(scope.row)"></el-button> |
| | | </el-tooltip> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | |
| | | <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" /> |
| | | <pagination v-show="total > 0" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" :total="total" @pagination="getList" /> |
| | | </el-card> |
| | | <!-- æ·»å æä¿®æ¹å
¬åå¯¹è¯æ¡ --> |
| | | <el-dialog :title="dialog.title" v-model="dialog.visible" width="780px" append-to-body> |
| | | <el-dialog v-model="dialog.visible" :title="dialog.title" width="780px" append-to-body> |
| | | <el-form ref="noticeFormRef" :model="form" :rules="rules" label-width="80px"> |
| | | <el-row> |
| | | <el-col :span="12"> |
| | |
| | | <el-col :span="24"> |
| | | <el-form-item label="ç¶æ"> |
| | | <el-radio-group v-model="form.status"> |
| | | <el-radio v-for="dict in sys_notice_status" :key="dict.value" :label="dict.value">{{ dict.label |
| | | }}</el-radio> |
| | | <el-radio v-for="dict in sys_notice_status" :key="dict.value" :label="dict.value">{{ dict.label }}</el-radio> |
| | | </el-radio-group> |
| | | </el-form-item> |
| | | </el-col> |
| | |
| | | </template> |
| | | |
| | | <script setup name="Notice" lang="ts"> |
| | | import { listNotice, getNotice, delNotice, addNotice, updateNotice } from "@/api/system/notice"; |
| | | import { NoticeForm, NoticeQuery, NoticeVO } from "@/api/system/notice/types"; |
| | | import { listNotice, getNotice, delNotice, addNotice, updateNotice } from '@/api/system/notice'; |
| | | import { NoticeForm, NoticeQuery, NoticeVO } from '@/api/system/notice/types'; |
| | | |
| | | const { proxy } = getCurrentInstance() as ComponentInternalInstance; |
| | | const { sys_notice_status, sys_notice_type } = toRefs<any>(proxy?.useDict("sys_notice_status", "sys_notice_type")); |
| | | const { sys_notice_status, sys_notice_type } = toRefs<any>(proxy?.useDict('sys_notice_status', 'sys_notice_type')); |
| | | |
| | | const noticeList = ref<NoticeVO[]>([]); |
| | | const loading = ref(true); |
| | |
| | | const queryFormRef = ref<ElFormInstance>(); |
| | | const noticeFormRef = ref<ElFormInstance>(); |
| | | |
| | | |
| | | const dialog = reactive<DialogOption>({ |
| | | visible: false, |
| | | title: '' |
| | |
| | | noticeTitle: '', |
| | | noticeType: '', |
| | | noticeContent: '', |
| | | status: "0", |
| | | status: '0', |
| | | remark: '', |
| | | createByName: '' |
| | | } |
| | | }; |
| | | const data = reactive<PageData<NoticeForm, NoticeQuery>>({ |
| | | form: { ...initFormData }, |
| | | queryParams: { |
| | |
| | | noticeType: '' |
| | | }, |
| | | rules: { |
| | | noticeTitle: [{ required: true, message: "å
¬åæ é¢ä¸è½ä¸ºç©º", trigger: "blur" }], |
| | | noticeType: [{ required: true, message: "å
¬åç±»åä¸è½ä¸ºç©º", trigger: "change" }] |
| | | }, |
| | | noticeTitle: [{ required: true, message: 'å
¬åæ é¢ä¸è½ä¸ºç©º', trigger: 'blur' }], |
| | | noticeType: [{ required: true, message: 'å
¬åç±»åä¸è½ä¸ºç©º', trigger: 'change' }] |
| | | } |
| | | }); |
| | | |
| | | const { queryParams, form, rules } = toRefs(data); |
| | |
| | | noticeList.value = res.rows; |
| | | total.value = res.total; |
| | | loading.value = false; |
| | | } |
| | | }; |
| | | /** åæ¶æé® */ |
| | | const cancel = () => { |
| | | reset(); |
| | | dialog.visible = false; |
| | | } |
| | | }; |
| | | /** 表åéç½® */ |
| | | const reset = () => { |
| | | form.value = { ...initFormData }; |
| | | noticeFormRef.value?.resetFields(); |
| | | } |
| | | }; |
| | | /** æç´¢æé®æä½ */ |
| | | const handleQuery = () => { |
| | | queryParams.value.pageNum = 1; |
| | | getList(); |
| | | } |
| | | }; |
| | | /** éç½®æé®æä½ */ |
| | | const resetQuery = () => { |
| | | queryFormRef.value?.resetFields(); |
| | | handleQuery(); |
| | | } |
| | | }; |
| | | /** å¤éæ¡é䏿°æ® */ |
| | | const handleSelectionChange = (selection: NoticeVO[]) => { |
| | | ids.value = selection.map(item => item.noticeId); |
| | | ids.value = selection.map((item) => item.noticeId); |
| | | single.value = selection.length != 1; |
| | | multiple.value = !selection.length; |
| | | } |
| | | }; |
| | | /** æ°å¢æé®æä½ */ |
| | | const handleAdd = () => { |
| | | reset(); |
| | | dialog.visible = true; |
| | | dialog.title = "æ·»å å
Œ"; |
| | | } |
| | | dialog.title = 'æ·»å å
Œ'; |
| | | }; |
| | | /**ä¿®æ¹æé®æä½ */ |
| | | const handleUpdate = async (row?: NoticeVO) => { |
| | | reset(); |
| | |
| | | const { data } = await getNotice(noticeId); |
| | | Object.assign(form.value, data); |
| | | dialog.visible = true; |
| | | dialog.title = "ä¿®æ¹å
Œ"; |
| | | } |
| | | dialog.title = 'ä¿®æ¹å
Œ'; |
| | | }; |
| | | /** æäº¤æé® */ |
| | | const submitForm = () => { |
| | | noticeFormRef.value?.validate(async (valid: boolean) => { |
| | | if (valid) { |
| | | form.value.noticeId ? await updateNotice(form.value) : await addNotice(form.value); |
| | | proxy?.$modal.msgSuccess("ä¿®æ¹æå"); |
| | | proxy?.$modal.msgSuccess('ä¿®æ¹æå'); |
| | | dialog.visible = false; |
| | | await getList(); |
| | | } |
| | | }); |
| | | } |
| | | }; |
| | | /** å é¤æé®æä½ */ |
| | | const handleDelete = async (row?: NoticeVO) => { |
| | | const noticeIds = row?.noticeId || ids.value |
| | | const noticeIds = row?.noticeId || ids.value; |
| | | await proxy?.$modal.confirm('æ¯å¦ç¡®è®¤å é¤å
¬åç¼å·ä¸º"' + noticeIds + '"çæ°æ®é¡¹ï¼'); |
| | | await delNotice(noticeIds); |
| | | await getList(); |
| | | proxy?.$modal.msgSuccess("å 餿å"); |
| | | } |
| | | proxy?.$modal.msgSuccess('å 餿å'); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | getList(); |
| | | }) |
| | | }); |
| | | </script> |
| | |
| | | <template> |
| | | <div class="p-2"> |
| | | <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave"> |
| | | <div class="mb-[10px]" v-show="showSearch"> |
| | | <div v-show="showSearch" class="mb-[10px]"> |
| | | <el-card shadow="hover"> |
| | | <el-form :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px"> |
| | | <el-form ref="queryFormRef" :model="queryParams" :inline="true" label-width="68px"> |
| | | <el-form-item label="é
ç½®key" prop="configKey"> |
| | | <el-input v-model="queryParams.configKey" placeholder="é
ç½®key" clearable style="width: 200px" @keyup.enter="handleQuery" /> |
| | | </el-form-item> |
| | |
| | | å é¤ |
| | | </el-button> |
| | | </el-col> |
| | | <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar> |
| | | <right-toolbar v-model:showSearch="showSearch" @query-table="getList"></right-toolbar> |
| | | </el-row> |
| | | </template> |
| | | |
| | | <el-table v-loading="loading" :data="ossConfigList" @selection-change="handleSelectionChange"> |
| | | <el-table-column type="selection" width="55" align="center" /> |
| | | <el-table-column label="主建" align="center" prop="ossConfigId" v-if="columns[0].visible" /> |
| | | <el-table-column label="é
ç½®key" align="center" prop="configKey" v-if="columns[1].visible" /> |
| | | <el-table-column label="访é®ç«ç¹" align="center" prop="endpoint" v-if="columns[2].visible" width="200" /> |
| | | <el-table-column label="èªå®ä¹åå" align="center" prop="domain" v-if="columns[3].visible" width="200" /> |
| | | <el-table-column label="æ¡¶åç§°" align="center" prop="bucketName" v-if="columns[4].visible" /> |
| | | <el-table-column label="åç¼" align="center" prop="prefix" v-if="columns[5].visible" /> |
| | | <el-table-column label="å" align="center" prop="region" v-if="columns[6].visible" /> |
| | | <el-table-column label="æ¡¶æéç±»å" align="center" prop="accessPolicy" v-if="columns[7].visible"> |
| | | <el-table-column v-if="columns[0].visible" label="主建" align="center" prop="ossConfigId" /> |
| | | <el-table-column v-if="columns[1].visible" label="é
ç½®key" align="center" prop="configKey" /> |
| | | <el-table-column v-if="columns[2].visible" label="访é®ç«ç¹" align="center" prop="endpoint" width="200" /> |
| | | <el-table-column v-if="columns[3].visible" label="èªå®ä¹åå" align="center" prop="domain" width="200" /> |
| | | <el-table-column v-if="columns[4].visible" label="æ¡¶åç§°" align="center" prop="bucketName" /> |
| | | <el-table-column v-if="columns[5].visible" label="åç¼" align="center" prop="prefix" /> |
| | | <el-table-column v-if="columns[6].visible" label="å" align="center" prop="region" /> |
| | | <el-table-column v-if="columns[7].visible" label="æ¡¶æéç±»å" align="center" prop="accessPolicy"> |
| | | <template #default="scope"> |
| | | <el-tag type="warning" v-if="scope.row.accessPolicy === '0'">private</el-tag> |
| | | <el-tag type="success" v-if="scope.row.accessPolicy === '1'">public</el-tag> |
| | | <el-tag type="info" v-if="scope.row.accessPolicy === '2'">custom</el-tag> |
| | | <el-tag v-if="scope.row.accessPolicy === '0'" type="warning">private</el-tag> |
| | | <el-tag v-if="scope.row.accessPolicy === '1'" type="success">public</el-tag> |
| | | <el-tag v-if="scope.row.accessPolicy === '2'" type="info">custom</el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="æ¯å¦é»è®¤" align="center" prop="status" v-if="columns[8].visible"> |
| | | <el-table-column v-if="columns[8].visible" label="æ¯å¦é»è®¤" align="center" prop="status"> |
| | | <template #default="scope"> |
| | | <el-switch v-model="scope.row.status" active-value="0" inactive-value="1" @change="handleStatusChange(scope.row)"></el-switch> |
| | | </template> |
| | |
| | | </el-table-column> |
| | | </el-table> |
| | | |
| | | <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" /> |
| | | <pagination v-show="total > 0" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" :total="total" @pagination="getList" /> |
| | | </el-card> |
| | | <!-- æ·»å æä¿®æ¹å¯¹è±¡åå¨é
ç½®å¯¹è¯æ¡ --> |
| | | <el-dialog :title="dialog.title" v-model="dialog.visible" width="800px" append-to-body> |
| | | <el-dialog v-model="dialog.visible" :title="dialog.title" width="800px" append-to-body> |
| | | <el-form ref="ossConfigFormRef" :model="form" :rules="rules" label-width="120px"> |
| | | <el-form-item label="é
ç½®key" prop="configKey"> |
| | | <el-input v-model="form.configKey" placeholder="请è¾å
¥é
ç½®key" /> |
| | |
| | | </template> |
| | | |
| | | <script setup name="OssConfig" lang="ts"> |
| | | import { |
| | | listOssConfig, |
| | | getOssConfig, |
| | | delOssConfig, |
| | | addOssConfig, |
| | | updateOssConfig, |
| | | changeOssConfigStatus |
| | | } from "@/api/system/ossConfig"; |
| | | import { OssConfigForm, OssConfigQuery, OssConfigVO } from "@/api/system/ossConfig/types"; |
| | | import { listOssConfig, getOssConfig, delOssConfig, addOssConfig, updateOssConfig, changeOssConfigStatus } from '@/api/system/ossConfig'; |
| | | import { OssConfigForm, OssConfigQuery, OssConfigVO } from '@/api/system/ossConfig/types'; |
| | | |
| | | |
| | | const { proxy } = getCurrentInstance() as ComponentInternalInstance |
| | | const { sys_yes_no } = toRefs<any>(proxy?.useDict("sys_yes_no")); |
| | | const { proxy } = getCurrentInstance() as ComponentInternalInstance; |
| | | const { sys_yes_no } = toRefs<any>(proxy?.useDict('sys_yes_no')); |
| | | |
| | | const ossConfigList = ref<OssConfigVO[]>([]); |
| | | const buttonLoading = ref(false); |
| | |
| | | { key: 8, label: `ç¶æ`, visible: true } |
| | | ]); |
| | | |
| | | |
| | | const initFormData: OssConfigForm = { |
| | | ossConfigId: undefined, |
| | | configKey: '', |
| | |
| | | prefix: '', |
| | | endpoint: '', |
| | | domain: '', |
| | | isHttps: "N", |
| | | accessPolicy: "1", |
| | | isHttps: 'N', |
| | | accessPolicy: '1', |
| | | region: '', |
| | | status: "1", |
| | | remark: '', |
| | | } |
| | | status: '1', |
| | | remark: '' |
| | | }; |
| | | const data = reactive<PageData<OssConfigForm, OssConfigQuery>>({ |
| | | form: { ...initFormData }, |
| | | // æ¥è¯¢åæ° |
| | |
| | | pageSize: 10, |
| | | configKey: '', |
| | | bucketName: '', |
| | | status: '', |
| | | status: '' |
| | | }, |
| | | rules: { |
| | | configKey: [{ required: true, message: "configKeyä¸è½ä¸ºç©º", trigger: "blur" },], |
| | | configKey: [{ required: true, message: 'configKeyä¸è½ä¸ºç©º', trigger: 'blur' }], |
| | | accessKey: [ |
| | | { required: true, message: "accessKeyä¸è½ä¸ºç©º", trigger: "blur" }, |
| | | { required: true, message: 'accessKeyä¸è½ä¸ºç©º', trigger: 'blur' }, |
| | | { |
| | | min: 2, |
| | | max: 200, |
| | | message: "accessKeyé¿åº¦å¿
é¡»ä»äº 2 å 100 ä¹é´", |
| | | trigger: "blur", |
| | | }, |
| | | message: 'accessKeyé¿åº¦å¿
é¡»ä»äº 2 å 100 ä¹é´', |
| | | trigger: 'blur' |
| | | } |
| | | ], |
| | | secretKey: [ |
| | | { required: true, message: "secretKeyä¸è½ä¸ºç©º", trigger: "blur" }, |
| | | { required: true, message: 'secretKeyä¸è½ä¸ºç©º', trigger: 'blur' }, |
| | | { |
| | | min: 2, |
| | | max: 100, |
| | | message: "secretKeyé¿åº¦å¿
é¡»ä»äº 2 å 100 ä¹é´", |
| | | trigger: "blur", |
| | | }, |
| | | message: 'secretKeyé¿åº¦å¿
é¡»ä»äº 2 å 100 ä¹é´', |
| | | trigger: 'blur' |
| | | } |
| | | ], |
| | | bucketName: [ |
| | | { required: true, message: "bucketNameä¸è½ä¸ºç©º", trigger: "blur" }, |
| | | { required: true, message: 'bucketNameä¸è½ä¸ºç©º', trigger: 'blur' }, |
| | | { |
| | | min: 2, |
| | | max: 100, |
| | | message: "bucketNameé¿åº¦å¿
é¡»ä»äº 2 å 100 ä¹é´", |
| | | trigger: "blur", |
| | | }, |
| | | message: 'bucketNameé¿åº¦å¿
é¡»ä»äº 2 å 100 ä¹é´', |
| | | trigger: 'blur' |
| | | } |
| | | ], |
| | | endpoint: [ |
| | | { required: true, message: "endpointä¸è½ä¸ºç©º", trigger: "blur" }, |
| | | { required: true, message: 'endpointä¸è½ä¸ºç©º', trigger: 'blur' }, |
| | | { |
| | | min: 2, |
| | | max: 100, |
| | | message: "endpointåç§°é¿åº¦å¿
é¡»ä»äº 2 å 100 ä¹é´", |
| | | trigger: "blur", |
| | | }, |
| | | message: 'endpointåç§°é¿åº¦å¿
é¡»ä»äº 2 å 100 ä¹é´', |
| | | trigger: 'blur' |
| | | } |
| | | ], |
| | | accessPolicy: [{ required: true, message: "accessPolicyä¸è½ä¸ºç©º", trigger: "blur" }] |
| | | accessPolicy: [{ required: true, message: 'accessPolicyä¸è½ä¸ºç©º', trigger: 'blur' }] |
| | | } |
| | | }); |
| | | |
| | |
| | | ossConfigList.value = res.rows; |
| | | total.value = res.total; |
| | | loading.value = false; |
| | | } |
| | | }; |
| | | /** åæ¶æé® */ |
| | | const cancel = () => { |
| | | dialog.visible = false; |
| | | reset(); |
| | | } |
| | | }; |
| | | /** 表åéç½® */ |
| | | const reset = () => { |
| | | form.value = { ...initFormData }; |
| | | ossConfigFormRef.value?.resetFields(); |
| | | } |
| | | }; |
| | | /** æç´¢æé®æä½ */ |
| | | const handleQuery = () => { |
| | | queryParams.value.pageNum = 1; |
| | | getList(); |
| | | } |
| | | }; |
| | | /** éç½®æé®æä½ */ |
| | | const resetQuery = () => { |
| | | queryFormRef.value?.resetFields(); |
| | | handleQuery(); |
| | | } |
| | | }; |
| | | /** éæ©æ¡æ° */ |
| | | const handleSelectionChange = (selection: OssConfigVO[]) => { |
| | | ids.value = selection.map(item => item.ossConfigId); |
| | | ids.value = selection.map((item) => item.ossConfigId); |
| | | single.value = selection.length != 1; |
| | | multiple.value = !selection.length; |
| | | } |
| | | }; |
| | | /** æ°å¢æé®æä½ */ |
| | | const handleAdd = () => { |
| | | reset(); |
| | | dialog.visible = true; |
| | | dialog.title = "æ·»å 对象åå¨é
ç½®"; |
| | | } |
| | | dialog.title = 'æ·»å 对象åå¨é
ç½®'; |
| | | }; |
| | | /** ä¿®æ¹æé®æä½ */ |
| | | const handleUpdate = async (row?: OssConfigVO) => { |
| | | reset(); |
| | |
| | | const res = await getOssConfig(ossConfigId); |
| | | Object.assign(form.value, res.data); |
| | | dialog.visible = true; |
| | | dialog.title = "ä¿®æ¹å¯¹è±¡åå¨é
ç½®"; |
| | | } |
| | | dialog.title = 'ä¿®æ¹å¯¹è±¡åå¨é
ç½®'; |
| | | }; |
| | | /** æäº¤æé® */ |
| | | const submitForm = () => { |
| | | ossConfigFormRef.value?.validate(async (valid: boolean) => { |
| | | if (valid) { |
| | | buttonLoading.value = true; |
| | | if (form.value.ossConfigId) { |
| | | await updateOssConfig(form.value).finally(() => buttonLoading.value = false); |
| | | await updateOssConfig(form.value).finally(() => (buttonLoading.value = false)); |
| | | } else { |
| | | await addOssConfig(form.value).finally(() => buttonLoading.value = false); |
| | | await addOssConfig(form.value).finally(() => (buttonLoading.value = false)); |
| | | } |
| | | proxy?.$modal.msgSuccess("æ°å¢æå"); |
| | | proxy?.$modal.msgSuccess('æ°å¢æå'); |
| | | dialog.visible = false; |
| | | await getList(); |
| | | } |
| | | }); |
| | | } |
| | | }; |
| | | /** ç¶æä¿®æ¹ */ |
| | | const handleStatusChange = async (row: OssConfigVO) => { |
| | | let text = row.status === "0" ? "å¯ç¨" : "åç¨"; |
| | | let text = row.status === '0' ? 'å¯ç¨' : 'åç¨'; |
| | | try { |
| | | await proxy?.$modal.confirm('确认è¦"' + text + '""' + row.configKey + '"é
ç½®å?'); |
| | | await changeOssConfigStatus(row.ossConfigId, row.status, row.configKey); |
| | | await getList() |
| | | proxy?.$modal.msgSuccess(text + "æå"); |
| | | } catch { return } finally { |
| | | row.status = row.status === "0" ? "1" : "0"; |
| | | await getList(); |
| | | proxy?.$modal.msgSuccess(text + 'æå'); |
| | | } catch { |
| | | return; |
| | | } finally { |
| | | row.status = row.status === '0' ? '1' : '0'; |
| | | } |
| | | |
| | | } |
| | | }; |
| | | /** å é¤æé®æä½ */ |
| | | const handleDelete = async (row?: OssConfigVO) => { |
| | | const ossConfigIds = row?.ossConfigId || ids.value; |
| | | await proxy?.$modal.confirm('æ¯å¦ç¡®è®¤å é¤OSSé
ç½®ç¼å·ä¸º"' + ossConfigIds + '"çæ°æ®é¡¹?'); |
| | | loading.value = true; |
| | | await delOssConfig(ossConfigIds).finally(() => loading.value = false); |
| | | await delOssConfig(ossConfigIds).finally(() => (loading.value = false)); |
| | | await getList(); |
| | | proxy?.$modal.msgSuccess("å 餿å"); |
| | | |
| | | } |
| | | proxy?.$modal.msgSuccess('å 餿å'); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | getList(); |
| | | }) |
| | | }); |
| | | </script> |
| | |
| | | <template> |
| | | <div class="p-2"> |
| | | <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave"> |
| | | <div class="mb-[10px]" v-show="showSearch"> |
| | | <div v-show="showSearch" class="mb-[10px]"> |
| | | <el-card shadow="hover"> |
| | | <el-form :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px"> |
| | | <el-form ref="queryFormRef" :model="queryParams" :inline="true" label-width="68px"> |
| | | <el-form-item label="æä»¶å" prop="fileName"> |
| | | <el-input v-model="queryParams.fileName" placeholder="请è¾å
¥æä»¶å" clearable style="width: 200px" @keyup.enter="handleQuery" /> |
| | | </el-form-item> |
| | |
| | | <template #header> |
| | | <el-row :gutter="10" class="mb8"> |
| | | <el-col :span="1.5"> |
| | | <el-button type="primary" plain icon="Upload" @click="handleFile" v-hasPermi="['system:oss:upload']">ä¸ä¼ æä»¶</el-button> |
| | | <el-button v-hasPermi="['system:oss:upload']" type="primary" plain icon="Upload" @click="handleFile">ä¸ä¼ æä»¶</el-button> |
| | | </el-col> |
| | | <el-col :span="1.5"> |
| | | <el-button type="primary" plain icon="Upload" @click="handleImage" v-hasPermi="['system:oss:upload']">ä¸ä¼ å¾ç</el-button> |
| | | <el-button v-hasPermi="['system:oss:upload']" type="primary" plain icon="Upload" @click="handleImage">ä¸ä¼ å¾ç</el-button> |
| | | </el-col> |
| | | <el-col :span="1.5"> |
| | | <el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['system:oss:remove']"> |
| | | <el-button v-hasPermi="['system:oss:remove']" type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()"> |
| | | å é¤ |
| | | </el-button> |
| | | </el-col> |
| | | <el-col :span="1.5"> |
| | | <el-button |
| | | v-hasPermi="['system:oss:edit']" |
| | | :type="previewListResource ? 'danger' : 'warning'" |
| | | plain |
| | | @click="handlePreviewListResource(!previewListResource)" |
| | | v-hasPermi="['system:oss:edit']" |
| | | >é¢è§å¼å
³ : |
| | | {{ |
| | | previewListResource ? "ç¦ç¨" : "å¯ç¨" }}</el-button |
| | | >é¢è§å¼å
³ : {{ previewListResource ? 'ç¦ç¨' : 'å¯ç¨' }}</el-button |
| | | > |
| | | </el-col> |
| | | <el-col :span="1.5"> |
| | | <el-button type="info" plain icon="Operation" @click="handleOssConfig" v-hasPermi="['system:oss:list']">é
置管ç</el-button> |
| | | <el-button v-hasPermi="['system:oss:list']" type="info" plain icon="Operation" @click="handleOssConfig">é
置管ç</el-button> |
| | | </el-col> |
| | | <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar> |
| | | <right-toolbar v-model:showSearch="showSearch" @query-table="getList"></right-toolbar> |
| | | </el-row> |
| | | </template> |
| | | |
| | | <el-table |
| | | v-if="showTable" |
| | | v-loading="loading" |
| | | :data="ossList" |
| | | @selection-change="handleSelectionChange" |
| | | :header-cell-class-name="handleHeaderClass" |
| | | @selection-change="handleSelectionChange" |
| | | @header-click="handleHeaderCLick" |
| | | v-if="showTable" |
| | | > |
| | | <el-table-column type="selection" width="55" align="center" /> |
| | | <el-table-column label="对象åå¨ä¸»é®" align="center" prop="ossId" v-if="false" /> |
| | | <el-table-column v-if="false" label="对象åå¨ä¸»é®" align="center" prop="ossId" /> |
| | | <el-table-column label="æä»¶å" align="center" prop="fileName" /> |
| | | <el-table-column label="åå" align="center" prop="originalName" /> |
| | | <el-table-column label="æä»¶åç¼" align="center" prop="fileSuffix" /> |
| | |
| | | :src="scope.row.url" |
| | | :preview-src-list="[scope.row.url]" |
| | | /> |
| | | <span v-text="scope.row.url" v-if="!checkFileSuffix(scope.row.fileSuffix) || !previewListResource" /> |
| | | <span v-if="!checkFileSuffix(scope.row.fileSuffix) || !previewListResource" v-text="scope.row.url" /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="å建æ¶é´" align="center" prop="createTime" width="180" sortable="custom"> |
| | |
| | | <el-table-column label="æä½" align="center" class-name="small-padding fixed-width"> |
| | | <template #default="scope"> |
| | | <el-tooltip content="ä¸è½½" placement="top"> |
| | | <el-button link type="primary" icon="Download" @click="handleDownload(scope.row)" v-hasPermi="['system:oss:download']"></el-button> |
| | | <el-button v-hasPermi="['system:oss:download']" link type="primary" icon="Download" @click="handleDownload(scope.row)"></el-button> |
| | | </el-tooltip> |
| | | <el-tooltip content="å é¤" placement="top"> |
| | | <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['system:oss:remove']"></el-button> |
| | | <el-button v-hasPermi="['system:oss:remove']" link type="primary" icon="Delete" @click="handleDelete(scope.row)"></el-button> |
| | | </el-tooltip> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | |
| | | <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" /> |
| | | <pagination v-show="total > 0" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" :total="total" @pagination="getList" /> |
| | | </el-card> |
| | | <!-- æ·»å æä¿®æ¹OSS对象åå¨å¯¹è¯æ¡ --> |
| | | <el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body> |
| | | <el-dialog v-model="dialog.visible" :title="dialog.title" width="500px" append-to-body> |
| | | <el-form ref="ossFormRef" :model="form" :rules="rules" label-width="80px"> |
| | | <el-form-item label="æä»¶å"> |
| | | <fileUpload v-model="form.file" v-if="type === 0" /> |
| | | <imageUpload v-model="form.file" v-if="type === 1" /> |
| | | <fileUpload v-if="type === 0" v-model="form.file" /> |
| | | <imageUpload v-if="type === 1" v-model="form.file" /> |
| | | </el-form-item> |
| | | </el-form> |
| | | <template #footer> |
| | |
| | | </template> |
| | | |
| | | <script setup name="Oss" lang="ts"> |
| | | import { listOss, delOss } from "@/api/system/oss"; |
| | | import ImagePreview from "@/components/ImagePreview/index.vue"; |
| | | import { OssForm, OssQuery, OssVO } from "@/api/system/oss/types"; |
| | | import { listOss, delOss } from '@/api/system/oss'; |
| | | import ImagePreview from '@/components/ImagePreview/index.vue'; |
| | | import { OssForm, OssQuery, OssVO } from '@/api/system/oss/types'; |
| | | |
| | | const router = useRouter(); |
| | | const { proxy } = getCurrentInstance() as ComponentInternalInstance; |
| | |
| | | const queryFormRef = ref<ElFormInstance>(); |
| | | |
| | | const initFormData = { |
| | | file: undefined, |
| | | } |
| | | file: undefined |
| | | }; |
| | | const data = reactive<PageData<OssForm, OssQuery>>({ |
| | | form: { ...initFormData }, |
| | | // æ¥è¯¢åæ° |
| | |
| | | isAsc: defaultSort.value.order |
| | | }, |
| | | rules: { |
| | | file: [ |
| | | { required: true, message: "æä»¶ä¸è½ä¸ºç©º", trigger: "blur" } |
| | | ] |
| | | file: [{ required: true, message: 'æä»¶ä¸è½ä¸ºç©º', trigger: 'blur' }] |
| | | } |
| | | }); |
| | | |
| | |
| | | /** æ¥è¯¢OSS对象åå¨å表 */ |
| | | const getList = async () => { |
| | | loading.value = true; |
| | | const res = await proxy?.getConfigKey("sys.oss.previewListResource"); |
| | | const res = await proxy?.getConfigKey('sys.oss.previewListResource'); |
| | | previewListResource.value = res?.data === undefined ? true : res.data === 'true'; |
| | | const response = await listOss(proxy?.addDateRange(queryParams.value, dateRangeCreateTime.value, "CreateTime")); |
| | | const response = await listOss(proxy?.addDateRange(queryParams.value, dateRangeCreateTime.value, 'CreateTime')); |
| | | ossList.value = response.rows; |
| | | total.value = response.total; |
| | | loading.value = false; |
| | | showTable.value = true; |
| | | } |
| | | }; |
| | | function checkFileSuffix(fileSuffix: string[]) { |
| | | let arr = ["png", "jpg", "jpeg"]; |
| | | return arr.some(type => { |
| | | let arr = ['png', 'jpg', 'jpeg']; |
| | | return arr.some((type) => { |
| | | return fileSuffix.indexOf(type) > -1; |
| | | }); |
| | | } |
| | |
| | | } |
| | | /** éæ©æ¡æ° */ |
| | | function handleSelectionChange(selection: OssVO[]) { |
| | | ids.value = selection.map(item => item.ossId); |
| | | ids.value = selection.map((item) => item.ossId); |
| | | single.value = selection.length != 1; |
| | | multiple.value = !selection.length; |
| | | } |
| | | /** 设置åçæåºä¸ºæä»¬èªå®ä¹çæåº */ |
| | | const handleHeaderClass = ({ column }: any): any => { |
| | | column.order = column.multiOrder |
| | | } |
| | | column.order = column.multiOrder; |
| | | }; |
| | | /** ç¹å»è¡¨å¤´è¿è¡æåº */ |
| | | const handleHeaderCLick = (column: any) => { |
| | | if (column.sortable !== 'custom') { |
| | | return |
| | | return; |
| | | } |
| | | switch (column.multiOrder) { |
| | | case 'descending': |
| | |
| | | column.multiOrder = 'descending'; |
| | | break; |
| | | } |
| | | handleOrderChange(column.property, column.multiOrder) |
| | | } |
| | | handleOrderChange(column.property, column.multiOrder); |
| | | }; |
| | | const handleOrderChange = (prop: string, order: string) => { |
| | | let orderByArr = queryParams.value.orderByColumn ? queryParams.value.orderByColumn.split(",") : []; |
| | | let isAscArr = queryParams.value.isAsc ? queryParams.value.isAsc.split(",") : []; |
| | | let propIndex = orderByArr.indexOf(prop) |
| | | let orderByArr = queryParams.value.orderByColumn ? queryParams.value.orderByColumn.split(',') : []; |
| | | let isAscArr = queryParams.value.isAsc ? queryParams.value.isAsc.split(',') : []; |
| | | let propIndex = orderByArr.indexOf(prop); |
| | | if (propIndex !== -1) { |
| | | if (order) { |
| | | //æåºéå·²åå¨ åªä¿®æ¹æåº |
| | | isAscArr[propIndex] = order; |
| | | } else { |
| | | //妿order为null åå 餿åºå段å屿§ |
| | | isAscArr.splice(propIndex, 1);//å é¤æåº |
| | | orderByArr.splice(propIndex, 1);//å é¤å±æ§ |
| | | isAscArr.splice(propIndex, 1); //å é¤æåº |
| | | orderByArr.splice(propIndex, 1); //å é¤å±æ§ |
| | | } |
| | | } else { |
| | | //æåºéä¸åå¨åæ°å¢æåº |
| | |
| | | isAscArr.push(order); |
| | | } |
| | | //åå¹¶æåº |
| | | queryParams.value.orderByColumn = orderByArr.join(","); |
| | | queryParams.value.isAsc = isAscArr.join(","); |
| | | queryParams.value.orderByColumn = orderByArr.join(','); |
| | | queryParams.value.isAsc = isAscArr.join(','); |
| | | getList(); |
| | | } |
| | | }; |
| | | /** 任塿¥å¿å表æ¥è¯¢ */ |
| | | const handleOssConfig = () => { |
| | | router.push('/system/oss-config/index') |
| | | } |
| | | router.push('/system/oss-config/index'); |
| | | }; |
| | | /** æä»¶æé®æä½ */ |
| | | const handleFile = () => { |
| | | reset(); |
| | | type.value = 0; |
| | | dialog.visible = true; |
| | | dialog.title = "ä¸ä¼ æä»¶"; |
| | | } |
| | | dialog.title = 'ä¸ä¼ æä»¶'; |
| | | }; |
| | | /** å¾çæé®æä½ */ |
| | | const handleImage = () => { |
| | | reset(); |
| | | type.value = 1; |
| | | dialog.visible = true; |
| | | dialog.title = "ä¸ä¼ å¾ç"; |
| | | } |
| | | dialog.title = 'ä¸ä¼ å¾ç'; |
| | | }; |
| | | /** æäº¤æé® */ |
| | | const submitForm = () => { |
| | | dialog.visible = false; |
| | | getList(); |
| | | } |
| | | }; |
| | | /** ä¸è½½æé®æä½ */ |
| | | const handleDownload = (row: OssVO) => { |
| | | proxy?.$download.oss(row.ossId) |
| | | } |
| | | proxy?.$download.oss(row.ossId); |
| | | }; |
| | | /** ç¨æ·ç¶æä¿®æ¹ */ |
| | | const handlePreviewListResource = async (preview: boolean) => { |
| | | let text = preview ? "å¯ç¨" : "åç¨"; |
| | | let text = preview ? 'å¯ç¨' : 'åç¨'; |
| | | try { |
| | | await proxy?.$modal.confirm('确认è¦"' + text + '""é¢è§å表å¾ç"é
ç½®å?'); |
| | | await proxy?.updateConfigByKey("sys.oss.previewListResource", preview); |
| | | await getList() |
| | | proxy?.$modal.msgSuccess(text + "æå"); |
| | | } catch { return } |
| | | } |
| | | await proxy?.updateConfigByKey('sys.oss.previewListResource', preview); |
| | | await getList(); |
| | | proxy?.$modal.msgSuccess(text + 'æå'); |
| | | } catch { |
| | | return; |
| | | } |
| | | }; |
| | | /** å é¤æé®æä½ */ |
| | | const handleDelete = async (row?: OssVO) => { |
| | | const ossIds = row?.ossId || ids.value; |
| | | await proxy?.$modal.confirm('æ¯å¦ç¡®è®¤å é¤OSS对象åå¨ç¼å·ä¸º"' + ossIds + '"çæ°æ®é¡¹?'); |
| | | loading.value = true; |
| | | await delOss(ossIds).finally(() => loading.value = false); |
| | | await delOss(ossIds).finally(() => (loading.value = false)); |
| | | await getList(); |
| | | proxy?.$modal.msgSuccess("å 餿å"); |
| | | } |
| | | proxy?.$modal.msgSuccess('å 餿å'); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | getList(); |
| | | }) |
| | | }); |
| | | </script> |
| | |
| | | <template> |
| | | <div class="p-2"> |
| | | <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave"> |
| | | <div class="mb-[10px]" v-show="showSearch"> |
| | | <div v-show="showSearch" class="mb-[10px]"> |
| | | <el-card shadow="hover"> |
| | | <el-form :model="queryParams" ref="queryFormRef" :inline="true" label-width="70"> |
| | | <el-form ref="queryFormRef" :model="queryParams" :inline="true" label-width="70"> |
| | | <el-form-item label="å²ä½ç¼ç " prop="postCode"> |
| | | <el-input v-model="queryParams.postCode" placeholder="请è¾å
¥å²ä½ç¼ç " clearable style="width: 200px" @keyup.enter="handleQuery" /> |
| | | </el-form-item> |
| | |
| | | <template #header> |
| | | <el-row :gutter="10" class="mb8"> |
| | | <el-col :span="1.5"> |
| | | <el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['system:post:add']">æ°å¢</el-button> |
| | | <el-button v-hasPermi="['system:post:add']" type="primary" plain icon="Plus" @click="handleAdd">æ°å¢</el-button> |
| | | </el-col> |
| | | <el-col :span="1.5"> |
| | | <el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['system:post:edit']">ä¿®æ¹</el-button> |
| | | <el-button v-hasPermi="['system:post:edit']" type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()">ä¿®æ¹</el-button> |
| | | </el-col> |
| | | <el-col :span="1.5"> |
| | | <el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['system:post:remove']"> |
| | | <el-button v-hasPermi="['system:post:remove']" type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()"> |
| | | å é¤ |
| | | </el-button> |
| | | </el-col> |
| | | <el-col :span="1.5"> |
| | | <el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['system:post:export']">导åº</el-button> |
| | | <el-button v-hasPermi="['system:post:export']" type="warning" plain icon="Download" @click="handleExport">导åº</el-button> |
| | | </el-col> |
| | | <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar> |
| | | <right-toolbar v-model:showSearch="showSearch" @query-table="getList"></right-toolbar> |
| | | </el-row> |
| | | </template> |
| | | |
| | | <el-table v-loading="loading" :data="postList" @selection-change="handleSelectionChange"> |
| | | <el-table-column type="selection" width="55" align="center" /> |
| | | <el-table-column label="å²ä½ç¼å·" align="center" prop="postId" v-if="false" /> |
| | | <el-table-column v-if="false" label="å²ä½ç¼å·" align="center" prop="postId" /> |
| | | <el-table-column label="å²ä½ç¼ç " align="center" prop="postCode" /> |
| | | <el-table-column label="å²ä½åç§°" align="center" prop="postName" /> |
| | | <el-table-column label="å²ä½æåº" align="center" prop="postSort" /> |
| | |
| | | <el-table-column label="æä½" width="180" align="center" class-name="small-padding fixed-width"> |
| | | <template #default="scope"> |
| | | <el-tooltip content="ä¿®æ¹" placement="top"> |
| | | <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['system:post:edit']"></el-button> |
| | | <el-button v-hasPermi="['system:post:edit']" link type="primary" icon="Edit" @click="handleUpdate(scope.row)"></el-button> |
| | | </el-tooltip> |
| | | <el-tooltip content="å é¤" placement="top"> |
| | | <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['system:post:remove']"></el-button> |
| | | <el-button v-hasPermi="['system:post:remove']" link type="primary" icon="Delete" @click="handleDelete(scope.row)"></el-button> |
| | | </el-tooltip> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | |
| | | <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" /> |
| | | <pagination v-show="total > 0" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" :total="total" @pagination="getList" /> |
| | | </el-card> |
| | | |
| | | <!-- æ·»å æä¿®æ¹å²ä½å¯¹è¯æ¡ --> |
| | | <el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body> |
| | | <el-dialog v-model="dialog.visible" :title="dialog.title" width="500px" append-to-body> |
| | | <el-form ref="postFormRef" :model="form" :rules="rules" label-width="80px"> |
| | | <el-form-item label="å²ä½åç§°" prop="postName"> |
| | | <el-input v-model="form.postName" placeholder="请è¾å
¥å²ä½åç§°" /> |
| | |
| | | </template> |
| | | |
| | | <script setup name="Post" lang="ts"> |
| | | import { listPost, addPost, delPost, getPost, updatePost } from "@/api/system/post"; |
| | | import { PostForm, PostQuery, PostVO } from "@/api/system/post/types"; |
| | | import { listPost, addPost, delPost, getPost, updatePost } from '@/api/system/post'; |
| | | import { PostForm, PostQuery, PostVO } from '@/api/system/post/types'; |
| | | |
| | | const { proxy } = getCurrentInstance() as ComponentInternalInstance; |
| | | const { sys_normal_disable } = toRefs<any>(proxy?.useDict("sys_normal_disable")); |
| | | const { sys_normal_disable } = toRefs<any>(proxy?.useDict('sys_normal_disable')); |
| | | |
| | | const postList = ref<PostVO[]>([]); |
| | | const loading = ref(true); |
| | |
| | | postCode: '', |
| | | postName: '', |
| | | postSort: 0, |
| | | status: "0", |
| | | status: '0', |
| | | remark: '' |
| | | } |
| | | }; |
| | | |
| | | const data = reactive<PageData<PostForm, PostQuery>>({ |
| | | form: { ...initFormData }, |
| | |
| | | status: '' |
| | | }, |
| | | rules: { |
| | | postName: [{ required: true, message: "å²ä½åç§°ä¸è½ä¸ºç©º", trigger: "blur" }], |
| | | postCode: [{ required: true, message: "å²ä½ç¼ç ä¸è½ä¸ºç©º", trigger: "blur" }], |
| | | postSort: [{ required: true, message: "å²ä½é¡ºåºä¸è½ä¸ºç©º", trigger: "blur" }], |
| | | postName: [{ required: true, message: 'å²ä½åç§°ä¸è½ä¸ºç©º', trigger: 'blur' }], |
| | | postCode: [{ required: true, message: 'å²ä½ç¼ç ä¸è½ä¸ºç©º', trigger: 'blur' }], |
| | | postSort: [{ required: true, message: 'å²ä½é¡ºåºä¸è½ä¸ºç©º', trigger: 'blur' }] |
| | | } |
| | | }); |
| | | |
| | |
| | | postList.value = res.rows; |
| | | total.value = res.total; |
| | | loading.value = false; |
| | | } |
| | | }; |
| | | /** åæ¶æé® */ |
| | | const cancel = () => { |
| | | reset(); |
| | | dialog.visible = false; |
| | | } |
| | | }; |
| | | /** 表åéç½® */ |
| | | const reset = () => { |
| | | form.value = { ...initFormData }; |
| | | postFormRef.value?.resetFields(); |
| | | } |
| | | }; |
| | | /** æç´¢æé®æä½ */ |
| | | const handleQuery = () => { |
| | | queryParams.value.pageNum = 1; |
| | | getList(); |
| | | } |
| | | }; |
| | | /** éç½®æé®æä½ */ |
| | | const resetQuery = () => { |
| | | queryFormRef.value?.resetFields(); |
| | | handleQuery(); |
| | | } |
| | | }; |
| | | /** å¤éæ¡é䏿°æ® */ |
| | | const handleSelectionChange = (selection: PostVO[]) => { |
| | | ids.value = selection.map(item => item.postId); |
| | | ids.value = selection.map((item) => item.postId); |
| | | single.value = selection.length != 1; |
| | | multiple.value = !selection.length; |
| | | } |
| | | }; |
| | | /** æ°å¢æé®æä½ */ |
| | | const handleAdd = () => { |
| | | reset(); |
| | | dialog.visible = true; |
| | | dialog.title = "æ·»å å²ä½"; |
| | | } |
| | | dialog.title = 'æ·»å å²ä½'; |
| | | }; |
| | | /** ä¿®æ¹æé®æä½ */ |
| | | const handleUpdate = async (row?: PostVO) => { |
| | | reset(); |
| | |
| | | const res = await getPost(postId); |
| | | Object.assign(form.value, res.data); |
| | | dialog.visible = true; |
| | | dialog.title = "ä¿®æ¹å²ä½"; |
| | | } |
| | | dialog.title = 'ä¿®æ¹å²ä½'; |
| | | }; |
| | | /** æäº¤æé® */ |
| | | const submitForm = () => { |
| | | postFormRef.value?.validate(async (valid: boolean) => { |
| | | if (valid) { |
| | | form.value.postId ? await updatePost(form.value) : await addPost(form.value); |
| | | proxy?.$modal.msgSuccess("æä½æå"); |
| | | proxy?.$modal.msgSuccess('æä½æå'); |
| | | dialog.visible = false; |
| | | await getList(); |
| | | } |
| | | }); |
| | | } |
| | | }; |
| | | /** å é¤æé®æä½ */ |
| | | const handleDelete = async (row?: PostVO) => { |
| | | const postIds = row?.postId || ids.value; |
| | | await proxy?.$modal.confirm('æ¯å¦ç¡®è®¤å é¤å²ä½ç¼å·ä¸º"' + postIds + '"çæ°æ®é¡¹ï¼'); |
| | | await delPost(postIds); |
| | | await getList(); |
| | | proxy?.$modal.msgSuccess("å 餿å"); |
| | | } |
| | | proxy?.$modal.msgSuccess('å 餿å'); |
| | | }; |
| | | /** å¯¼åºæé®æä½ */ |
| | | const handleExport = () => { |
| | | proxy?.download("system/post/export", { |
| | | ...queryParams.value |
| | | }, `post_${new Date().getTime()}.xlsx`); |
| | | } |
| | | proxy?.download( |
| | | 'system/post/export', |
| | | { |
| | | ...queryParams.value |
| | | }, |
| | | `post_${new Date().getTime()}.xlsx` |
| | | ); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | getList(); |
| | |
| | | <template> |
| | | <div class="p-2"> |
| | | <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave"> |
| | | <div class="search" v-show="showSearch"> |
| | | <el-form :model="queryParams" ref="queryFormRef" :inline="true"> |
| | | <div v-show="showSearch" class="search"> |
| | | <el-form ref="queryFormRef" :model="queryParams" :inline="true"> |
| | | <el-form-item label="ç¨æ·åç§°" prop="userName"> |
| | | <el-input v-model="queryParams.userName" placeholder="请è¾å
¥ç¨æ·åç§°" clearable style="width: 240px" @keyup.enter="handleQuery" /> |
| | | </el-form-item> |
| | |
| | | <template #header> |
| | | <el-row :gutter="10"> |
| | | <el-col :span="1.5"> |
| | | <el-button type="primary" plain icon="Plus" @click="openSelectUser" v-hasPermi="['system:role:add']">æ·»å ç¨æ·</el-button> |
| | | <el-button v-hasPermi="['system:role:add']" type="primary" plain icon="Plus" @click="openSelectUser">æ·»å ç¨æ·</el-button> |
| | | </el-col> |
| | | <el-col :span="1.5"> |
| | | <el-button type="danger" plain icon="CircleClose" :disabled="multiple" @click="cancelAuthUserAll" v-hasPermi="['system:role:remove']"> |
| | | <el-button v-hasPermi="['system:role:remove']" type="danger" plain icon="CircleClose" :disabled="multiple" @click="cancelAuthUserAll"> |
| | | æ¹éåæ¶ææ |
| | | </el-button> |
| | | </el-col> |
| | | <el-col :span="1.5"> |
| | | <el-button type="warning" plain icon="Close" @click="handleClose">å
³é</el-button> |
| | | </el-col> |
| | | <right-toolbar v-model:showSearch="showSearch" @queryTable="getList" :search="true"></right-toolbar> |
| | | <right-toolbar v-model:showSearch="showSearch" :search="true" @query-table="getList"></right-toolbar> |
| | | </el-row> |
| | | </template> |
| | | <el-table v-loading="loading" :data="userList" @selection-change="handleSelectionChange"> |
| | |
| | | <el-table-column label="æä½" align="center" class-name="small-padding fixed-width"> |
| | | <template #default="scope"> |
| | | <el-tooltip content="åæ¶ææ" placement="top"> |
| | | <el-button link type="primary" icon="CircleClose" @click="cancelAuthUser(scope.row)" v-hasPermi="['system:role:remove']"> </el-button> |
| | | <el-button v-hasPermi="['system:role:remove']" link type="primary" icon="CircleClose" @click="cancelAuthUser(scope.row)"> </el-button> |
| | | </el-tooltip> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | |
| | | <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" /> |
| | | <select-user ref="selectRef" :roleId="queryParams.roleId" @ok="handleQuery" /> |
| | | <pagination v-show="total > 0" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" :total="total" @pagination="getList" /> |
| | | <select-user ref="selectRef" :role-id="queryParams.roleId" @ok="handleQuery" /> |
| | | </el-card> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup name="AuthUser" lang="ts"> |
| | | import { allocatedUserList, authUserCancel, authUserCancelAll } from "@/api/system/role"; |
| | | import { UserQuery } from "@/api/system/user/types"; |
| | | import { UserVO } from "@/api/system/user/types"; |
| | | import SelectUser from "./selectUser.vue"; |
| | | |
| | | import { allocatedUserList, authUserCancel, authUserCancelAll } from '@/api/system/role'; |
| | | import { UserQuery } from '@/api/system/user/types'; |
| | | import { UserVO } from '@/api/system/user/types'; |
| | | import SelectUser from './selectUser.vue'; |
| | | |
| | | const route = useRoute(); |
| | | const { proxy } = getCurrentInstance() as ComponentInternalInstance; |
| | | const { sys_normal_disable } = toRefs<any>(proxy?.useDict("sys_normal_disable")); |
| | | const { sys_normal_disable } = toRefs<any>(proxy?.useDict('sys_normal_disable')); |
| | | |
| | | const userList = ref<UserVO[]>([]); |
| | | const loading = ref(true); |
| | |
| | | pageSize: 10, |
| | | roleId: route.params.roleId as string, |
| | | userName: undefined, |
| | | phonenumber: undefined, |
| | | phonenumber: undefined |
| | | }); |
| | | |
| | | /** æ¥è¯¢ææç¨æ·å表 */ |
| | |
| | | userList.value = res.rows; |
| | | total.value = res.total; |
| | | loading.value = false; |
| | | } |
| | | }; |
| | | // è¿åæé® |
| | | const handleClose = () => { |
| | | const obj = { path: "/system/role" }; |
| | | const obj = { path: '/system/role' }; |
| | | proxy?.$tab.closeOpenPage(obj); |
| | | } |
| | | }; |
| | | /** æç´¢æé®æä½ */ |
| | | const handleQuery = () => { |
| | | queryParams.pageNum = 1; |
| | | getList(); |
| | | } |
| | | }; |
| | | /** éç½®æé®æä½ */ |
| | | const resetQuery = () => { |
| | | queryFormRef.value?.resetFields(); |
| | | handleQuery(); |
| | | } |
| | | }; |
| | | // å¤éæ¡é䏿°æ® |
| | | const handleSelectionChange = (selection: UserVO[]) => { |
| | | userIds.value = selection.map(item => item.userId); |
| | | userIds.value = selection.map((item) => item.userId); |
| | | multiple.value = !selection.length; |
| | | } |
| | | }; |
| | | /** æå¼ææç¨æ·è¡¨å¼¹çª */ |
| | | const openSelectUser = () => { |
| | | selectRef.value?.show(); |
| | | } |
| | | }; |
| | | /** åæ¶æææé®æä½ */ |
| | | const cancelAuthUser = async (row: UserVO) => { |
| | | await proxy?.$modal.confirm('确认è¦åæ¶è¯¥ç¨æ·"' + row.userName + '"è§è²åï¼'); |
| | | await authUserCancel({ userId: row.userId, roleId: queryParams.roleId }); |
| | | await getList(); |
| | | proxy?.$modal.msgSuccess("åæ¶æææå"); |
| | | } |
| | | proxy?.$modal.msgSuccess('åæ¶æææå'); |
| | | }; |
| | | /** æ¹éåæ¶æææé®æä½ */ |
| | | const cancelAuthUserAll = async () => { |
| | | const roleId = queryParams.roleId; |
| | | const uIds = userIds.value.join(","); |
| | | await proxy?.$modal.confirm("æ¯å¦åæ¶éä¸ç¨æ·æææ°æ®é¡¹?"); |
| | | const uIds = userIds.value.join(','); |
| | | await proxy?.$modal.confirm('æ¯å¦åæ¶éä¸ç¨æ·æææ°æ®é¡¹?'); |
| | | await authUserCancelAll({ roleId: roleId, userIds: uIds }); |
| | | await getList(); |
| | | proxy?.$modal.msgSuccess("åæ¶æææå"); |
| | | } |
| | | proxy?.$modal.msgSuccess('åæ¶æææå'); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | getList(); |
| | |
| | | <template> |
| | | <div class="p-2"> |
| | | <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave"> |
| | | <div class="mb-[10px]" v-show="showSearch"> |
| | | <div v-show="showSearch" class="mb-[10px]"> |
| | | <el-card shadow="hover"> |
| | | <el-form ref="queryFormRef" :model="queryParams" :inline="true" label-width="68px"> |
| | | <el-form-item label="è§è²åç§°" prop="roleName"> |
| | |
| | | </el-form-item> |
| | | |
| | | <el-form-item> |
| | | <el-button type="primary" @click="handleQuery" icon="Search">æç´¢</el-button> |
| | | <el-button @click="resetQuery" icon="Refresh">éç½®</el-button> |
| | | <el-button type="primary" icon="Search" @click="handleQuery">æç´¢</el-button> |
| | | <el-button icon="Refresh" @click="resetQuery">éç½®</el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | </el-card> |
| | |
| | | <template #header> |
| | | <el-row :gutter="10"> |
| | | <el-col :span="1.5"> |
| | | <el-button type="primary" plain @click="handleAdd()" icon="Plus" v-hasPermi="['system:role:add']">æ°å¢</el-button> |
| | | <el-button v-hasPermi="['system:role:add']" type="primary" plain icon="Plus" @click="handleAdd()">æ°å¢</el-button> |
| | | </el-col> |
| | | <el-col :span="1.5"> |
| | | <el-button type="success" plain @click="handleUpdate()" :disabled="single" icon="Edit" v-hasPermi="['system:role:edit']">ä¿®æ¹</el-button> |
| | | <el-button v-hasPermi="['system:role:edit']" type="success" plain :disabled="single" icon="Edit" @click="handleUpdate()">ä¿®æ¹</el-button> |
| | | </el-col> |
| | | <el-col :span="1.5"> |
| | | <el-button type="danger" plain :disabled="ids.length === 0" @click="handleDelete()" v-hasPermi="['system:role:delete']">å é¤</el-button> |
| | | <el-button v-hasPermi="['system:role:delete']" type="danger" plain :disabled="ids.length === 0" @click="handleDelete()">å é¤</el-button> |
| | | </el-col> |
| | | <el-col :span="1.5"> |
| | | <el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['system:role:export']">导åº</el-button> |
| | | <el-button v-hasPermi="['system:role:export']" type="warning" plain icon="Download" @click="handleExport">导åº</el-button> |
| | | </el-col> |
| | | <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar> |
| | | <right-toolbar v-model:showSearch="showSearch" @query-table="getList"></right-toolbar> |
| | | </el-row> |
| | | </template> |
| | | |
| | | <el-table ref="roleTableRef" v-loading="loading" :data="roleList" @selection-change="handleSelectionChange"> |
| | | <el-table-column type="selection" width="55" align="center" /> |
| | | <el-table-column label="è§è²ç¼å·" prop="roleId" width="120" v-if="false" /> |
| | | <el-table-column v-if="false" label="è§è²ç¼å·" prop="roleId" width="120" /> |
| | | <el-table-column label="è§è²åç§°" prop="roleName" :show-overflow-tooltip="true" width="150" /> |
| | | <el-table-column label="æéå符" prop="roleKey" :show-overflow-tooltip="true" width="200" /> |
| | | <el-table-column label="æ¾ç¤ºé¡ºåº" prop="roleSort" width="100" /> |
| | |
| | | |
| | | <el-table-column fixed="right" label="æä½" width="180"> |
| | | <template #default="scope"> |
| | | <el-tooltip content="ä¿®æ¹" placement="top" v-if="scope.row.roleId !== 1"> |
| | | <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['system:role:edit']"></el-button> |
| | | <el-tooltip v-if="scope.row.roleId !== 1" content="ä¿®æ¹" placement="top"> |
| | | <el-button v-hasPermi="['system:role:edit']" link type="primary" icon="Edit" @click="handleUpdate(scope.row)"></el-button> |
| | | </el-tooltip> |
| | | <el-tooltip content="å é¤" placement="top" v-if="scope.row.roleId !== 1"> |
| | | <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['system:role:remove']"></el-button> |
| | | <el-tooltip v-if="scope.row.roleId !== 1" content="å é¤" placement="top"> |
| | | <el-button v-hasPermi="['system:role:remove']" link type="primary" icon="Delete" @click="handleDelete(scope.row)"></el-button> |
| | | </el-tooltip> |
| | | <el-tooltip content="æ°æ®æé" placement="top" v-if="scope.row.roleId !== 1"> |
| | | <el-button link type="primary" icon="CircleCheck" @click="handleDataScope(scope.row)" v-hasPermi="['system:role:edit']"></el-button> |
| | | <el-tooltip v-if="scope.row.roleId !== 1" content="æ°æ®æé" placement="top"> |
| | | <el-button v-hasPermi="['system:role:edit']" link type="primary" icon="CircleCheck" @click="handleDataScope(scope.row)"></el-button> |
| | | </el-tooltip> |
| | | <el-tooltip content="åé
ç¨æ·" placement="top" v-if="scope.row.roleId !== 1"> |
| | | <el-button link type="primary" icon="User" @click="handleAuthUser(scope.row)" v-hasPermi="['system:role:edit']"></el-button> |
| | | <el-tooltip v-if="scope.row.roleId !== 1" content="åé
ç¨æ·" placement="top"> |
| | | <el-button v-hasPermi="['system:role:edit']" link type="primary" icon="User" @click="handleAuthUser(scope.row)"></el-button> |
| | | </el-tooltip> |
| | | </template> |
| | | </el-table-column> |
| | |
| | | /> |
| | | </el-card> |
| | | |
| | | <el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body> |
| | | <el-dialog v-model="dialog.visible" :title="dialog.title" width="500px" append-to-body> |
| | | <el-form ref="roleFormRef" :model="form" :rules="rules" label-width="100px"> |
| | | <el-form-item label="è§è²åç§°" prop="roleName"> |
| | | <el-input v-model="form.roleName" placeholder="请è¾å
¥è§è²åç§°" /> |
| | |
| | | </el-form-item> |
| | | <el-form-item label="ç¶æ"> |
| | | <el-radio-group v-model="form.status"> |
| | | <el-radio v-for="dict in sys_normal_disable" :key="dict.value" :label="dict.value">{{ |
| | | dict.label |
| | | }}</el-radio> |
| | | <el-radio v-for="dict in sys_normal_disable" :key="dict.value" :label="dict.value">{{ dict.label }}</el-radio> |
| | | </el-radio-group> |
| | | </el-form-item> |
| | | <el-form-item label="èåæé"> |
| | |
| | | <el-checkbox v-model="menuNodeAll" @change="handleCheckedTreeNodeAll($event, 'menu')">å
¨é/å
¨ä¸é</el-checkbox> |
| | | <el-checkbox v-model="form.menuCheckStrictly" @change="handleCheckedTreeConnect($event, 'menu')">ç¶åèå¨</el-checkbox> |
| | | <el-tree |
| | | ref="menuRef" |
| | | class="tree-border" |
| | | :data="menuOptions" |
| | | show-checkbox |
| | | ref="menuRef" |
| | | node-key="id" |
| | | :check-strictly="!form.menuCheckStrictly" |
| | | empty-text="å è½½ä¸ï¼è¯·ç¨å" |
| | |
| | | </el-dialog> |
| | | |
| | | <!-- åé
è§è²æ°æ®æéå¯¹è¯æ¡ --> |
| | | <el-dialog :title="dialog.title" v-model="openDataScope" width="500px" append-to-body> |
| | | <el-form :model="form" label-width="80px" ref="dataScopeRef"> |
| | | <el-dialog v-model="openDataScope" :title="dialog.title" width="500px" append-to-body> |
| | | <el-form ref="dataScopeRef" :model="form" label-width="80px"> |
| | | <el-form-item label="è§è²åç§°"> |
| | | <el-input v-model="form.roleName" :disabled="true" /> |
| | | </el-form-item> |
| | |
| | | <el-option v-for="item in dataScopeOptions" :key="item.value" :label="item.label" :value="item.value"></el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="æ°æ®æé" v-show="form.dataScope === '2'"> |
| | | <el-form-item v-show="form.dataScope === '2'" label="æ°æ®æé"> |
| | | <el-checkbox v-model="deptExpand" @change="handleCheckedTreeExpand($event, 'dept')">å±å¼/æå </el-checkbox> |
| | | <el-checkbox v-model="deptNodeAll" @change="handleCheckedTreeNodeAll($event, 'dept')">å
¨é/å
¨ä¸é</el-checkbox> |
| | | <el-checkbox v-model="form.deptCheckStrictly" @change="handleCheckedTreeConnect($event, 'dept')">ç¶åèå¨</el-checkbox> |
| | | <el-tree |
| | | ref="deptRef" |
| | | class="tree-border" |
| | | :data="deptOptions" |
| | | show-checkbox |
| | | default-expand-all |
| | | ref="deptRef" |
| | | node-key="id" |
| | | :check-strictly="!form.deptCheckStrictly" |
| | | empty-text="å è½½ä¸ï¼è¯·ç¨å" |
| | |
| | | </template> |
| | | |
| | | <script setup name="Role" lang="ts"> |
| | | import { addRole, changeRoleStatus, dataScope, delRole, getRole, listRole, updateRole, deptTreeSelect } from "@/api/system/role"; |
| | | import { addRole, changeRoleStatus, dataScope, delRole, getRole, listRole, updateRole, deptTreeSelect } from '@/api/system/role'; |
| | | import { roleMenuTreeselect, treeselect as menuTreeselect } from '@/api/system/menu/index'; |
| | | import { RoleVO, RoleForm, RoleQuery, DeptTreeOption } from '@/api/system/role/types'; |
| | | import { MenuTreeOption, RoleMenuTree } from '@/api/system/menu/types'; |
| | |
| | | const { sys_normal_disable } = toRefs<any>(proxy?.useDict('sys_normal_disable')); |
| | | |
| | | const roleList = ref<RoleVO[]>(); |
| | | const loading = ref(true) |
| | | const showSearch = ref(true) |
| | | const ids = ref<Array<string | number>>([]) |
| | | const single = ref(true) |
| | | const multiple = ref(true) |
| | | const total = ref(0) |
| | | const dateRange = ref<[DateModelType, DateModelType]>(['', '']) |
| | | const menuOptions = ref<MenuTreeOption[]>([]) |
| | | const menuExpand = ref(false) |
| | | const menuNodeAll = ref(false) |
| | | const deptExpand = ref(true) |
| | | const deptNodeAll = ref(false) |
| | | const deptOptions = ref<DeptTreeOption[]>([]) |
| | | const openDataScope = ref(false) |
| | | const loading = ref(true); |
| | | const showSearch = ref(true); |
| | | const ids = ref<Array<string | number>>([]); |
| | | const single = ref(true); |
| | | const multiple = ref(true); |
| | | const total = ref(0); |
| | | const dateRange = ref<[DateModelType, DateModelType]>(['', '']); |
| | | const menuOptions = ref<MenuTreeOption[]>([]); |
| | | const menuExpand = ref(false); |
| | | const menuNodeAll = ref(false); |
| | | const deptExpand = ref(true); |
| | | const deptNodeAll = ref(false); |
| | | const deptOptions = ref<DeptTreeOption[]>([]); |
| | | const openDataScope = ref(false); |
| | | |
| | | /** æ°æ®èå´é项*/ |
| | | const dataScopeOptions = ref([ |
| | | { value: "1", label: "å
¨é¨æ°æ®æé" }, |
| | | { value: "2", label: "èªå®æ°æ®æé" }, |
| | | { value: "3", label: "æ¬é¨é¨æ°æ®æé" }, |
| | | { value: "4", label: "æ¬é¨é¨å以䏿°æ®æé" }, |
| | | { value: "5", label: "ä»
æ¬äººæ°æ®æé" } |
| | | ]) |
| | | { value: '1', label: 'å
¨é¨æ°æ®æé' }, |
| | | { value: '2', label: 'èªå®æ°æ®æé' }, |
| | | { value: '3', label: 'æ¬é¨é¨æ°æ®æé' }, |
| | | { value: '4', label: 'æ¬é¨é¨å以䏿°æ®æé' }, |
| | | { value: '5', label: 'ä»
æ¬äººæ°æ®æé' } |
| | | ]); |
| | | |
| | | const queryFormRef = ref<ElFormInstance>(); |
| | | const roleFormRef = ref<ElFormInstance>(); |
| | |
| | | remark: '', |
| | | dataScope: '1', |
| | | menuIds: [], |
| | | deptIds: [], |
| | | } |
| | | deptIds: [] |
| | | }; |
| | | |
| | | const data = reactive<PageData<RoleForm, RoleQuery>>({ |
| | | form: { ...initForm }, |
| | |
| | | pageSize: 10, |
| | | roleName: '', |
| | | roleKey: '', |
| | | status: '', |
| | | status: '' |
| | | }, |
| | | rules: { |
| | | roleName: [{ required: true, message: "è§è²åç§°ä¸è½ä¸ºç©º", trigger: "blur" }], |
| | | roleKey: [{ required: true, message: "æéå符ä¸è½ä¸ºç©º", trigger: "blur" }], |
| | | roleSort: [{ required: true, message: "è§è²é¡ºåºä¸è½ä¸ºç©º", trigger: "blur" }] |
| | | roleName: [{ required: true, message: 'è§è²åç§°ä¸è½ä¸ºç©º', trigger: 'blur' }], |
| | | roleKey: [{ required: true, message: 'æéå符ä¸è½ä¸ºç©º', trigger: 'blur' }], |
| | | roleSort: [{ required: true, message: 'è§è²é¡ºåºä¸è½ä¸ºç©º', trigger: 'blur' }] |
| | | } |
| | | }) |
| | | const { form, queryParams, rules } = toRefs(data) |
| | | }); |
| | | const { form, queryParams, rules } = toRefs(data); |
| | | |
| | | const dialog = reactive<DialogOption>({ |
| | | visible: false, |
| | |
| | | * æ¥è¯¢è§è²å表 |
| | | */ |
| | | const getList = () => { |
| | | loading.value = true |
| | | listRole(proxy?.addDateRange(queryParams.value, dateRange.value)).then(res => { |
| | | roleList.value = res.rows |
| | | total.value = res.total |
| | | loading.value = false |
| | | }) |
| | | } |
| | | loading.value = true; |
| | | listRole(proxy?.addDateRange(queryParams.value, dateRange.value)).then((res) => { |
| | | roleList.value = res.rows; |
| | | total.value = res.total; |
| | | loading.value = false; |
| | | }); |
| | | }; |
| | | |
| | | /** |
| | | * æç´¢æé®æä½ |
| | |
| | | const handleQuery = () => { |
| | | queryParams.value.pageNum = 1; |
| | | getList(); |
| | | } |
| | | }; |
| | | |
| | | /** éç½® */ |
| | | const resetQuery = () => { |
| | | dateRange.value = ['', ''] |
| | | dateRange.value = ['', '']; |
| | | queryFormRef.value?.resetFields(); |
| | | handleQuery(); |
| | | } |
| | | }; |
| | | /**å é¤æé®æä½ */ |
| | | const handleDelete = async (row?: RoleVO) => { |
| | | const roleids = row?.roleId || ids.value; |
| | |
| | | await delRole(roleids); |
| | | getList(); |
| | | proxy?.$modal.msgSuccess('å 餿å'); |
| | | } |
| | | }; |
| | | |
| | | /** å¯¼åºæé®æä½ */ |
| | | const handleExport = () => { |
| | | proxy?.download("system/role/export", { |
| | | ...queryParams.value, |
| | | }, `role_${new Date().getTime()}.xlsx`) |
| | | } |
| | | proxy?.download( |
| | | 'system/role/export', |
| | | { |
| | | ...queryParams.value |
| | | }, |
| | | `role_${new Date().getTime()}.xlsx` |
| | | ); |
| | | }; |
| | | /** å¤éæ¡é䏿°æ® */ |
| | | const handleSelectionChange = (selection: RoleVO[]) => { |
| | | ids.value = selection.map((item: RoleVO) => item.roleId); |
| | | single.value = selection.length != 1; |
| | | multiple.value = !selection.length; |
| | | } |
| | | }; |
| | | |
| | | /** è§è²ç¶æä¿®æ¹ */ |
| | | const handleStatusChange = async (row: RoleVO) => { |
| | | let text = row.status === "0" ? "å¯ç¨" : "åç¨"; |
| | | let text = row.status === '0' ? 'å¯ç¨' : 'åç¨'; |
| | | try { |
| | | await proxy?.$modal.confirm('确认è¦"' + text + '""' + row.roleName + '"è§è²å?'); |
| | | await changeRoleStatus(row.roleId, row.status); |
| | | proxy?.$modal.msgSuccess(text + "æå"); |
| | | proxy?.$modal.msgSuccess(text + 'æå'); |
| | | } catch { |
| | | row.status = row.status === "0" ? "1" : "0"; |
| | | row.status = row.status === '0' ? '1' : '0'; |
| | | } |
| | | } |
| | | }; |
| | | |
| | | /** åé
ç¨æ· */ |
| | | const handleAuthUser = (row: RoleVO) => { |
| | | router.push("/system/role-auth/user/" + row.roleId); |
| | | } |
| | | router.push('/system/role-auth/user/' + row.roleId); |
| | | }; |
| | | |
| | | /** æ¥è¯¢èåæ ç»æ */ |
| | | const getMenuTreeselect = async () => { |
| | | const res = await menuTreeselect(); |
| | | menuOptions.value = res.data; |
| | | } |
| | | }; |
| | | /** ææé¨é¨èç¹æ°æ® */ |
| | | const getDeptAllCheckedKeys = (): any => { |
| | | // ç®å被éä¸çé¨é¨èç¹ |
| | |
| | | if (halfCheckedKeys) { |
| | | checkedKeys?.unshift.apply(checkedKeys, halfCheckedKeys); |
| | | } |
| | | return checkedKeys |
| | | } |
| | | return checkedKeys; |
| | | }; |
| | | /** éç½®æ°å¢ç表å以åå
¶ä»æ°æ® */ |
| | | const reset = () => { |
| | | menuRef.value?.setCheckedKeys([]); |
| | | menuExpand.value = false |
| | | menuNodeAll.value = false |
| | | deptExpand.value = true |
| | | deptNodeAll.value = false |
| | | menuExpand.value = false; |
| | | menuNodeAll.value = false; |
| | | deptExpand.value = true; |
| | | deptNodeAll.value = false; |
| | | form.value = { ...initForm }; |
| | | roleFormRef.value?.resetFields(); |
| | | |
| | | } |
| | | }; |
| | | |
| | | /** æ·»å è§è² */ |
| | | const handleAdd = () => { |
| | | reset(); |
| | | getMenuTreeselect(); |
| | | dialog.visible = true; |
| | | dialog.title = "æ·»å è§è²"; |
| | | } |
| | | dialog.title = 'æ·»å è§è²'; |
| | | }; |
| | | /** ä¿®æ¹è§è² */ |
| | | const handleUpdate = async (row?: RoleVO) => { |
| | | reset(); |
| | | const roleId = row?.roleId || ids.value[0] |
| | | const roleId = row?.roleId || ids.value[0]; |
| | | const { data } = await getRole(roleId); |
| | | Object.assign(form.value, data); |
| | | form.value.roleSort = Number(form.value.roleSort); |
| | | const res = await getRoleMenuTreeselect(roleId); |
| | | dialog.title = "ä¿®æ¹è§è²"; |
| | | dialog.title = 'ä¿®æ¹è§è²'; |
| | | dialog.visible = true; |
| | | res.checkedKeys.forEach((v) => { |
| | | nextTick(() => { |
| | | menuRef.value?.setChecked(v, true, false); |
| | | }) |
| | | }) |
| | | |
| | | } |
| | | }); |
| | | }); |
| | | }; |
| | | /** æ ¹æ®è§è²IDæ¥è¯¢èåæ ç»æ */ |
| | | const getRoleMenuTreeselect = (roleId: string | number) => { |
| | | return roleMenuTreeselect(roleId).then((res): RoleMenuTree => { |
| | | menuOptions.value = res.data.menus; |
| | | return res.data; |
| | | }) |
| | | } |
| | | }); |
| | | }; |
| | | /** æ ¹æ®è§è²IDæ¥è¯¢é¨é¨æ ç»æ */ |
| | | const getRoleDeptTreeSelect = async (roleId: string | number) => { |
| | | const res = await deptTreeSelect(roleId); |
| | | deptOptions.value = res.data.depts; |
| | | return res.data; |
| | | } |
| | | }; |
| | | /** æ æéï¼å±å¼/æå ï¼*/ |
| | | const handleCheckedTreeExpand = (value: boolean, type: string) => { |
| | | if (type == "menu") { |
| | | if (type == 'menu') { |
| | | let treeList = menuOptions.value; |
| | | for (let i = 0; i < treeList.length; i++) { |
| | | if (menuRef.value) { |
| | | menuRef.value.store.nodesMap[treeList[i].id].expanded = value; |
| | | } |
| | | } |
| | | } else if (type == "dept") { |
| | | } else if (type == 'dept') { |
| | | let treeList = deptOptions.value; |
| | | for (let i = 0; i < treeList.length; i++) { |
| | | if (deptRef.value) { |
| | |
| | | } |
| | | } |
| | | } |
| | | } |
| | | }; |
| | | /** æ æéï¼å
¨é/å
¨ä¸éï¼ */ |
| | | const handleCheckedTreeNodeAll = (value: any, type: string) => { |
| | | if (type == "menu") { |
| | | menuRef.value?.setCheckedNodes(value ? menuOptions.value as any : []); |
| | | } else if (type == "dept") { |
| | | deptRef.value?.setCheckedNodes(value ? deptOptions.value as any : []); |
| | | if (type == 'menu') { |
| | | menuRef.value?.setCheckedNodes(value ? (menuOptions.value as any) : []); |
| | | } else if (type == 'dept') { |
| | | deptRef.value?.setCheckedNodes(value ? (deptOptions.value as any) : []); |
| | | } |
| | | } |
| | | }; |
| | | /** æ æéï¼ç¶åèå¨ï¼ */ |
| | | const handleCheckedTreeConnect = (value: any, type: string) => { |
| | | if (type == "menu") { |
| | | if (type == 'menu') { |
| | | form.value.menuCheckStrictly = value; |
| | | } else if (type == "dept") { |
| | | } else if (type == 'dept') { |
| | | form.value.deptCheckStrictly = value; |
| | | } |
| | | } |
| | | }; |
| | | /** ææèåèç¹æ°æ® */ |
| | | const getMenuAllCheckedKeys = (): any => { |
| | | // ç®å被éä¸çèåèç¹ |
| | |
| | | checkedKeys?.unshift.apply(checkedKeys, halfCheckedKeys); |
| | | } |
| | | return checkedKeys; |
| | | } |
| | | }; |
| | | /** æäº¤æé® */ |
| | | const submitForm = () => { |
| | | roleFormRef.value?.validate(async (valid: boolean) => { |
| | | if (valid) { |
| | | form.value.menuIds = getMenuAllCheckedKeys() |
| | | form.value.menuIds = getMenuAllCheckedKeys(); |
| | | form.value.roleId ? await updateRole(form.value) : await addRole(form.value); |
| | | proxy?.$modal.msgSuccess("æä½æå") |
| | | dialog.visible = false |
| | | getList() |
| | | proxy?.$modal.msgSuccess('æä½æå'); |
| | | dialog.visible = false; |
| | | getList(); |
| | | } |
| | | }) |
| | | } |
| | | }); |
| | | }; |
| | | /** åæ¶æé® */ |
| | | const cancel = () => { |
| | | reset() |
| | | reset(); |
| | | dialog.visible = false; |
| | | } |
| | | }; |
| | | /** éæ©è§è²æéèå´è§¦å */ |
| | | const dataScopeSelectChange = (value: string) => { |
| | | if (value !== "2") { |
| | | deptRef.value?.setCheckedKeys([]) |
| | | if (value !== '2') { |
| | | deptRef.value?.setCheckedKeys([]); |
| | | } |
| | | } |
| | | }; |
| | | /** åé
æ°æ®æéæä½ */ |
| | | const handleDataScope = async (row: RoleVO) => { |
| | | const response = await getRole(row.roleId); |
| | | Object.assign(form.value, response.data); |
| | | const res = await getRoleDeptTreeSelect(row.roleId); |
| | | openDataScope.value = true; |
| | | dialog.title = "åé
æ°æ®æé"; |
| | | dialog.title = 'åé
æ°æ®æé'; |
| | | await nextTick(() => { |
| | | deptRef.value?.setCheckedKeys(res.checkedKeys); |
| | | }) |
| | | } |
| | | }); |
| | | }; |
| | | /** æäº¤æé®ï¼æ°æ®æéï¼ */ |
| | | const submitDataScope = async () => { |
| | | if (form.value.roleId) { |
| | | form.value.deptIds = getDeptAllCheckedKeys(); |
| | | await dataScope(form.value); |
| | | proxy?.$modal.msgSuccess("ä¿®æ¹æå"); |
| | | proxy?.$modal.msgSuccess('ä¿®æ¹æå'); |
| | | openDataScope.value = false; |
| | | getList(); |
| | | } |
| | | } |
| | | }; |
| | | /** åæ¶æé®ï¼æ°æ®æéï¼*/ |
| | | const cancelDataScope = () => { |
| | | dataScopeRef.value?.resetFields(); |
| | | form.value = { ...initForm }; |
| | | openDataScope.value = false; |
| | | } |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | getList(); |
| | |
| | | <template> |
| | | <el-row> |
| | | <el-dialog title="éæ©ç¨æ·" v-model="visible" width="800px" top="5vh" append-to-body> |
| | | <el-form :model="queryParams" ref="queryFormRef" :inline="true"> |
| | | <el-dialog v-model="visible" title="éæ©ç¨æ·" width="800px" top="5vh" append-to-body> |
| | | <el-form ref="queryFormRef" :model="queryParams" :inline="true"> |
| | | <el-form-item label="ç¨æ·åç§°" prop="userName"> |
| | | <el-input v-model="queryParams.userName" placeholder="请è¾å
¥ç¨æ·åç§°" clearable @keyup.enter="handleQuery" /> |
| | | </el-form-item> |
| | |
| | | </el-form-item> |
| | | </el-form> |
| | | <el-row> |
| | | <el-table @row-click="clickRow" ref="tableRef" :data="userList" @selection-change="handleSelectionChange" height="260px"> |
| | | <el-table ref="tableRef" :data="userList" height="260px" @row-click="clickRow" @selection-change="handleSelectionChange"> |
| | | <el-table-column type="selection" width="55"></el-table-column> |
| | | <el-table-column label="ç¨æ·åç§°" prop="userName" :show-overflow-tooltip="true" /> |
| | | <el-table-column label="ç¨æ·æµç§°" prop="nickName" :show-overflow-tooltip="true" /> |
| | |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | <pagination v-if="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" /> |
| | | <pagination v-if="total > 0" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" :total="total" @pagination="getList" /> |
| | | </el-row> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | |
| | | </template> |
| | | |
| | | <script setup name="SelectUser" lang="ts"> |
| | | import { authUserSelectAll, unallocatedUserList } from "@/api/system/role"; |
| | | import { authUserSelectAll, unallocatedUserList } from '@/api/system/role'; |
| | | import { UserVO } from '@/api/system/user/types'; |
| | | import { UserQuery } from '@/api/system/user/types'; |
| | | |
| | | |
| | | const props = defineProps({ |
| | | roleId: { |
| | | type: [Number, String] |
| | | } |
| | | }) |
| | | }); |
| | | |
| | | const { proxy } = getCurrentInstance() as ComponentInternalInstance; |
| | | const { sys_normal_disable } = toRefs<any>(proxy?.useDict('sys_normal_disable')); |
| | |
| | | roleId: undefined, |
| | | userName: undefined, |
| | | phonenumber: undefined |
| | | }) |
| | | }); |
| | | |
| | | const tableRef = ref<ElTableInstance>(); |
| | | const queryFormRef = ref<ElFormInstance>(); |
| | |
| | | queryParams.roleId = props.roleId; |
| | | getList(); |
| | | visible.value = true; |
| | | } |
| | | }; |
| | | |
| | | /** |
| | | * éæ©è¡ |
| | |
| | | const clickRow = (row: any) => { |
| | | // eleçbug |
| | | tableRef.value?.toggleRowSelection(row, false); |
| | | } |
| | | }; |
| | | /** å¤éæ¡é䏿°æ® */ |
| | | const handleSelectionChange = (selection: UserVO[]) => { |
| | | userIds.value = selection.map((item: UserVO) => item.userId); |
| | | } |
| | | }; |
| | | |
| | | /** æ¥è¯¢æ°æ® */ |
| | | const getList = async () => { |
| | | const res = await unallocatedUserList(queryParams); |
| | | userList.value = res.rows; |
| | | total.value = res.total; |
| | | } |
| | | }; |
| | | /** æç´¢æé®æä½ */ |
| | | const handleQuery = () => { |
| | | queryParams.pageNum = 1; |
| | | getList(); |
| | | } |
| | | }; |
| | | /** éç½®æé®æä½ */ |
| | | const resetQuery = () => { |
| | | queryFormRef.value?.resetFields(); |
| | | getList(); |
| | | } |
| | | }; |
| | | |
| | | const emit = defineEmits(["ok"]); |
| | | const emit = defineEmits(['ok']); |
| | | /**éæ©ææç¨æ·æä½ */ |
| | | const handleSelectUser = async () => { |
| | | const roleId = queryParams.roleId; |
| | | const ids = userIds.value.join(','); |
| | | if (ids == "") { |
| | | if (ids == '') { |
| | | proxy?.$modal.msgError('è¯·éæ©è¦åé
çç¨æ·'); |
| | | return; |
| | | } |
| | |
| | | proxy?.$modal.msgSuccess('åé
æå'); |
| | | emit('ok'); |
| | | visible.value = false; |
| | | } |
| | | }; |
| | | // æ´é² |
| | | defineExpose({ |
| | | show, |
| | | show |
| | | }); |
| | | </script> |
| | | |
| | |
| | | <template> |
| | | <div class="p-2"> |
| | | <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave"> |
| | | <div class="mb-[10px]" v-show="showSearch"> |
| | | <div v-show="showSearch" class="mb-[10px]"> |
| | | <el-card shadow="hover"> |
| | | <el-form :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px"> |
| | | <el-form ref="queryFormRef" :model="queryParams" :inline="true" label-width="68px"> |
| | | <el-form-item label="ç§æ·ç¼å·" prop="tenantId"> |
| | | <el-input v-model="queryParams.tenantId" placeholder="请è¾å
¥ç§æ·ç¼å·" clearable style="width: 240px" @keyup.enter="handleQuery" /> |
| | | </el-form-item> |
| | |
| | | <template #header> |
| | | <el-row :gutter="10" class="mb8"> |
| | | <el-col :span="1.5"> |
| | | <el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['system:tenant:add']">æ°å¢</el-button> |
| | | <el-button v-hasPermi="['system:tenant:add']" type="primary" plain icon="Plus" @click="handleAdd">æ°å¢</el-button> |
| | | </el-col> |
| | | <el-col :span="1.5"> |
| | | <el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['system:tenant:edit']" |
| | | <el-button v-hasPermi="['system:tenant:edit']" type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" |
| | | >ä¿®æ¹</el-button |
| | | > |
| | | </el-col> |
| | | <el-col :span="1.5"> |
| | | <el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['system:tenant:remove']"> |
| | | <el-button v-hasPermi="['system:tenant:remove']" type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()"> |
| | | å é¤ |
| | | </el-button> |
| | | </el-col> |
| | | <el-col :span="1.5"> |
| | | <el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['system:tenant:export']">导åº</el-button> |
| | | <el-button v-hasPermi="['system:tenant:export']" type="warning" plain icon="Download" @click="handleExport">导åº</el-button> |
| | | </el-col> |
| | | <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar> |
| | | <right-toolbar v-model:showSearch="showSearch" @query-table="getList"></right-toolbar> |
| | | </el-row> |
| | | </template> |
| | | |
| | | <el-table v-loading="loading" :data="tenantList" @selection-change="handleSelectionChange"> |
| | | <el-table-column type="selection" width="55" align="center" /> |
| | | <el-table-column label="id" align="center" prop="id" v-if="false" /> |
| | | <el-table-column v-if="false" label="id" align="center" prop="id" /> |
| | | <el-table-column label="ç§æ·ç¼å·" align="center" prop="tenantId" /> |
| | | <el-table-column label="è系人" align="center" prop="contactUserName" /> |
| | | <el-table-column label="èç³»çµè¯" align="center" prop="contactPhone" /> |
| | |
| | | <el-table-column width="150" label="æä½" align="center" fixed="right" class-name="small-padding fixed-width"> |
| | | <template #default="scope"> |
| | | <el-tooltip content="ä¿®æ¹" placement="top"> |
| | | <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['system:tenant:edit']"></el-button> |
| | | <el-button v-hasPermi="['system:tenant:edit']" link type="primary" icon="Edit" @click="handleUpdate(scope.row)"></el-button> |
| | | </el-tooltip> |
| | | <el-tooltip content="忥å¥é¤" placement="top"> |
| | | <el-button link type="primary" icon="Refresh" @click="handleSyncTenantPackage(scope.row)" v-hasPermi="['system:tenant:edit']"> |
| | | <el-button v-hasPermi="['system:tenant:edit']" link type="primary" icon="Refresh" @click="handleSyncTenantPackage(scope.row)"> |
| | | </el-button> |
| | | </el-tooltip> |
| | | <el-tooltip content="å é¤" placement="top"> |
| | | <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['system:tenant:remove']"></el-button> |
| | | <el-button v-hasPermi="['system:tenant:remove']" link type="primary" icon="Delete" @click="handleDelete(scope.row)"></el-button> |
| | | </el-tooltip> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | |
| | | <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" /> |
| | | <pagination v-show="total > 0" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" :total="total" @pagination="getList" /> |
| | | </el-card> |
| | | <!-- æ·»å æä¿®æ¹ç§æ·å¯¹è¯æ¡ --> |
| | | <el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body> |
| | | <el-dialog v-model="dialog.visible" :title="dialog.title" width="500px" append-to-body> |
| | | <el-form ref="tenantFormRef" :model="form" :rules="rules" label-width="80px"> |
| | | <el-form-item label="ä¼ä¸åç§°" prop="companyName"> |
| | | <el-input v-model="form.companyName" placeholder="请è¾å
¥ä¼ä¸åç§°" /> |
| | |
| | | <el-input v-model="form.username" placeholder="请è¾å
¥ç³»ç»ç¨æ·å" maxlength="30" /> |
| | | </el-form-item> |
| | | <el-form-item v-if="!form.id" label="ç¨æ·å¯ç " prop="password"> |
| | | <el-input type="password" v-model="form.password" placeholder="请è¾å
¥ç³»ç»ç¨æ·å¯ç " maxlength="20" /> |
| | | <el-input v-model="form.password" type="password" placeholder="请è¾å
¥ç³»ç»ç¨æ·å¯ç " maxlength="20" /> |
| | | </el-form-item> |
| | | <el-form-item label="ç§æ·å¥é¤" prop="packageId"> |
| | | <el-select v-model="form.packageId" :disabled="!!form.tenantId" placeholder="è¯·éæ©ç§æ·å¥é¤" clearable style="width: 100%"> |
| | |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="è¿ææ¶é´" prop="expireTime"> |
| | | <el-date-picker clearable v-model="form.expireTime" type="datetime" value-format="YYYY-MM-DD HH:mm:ss" placeholder="è¯·éæ©è¿ææ¶é´"> |
| | | <el-date-picker v-model="form.expireTime" clearable type="datetime" value-format="YYYY-MM-DD HH:mm:ss" placeholder="è¯·éæ©è¿ææ¶é´"> |
| | | </el-date-picker> |
| | | </el-form-item> |
| | | <el-form-item label="ç¨æ·æ°é" prop="accountCount"> |
| | |
| | | <el-input v-model="form.licenseNumber" placeholder="请è¾å
¥ç»ä¸ç¤¾ä¼ä¿¡ç¨ä»£ç " /> |
| | | </el-form-item> |
| | | <el-form-item label="ä¼ä¸ç®ä»" prop="intro"> |
| | | <el-input type="textarea" v-model="form.intro" placeholder="请è¾å
¥ä¼ä¸ç®ä»" /> |
| | | <el-input v-model="form.intro" type="textarea" placeholder="请è¾å
¥ä¼ä¸ç®ä»" /> |
| | | </el-form-item> |
| | | <el-form-item label="夿³¨" prop="remark"> |
| | | <el-input v-model="form.remark" placeholder="请è¾å
¥å¤æ³¨" /> |
| | |
| | | packageId: '', |
| | | expireTime: '', |
| | | accountCount: 0, |
| | | status: '0', |
| | | } |
| | | status: '0' |
| | | }; |
| | | const data = reactive<PageData<TenantForm, TenantQuery>>({ |
| | | form: { ...initFormData }, |
| | | queryParams: { |
| | |
| | | companyName: '' |
| | | }, |
| | | rules: { |
| | | id: [{ required: true, message: "idä¸è½ä¸ºç©º", trigger: "blur" }], |
| | | tenantId: [{ required: true, message: "ç§æ·ç¼å·ä¸è½ä¸ºç©º", trigger: "blur" }], |
| | | contactUserName: [{ required: true, message: "è系人ä¸è½ä¸ºç©º", trigger: "blur" }], |
| | | contactPhone: [{ required: true, message: "èç³»çµè¯ä¸è½ä¸ºç©º", trigger: "blur" }], |
| | | companyName: [{ required: true, message: "ä¼ä¸åç§°ä¸è½ä¸ºç©º", trigger: "blur" }], |
| | | id: [{ required: true, message: 'idä¸è½ä¸ºç©º', trigger: 'blur' }], |
| | | tenantId: [{ required: true, message: 'ç§æ·ç¼å·ä¸è½ä¸ºç©º', trigger: 'blur' }], |
| | | contactUserName: [{ required: true, message: 'è系人ä¸è½ä¸ºç©º', trigger: 'blur' }], |
| | | contactPhone: [{ required: true, message: 'èç³»çµè¯ä¸è½ä¸ºç©º', trigger: 'blur' }], |
| | | companyName: [{ required: true, message: 'ä¼ä¸åç§°ä¸è½ä¸ºç©º', trigger: 'blur' }], |
| | | username: [ |
| | | { required: true, message: "ç¨æ·åä¸è½ä¸ºç©º", trigger: "blur" }, |
| | | { required: true, message: 'ç¨æ·åä¸è½ä¸ºç©º', trigger: 'blur' }, |
| | | { min: 2, max: 20, message: 'ç¨æ·åç§°é¿åº¦å¿
é¡»ä»äº 2 å 20 ä¹é´', trigger: 'blur' } |
| | | ], |
| | | password: [ |
| | | { required: true, message: "å¯ç ä¸è½ä¸ºç©º", trigger: "blur" }, |
| | | { required: true, message: 'å¯ç ä¸è½ä¸ºç©º', trigger: 'blur' }, |
| | | { min: 5, max: 20, message: 'ç¨æ·å¯ç é¿åº¦å¿
é¡»ä»äº 5 å 20 ä¹é´', trigger: 'blur' } |
| | | ] |
| | | } |
| | |
| | | |
| | | /** æ¥è¯¢ææç§æ·å¥é¤ */ |
| | | const getTenantPackage = async () => { |
| | | const res = await selectTenantPackage() |
| | | const res = await selectTenantPackage(); |
| | | packageList.value = res.data; |
| | | } |
| | | }; |
| | | |
| | | /** æ¥è¯¢ç§æ·å表 */ |
| | | const getList = async () => { |
| | |
| | | tenantList.value = res.rows; |
| | | total.value = res.total; |
| | | loading.value = false; |
| | | } |
| | | }; |
| | | |
| | | // ç§æ·å¥é¤ç¶æä¿®æ¹ |
| | | const handleStatusChange = async (row: TenantVO) => { |
| | | let text = row.status === "0" ? "å¯ç¨" : "åç¨"; |
| | | let text = row.status === '0' ? 'å¯ç¨' : 'åç¨'; |
| | | try { |
| | | await proxy?.$modal.confirm('确认è¦"' + text + '""' + row.companyName + '"ç§æ·åï¼'); |
| | | await changeTenantStatus(row.id, row.tenantId, row.status); |
| | | proxy?.$modal.msgSuccess(text + "æå"); |
| | | proxy?.$modal.msgSuccess(text + 'æå'); |
| | | } catch { |
| | | row.status = row.status === "0" ? "1" : "0"; |
| | | row.status = row.status === '0' ? '1' : '0'; |
| | | } |
| | | |
| | | |
| | | } |
| | | }; |
| | | |
| | | // åæ¶æé® |
| | | const cancel = () => { |
| | | reset(); |
| | | dialog.visible = false; |
| | | } |
| | | }; |
| | | |
| | | // 表åéç½® |
| | | const reset = () => { |
| | | form.value = { ...initFormData }; |
| | | tenantFormRef.value?.resetFields(); |
| | | } |
| | | }; |
| | | |
| | | /** æç´¢æé®æä½ */ |
| | | const handleQuery = () => { |
| | | queryParams.value.pageNum = 1; |
| | | getList(); |
| | | } |
| | | }; |
| | | |
| | | /** éç½®æé®æä½ */ |
| | | const resetQuery = () => { |
| | | queryFormRef.value?.resetFields(); |
| | | handleQuery(); |
| | | } |
| | | }; |
| | | |
| | | // å¤éæ¡é䏿°æ® |
| | | const handleSelectionChange = (selection: TenantVO[]) => { |
| | | ids.value = selection.map(item => item.id); |
| | | ids.value = selection.map((item) => item.id); |
| | | single.value = selection.length != 1; |
| | | multiple.value = !selection.length; |
| | | } |
| | | }; |
| | | |
| | | /** æ°å¢æé®æä½ */ |
| | | const handleAdd = () => { |
| | | reset(); |
| | | getTenantPackage(); |
| | | dialog.visible = true; |
| | | dialog.title = "æ·»å ç§æ·"; |
| | | } |
| | | dialog.title = 'æ·»å ç§æ·'; |
| | | }; |
| | | |
| | | /** ä¿®æ¹æé®æä½ */ |
| | | const handleUpdate = async (row?: TenantVO) => { |
| | |
| | | await getTenantPackage(); |
| | | const _id = row?.id || ids.value[0]; |
| | | const res = await getTenant(_id); |
| | | Object.assign(form.value, res.data) |
| | | Object.assign(form.value, res.data); |
| | | dialog.visible = true; |
| | | dialog.title = "ä¿®æ¹ç§æ·"; |
| | | } |
| | | dialog.title = 'ä¿®æ¹ç§æ·'; |
| | | }; |
| | | |
| | | /** æäº¤æé® */ |
| | | const submitForm = () => { |
| | |
| | | if (valid) { |
| | | buttonLoading.value = true; |
| | | if (form.value.id) { |
| | | await updateTenant(form.value).finally(() => buttonLoading.value = false); |
| | | await updateTenant(form.value).finally(() => (buttonLoading.value = false)); |
| | | } else { |
| | | await addTenant(form.value).finally(() => buttonLoading.value = false); |
| | | await addTenant(form.value).finally(() => (buttonLoading.value = false)); |
| | | } |
| | | proxy?.$modal.msgSuccess("æä½æå"); |
| | | proxy?.$modal.msgSuccess('æä½æå'); |
| | | dialog.visible = false; |
| | | await getList(); |
| | | } |
| | | }); |
| | | } |
| | | }; |
| | | |
| | | /** å é¤æé®æä½ */ |
| | | const handleDelete = async (row?: TenantVO) => { |
| | | const _ids = row?.id || ids.value; |
| | | await proxy?.$modal.confirm('æ¯å¦ç¡®è®¤å é¤ç§æ·ç¼å·ä¸º"' + _ids + '"çæ°æ®é¡¹ï¼') |
| | | await proxy?.$modal.confirm('æ¯å¦ç¡®è®¤å é¤ç§æ·ç¼å·ä¸º"' + _ids + '"çæ°æ®é¡¹ï¼'); |
| | | loading.value = true; |
| | | await delTenant(_ids).finally(() => loading.value = false); |
| | | await delTenant(_ids).finally(() => (loading.value = false)); |
| | | await getList(); |
| | | proxy?.$modal.msgSuccess("å 餿å"); |
| | | |
| | | |
| | | } |
| | | proxy?.$modal.msgSuccess('å 餿å'); |
| | | }; |
| | | |
| | | /** åæ¥ç§æ·å¥é¤æé®æä½ */ |
| | | const handleSyncTenantPackage = async (row: TenantVO) => { |
| | |
| | | loading.value = true; |
| | | await syncTenantPackage(row.tenantId, row.packageId); |
| | | await getList(); |
| | | proxy?.$modal.msgSuccess("忥æå"); |
| | | } catch { return } finally { |
| | | proxy?.$modal.msgSuccess('忥æå'); |
| | | } catch { |
| | | return; |
| | | } finally { |
| | | loading.value = false; |
| | | } |
| | | } |
| | | }; |
| | | |
| | | /** å¯¼åºæé®æä½ */ |
| | | const handleExport = () => { |
| | | proxy?.download('system/tenant/export', { |
| | | ...queryParams.value |
| | | }, `tenant_${new Date().getTime()}.xlsx`) |
| | | } |
| | | proxy?.download( |
| | | 'system/tenant/export', |
| | | { |
| | | ...queryParams.value |
| | | }, |
| | | `tenant_${new Date().getTime()}.xlsx` |
| | | ); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | getList(); |
| | | }) |
| | | }); |
| | | </script> |
| | |
| | | <template> |
| | | <div class="p-2"> |
| | | <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave"> |
| | | <div class="mb-[10px]" v-show="showSearch"> |
| | | <div v-show="showSearch" class="mb-[10px]"> |
| | | <el-card shadow="hover"> |
| | | <el-form :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px"> |
| | | <el-form ref="queryFormRef" :model="queryParams" :inline="true" label-width="68px"> |
| | | <el-form-item label="å¥é¤åç§°" prop="packageName"> |
| | | <el-input v-model="queryParams.packageName" placeholder="请è¾å
¥å¥é¤åç§°" clearable style="width: 240px" @keyup.enter="handleQuery" /> |
| | | </el-form-item> |
| | |
| | | <template #header> |
| | | <el-row :gutter="10" class="mb8"> |
| | | <el-col :span="1.5"> |
| | | <el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['system:tenantPackage:add']"> æ°å¢ </el-button> |
| | | <el-button v-hasPermi="['system:tenantPackage:add']" type="primary" plain icon="Plus" @click="handleAdd"> æ°å¢ </el-button> |
| | | </el-col> |
| | | <el-col :span="1.5"> |
| | | <el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['system:tenantPackage:edit']"> |
| | | <el-button v-hasPermi="['system:tenantPackage:edit']" type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()"> |
| | | ä¿®æ¹ |
| | | </el-button> |
| | | </el-col> |
| | | <el-col :span="1.5"> |
| | | <el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['system:tenantPackage:remove']"> |
| | | <el-button v-hasPermi="['system:tenantPackage:remove']" type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()"> |
| | | å é¤ |
| | | </el-button> |
| | | </el-col> |
| | | <el-col :span="1.5"> |
| | | <el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['system:tenantPackage:export']">å¯¼åº </el-button> |
| | | <el-button v-hasPermi="['system:tenantPackage:export']" type="warning" plain icon="Download" @click="handleExport">å¯¼åº </el-button> |
| | | </el-col> |
| | | <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar> |
| | | <right-toolbar v-model:showSearch="showSearch" @query-table="getList"></right-toolbar> |
| | | </el-row> |
| | | </template> |
| | | |
| | | <el-table v-loading="loading" :data="tenantPackageList" @selection-change="handleSelectionChange"> |
| | | <el-table-column type="selection" width="55" align="center" /> |
| | | <el-table-column label="ç§æ·å¥é¤id" align="center" prop="packageId" v-if="false" /> |
| | | <el-table-column v-if="false" label="ç§æ·å¥é¤id" align="center" prop="packageId" /> |
| | | <el-table-column label="å¥é¤åç§°" align="center" prop="packageName" /> |
| | | <el-table-column label="夿³¨" align="center" prop="remark" /> |
| | | <el-table-column label="ç¶æ" align="center" prop="status"> |
| | |
| | | <el-table-column label="æä½" align="center" class-name="small-padding fixed-width"> |
| | | <template #default="scope"> |
| | | <el-tooltip content="ä¿®æ¹" placement="top"> |
| | | <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['system:tenantPackage:edit']"></el-button> |
| | | <el-button v-hasPermi="['system:tenantPackage:edit']" link type="primary" icon="Edit" @click="handleUpdate(scope.row)"></el-button> |
| | | </el-tooltip> |
| | | <el-tooltip content="å é¤" placement="top"> |
| | | <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['system:tenantPackage:remove']"></el-button> |
| | | <el-button v-hasPermi="['system:tenantPackage:remove']" link type="primary" icon="Delete" @click="handleDelete(scope.row)"></el-button> |
| | | </el-tooltip> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | |
| | | <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" /> |
| | | <pagination v-show="total > 0" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" :total="total" @pagination="getList" /> |
| | | </el-card> |
| | | |
| | | <!-- æ·»å æä¿®æ¹ç§æ·å¥é¤å¯¹è¯æ¡ --> |
| | | <el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body> |
| | | <el-dialog v-model="dialog.visible" :title="dialog.title" width="500px" append-to-body> |
| | | <el-form ref="tenantPackageFormRef" :model="form" :rules="rules" label-width="80px"> |
| | | <el-form-item label="å¥é¤åç§°" prop="packageName"> |
| | | <el-input v-model="form.packageName" placeholder="请è¾å
¥å¥é¤åç§°" /> |
| | |
| | | <el-checkbox v-model="menuNodeAll" @change="handleCheckedTreeNodeAll($event, 'menu')">å
¨é/å
¨ä¸é </el-checkbox> |
| | | <el-checkbox v-model="form.menuCheckStrictly" @change="handleCheckedTreeConnect($event, 'menu')">ç¶åèå¨ </el-checkbox> |
| | | <el-tree |
| | | ref="menuTreeRef" |
| | | class="tree-border" |
| | | :data="menuOptions" |
| | | show-checkbox |
| | | ref="menuTreeRef" |
| | | node-key="id" |
| | | :check-strictly="!form.menuCheckStrictly" |
| | | empty-text="å è½½ä¸ï¼è¯·ç¨å" |
| | |
| | | addTenantPackage, |
| | | updateTenantPackage, |
| | | changePackageStatus |
| | | } from "@/api/system/tenantPackage"; |
| | | import { treeselect as menuTreeselect, tenantPackageMenuTreeselect } from "@/api/system/menu"; |
| | | import { TenantPkgForm, TenantPkgQuery, TenantPkgVO } from "@/api/system/tenantPackage/types"; |
| | | import { MenuTreeOption } from "@/api/system/menu/types"; |
| | | import to from "await-to-js"; |
| | | } from '@/api/system/tenantPackage'; |
| | | import { treeselect as menuTreeselect, tenantPackageMenuTreeselect } from '@/api/system/menu'; |
| | | import { TenantPkgForm, TenantPkgQuery, TenantPkgVO } from '@/api/system/tenantPackage/types'; |
| | | import { MenuTreeOption } from '@/api/system/menu/types'; |
| | | import to from 'await-to-js'; |
| | | |
| | | const { proxy } = getCurrentInstance() as ComponentInternalInstance; |
| | | |
| | |
| | | |
| | | const dialog = reactive<DialogOption>({ |
| | | visible: false, |
| | | title: "" |
| | | title: '' |
| | | }); |
| | | |
| | | |
| | | const initFormData: TenantPkgForm = { |
| | | packageId: undefined, |
| | | packageName: "", |
| | | menuIds: "", |
| | | remark: "", |
| | | packageName: '', |
| | | menuIds: '', |
| | | remark: '', |
| | | menuCheckStrictly: true |
| | | }; |
| | | const data = reactive<PageData<TenantPkgForm, TenantPkgQuery>>({ |
| | |
| | | queryParams: { |
| | | pageNum: 1, |
| | | pageSize: 10, |
| | | packageName: "" |
| | | packageName: '' |
| | | }, |
| | | rules: { |
| | | packageId: [{ required: true, message: "ç§æ·å¥é¤idä¸è½ä¸ºç©º", trigger: "blur" }], |
| | | packageName: [{ required: true, message: "å¥é¤åç§°ä¸è½ä¸ºç©º", trigger: "blur" }] |
| | | packageId: [{ required: true, message: 'ç§æ·å¥é¤idä¸è½ä¸ºç©º', trigger: 'blur' }], |
| | | packageName: [{ required: true, message: 'å¥é¤åç§°ä¸è½ä¸ºç©º', trigger: 'blur' }] |
| | | } |
| | | }); |
| | | |
| | |
| | | |
| | | // ç§æ·å¥é¤ç¶æä¿®æ¹ |
| | | const handleStatusChange = async (row: TenantPkgVO) => { |
| | | let text = row.status === "0" ? "å¯ç¨" : "åç¨"; |
| | | const [err] = await to(proxy?.$modal.confirm("确认è¦\"" + text + "\"\"" + row.packageName + "\"å¥é¤åï¼") as Promise<any>); |
| | | let text = row.status === '0' ? 'å¯ç¨' : 'åç¨'; |
| | | const [err] = await to(proxy?.$modal.confirm('确认è¦"' + text + '""' + row.packageName + '"å¥é¤åï¼') as Promise<any>); |
| | | if (err) { |
| | | row.status = row.status === "0" ? "1" : "0"; |
| | | row.status = row.status === '0' ? '1' : '0'; |
| | | } else { |
| | | await changePackageStatus(row.packageId, row.status); |
| | | proxy?.$modal.msgSuccess(text + "æå"); |
| | | proxy?.$modal.msgSuccess(text + 'æå'); |
| | | } |
| | | }; |
| | | |
| | |
| | | |
| | | // å¤éæ¡é䏿°æ® |
| | | const handleSelectionChange = (selection: TenantPkgVO[]) => { |
| | | ids.value = selection.map(item => item.packageId); |
| | | ids.value = selection.map((item) => item.packageId); |
| | | single.value = selection.length != 1; |
| | | multiple.value = !selection.length; |
| | | }; |
| | | |
| | | // æ æéï¼å±å¼/æå ï¼ |
| | | const handleCheckedTreeExpand = (value: CheckboxValueType, type: string) => { |
| | | if (type == "menu") { |
| | | if (type == 'menu') { |
| | | let treeList = menuOptions.value; |
| | | for (let i = 0; i < treeList.length; i++) { |
| | | if (menuTreeRef.value) { |
| | |
| | | |
| | | // æ æéï¼å
¨é/å
¨ä¸éï¼ |
| | | const handleCheckedTreeNodeAll = (value: CheckboxValueType, type: string) => { |
| | | if (type == "menu") { |
| | | menuTreeRef.value?.setCheckedNodes(value ? menuOptions.value as any : []); |
| | | if (type == 'menu') { |
| | | menuTreeRef.value?.setCheckedNodes(value ? (menuOptions.value as any) : []); |
| | | } |
| | | }; |
| | | |
| | | // æ æéï¼ç¶åèå¨ï¼ |
| | | const handleCheckedTreeConnect = (value: CheckboxValueType, type: string) => { |
| | | if (type == "menu") { |
| | | if (type == 'menu') { |
| | | form.value.menuCheckStrictly = value as boolean; |
| | | } |
| | | }; |
| | |
| | | reset(); |
| | | getMenuTreeselect(); |
| | | dialog.visible = true; |
| | | dialog.title = "æ·»å ç§æ·å¥é¤"; |
| | | dialog.title = 'æ·»å ç§æ·å¥é¤'; |
| | | }; |
| | | |
| | | /** ä¿®æ¹æé®æä½ */ |
| | |
| | | form.value = response.data; |
| | | const res = await getPackageMenuTreeselect(_packageId); |
| | | dialog.visible = true; |
| | | dialog.title = "ä¿®æ¹ç§æ·å¥é¤"; |
| | | dialog.title = 'ä¿®æ¹ç§æ·å¥é¤'; |
| | | res.data.checkedKeys.forEach((v) => { |
| | | nextTick(() => { |
| | | menuTreeRef.value?.setChecked(v, true, false); |
| | |
| | | buttonLoading.value = true; |
| | | form.value.menuIds = getMenuAllCheckedKeys(); |
| | | if (form.value.packageId != null) { |
| | | await updateTenantPackage(form.value).finally(() => buttonLoading.value = false); |
| | | await updateTenantPackage(form.value).finally(() => (buttonLoading.value = false)); |
| | | } else { |
| | | await addTenantPackage(form.value).finally(() => buttonLoading.value = false); |
| | | await addTenantPackage(form.value).finally(() => (buttonLoading.value = false)); |
| | | } |
| | | proxy?.$modal.msgSuccess("æä½æå"); |
| | | proxy?.$modal.msgSuccess('æä½æå'); |
| | | dialog.visible = false; |
| | | await getList(); |
| | | } |
| | |
| | | /** å é¤æé®æä½ */ |
| | | const handleDelete = async (row?: TenantPkgVO) => { |
| | | const _packageIds = row?.packageId || ids.value; |
| | | await proxy?.$modal.confirm("æ¯å¦ç¡®è®¤å é¤ç§æ·å¥é¤ç¼å·ä¸º\"" + _packageIds + "\"çæ°æ®é¡¹ï¼").finally(() => { |
| | | await proxy?.$modal.confirm('æ¯å¦ç¡®è®¤å é¤ç§æ·å¥é¤ç¼å·ä¸º"' + _packageIds + '"çæ°æ®é¡¹ï¼').finally(() => { |
| | | loading.value = false; |
| | | }); |
| | | await delTenantPackage(_packageIds); |
| | | loading.value = true; |
| | | await getList(); |
| | | proxy?.$modal.msgSuccess("å 餿å"); |
| | | proxy?.$modal.msgSuccess('å 餿å'); |
| | | }; |
| | | |
| | | /** å¯¼åºæé®æä½ */ |
| | | const handleExport = () => { |
| | | proxy?.download("system/tenantPackage/export", { |
| | | ...queryParams.value |
| | | }, `tenantPackage_${new Date().getTime()}.xlsx`); |
| | | proxy?.download( |
| | | 'system/tenantPackage/export', |
| | | { |
| | | ...queryParams.value |
| | | }, |
| | | `tenantPackage_${new Date().getTime()}.xlsx` |
| | | ); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | |
| | | <h4 class="panel-title">è§è²ä¿¡æ¯</h4> |
| | | <div> |
| | | <el-table |
| | | ref="tableRef" |
| | | v-loading="loading" |
| | | :row-key="getRowKey" |
| | | @row-click="clickRow" |
| | | ref="tableRef" |
| | | @selection-change="handleSelectionChange" |
| | | :data="roles.slice((pageNum - 1) * pageSize, pageNum * pageSize)" |
| | | @row-click="clickRow" |
| | | @selection-change="handleSelectionChange" |
| | | > |
| | | <el-table-column label="åºå·" width="55" type="index" align="center"> |
| | | <template #default="scope"> |
| | |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | <pagination v-show="total > 0" :total="total" v-model:page="pageNum" v-model:limit="pageSize" /> |
| | | <div style="text-align: center;margin-left:-120px;margin-top:30px;"> |
| | | <pagination v-show="total > 0" v-model:page="pageNum" v-model:limit="pageSize" :total="total" /> |
| | | <div style="text-align: center; margin-left: -120px; margin-top: 30px"> |
| | | <el-button type="primary" @click="submitForm()">æäº¤</el-button> |
| | | <el-button @click="close()">è¿å</el-button> |
| | | </div> |
| | |
| | | </template> |
| | | |
| | | <script setup name="AuthRole" lang="ts"> |
| | | import { RoleVO } from "@/api/system/role/types"; |
| | | import { getAuthRole, updateAuthRole } from "@/api/system/user"; |
| | | import { UserForm } from "@/api/system/user/types"; |
| | | import { RoleVO } from '@/api/system/role/types'; |
| | | import { getAuthRole, updateAuthRole } from '@/api/system/user'; |
| | | import { UserForm } from '@/api/system/user/types'; |
| | | |
| | | const route = useRoute(); |
| | | const { proxy } = getCurrentInstance() as ComponentInternalInstance; |
| | |
| | | const roles = ref<RoleVO[]>([]); |
| | | const form = ref<Partial<UserForm>>({ |
| | | nickName: undefined, |
| | | userName: "", |
| | | userName: '', |
| | | userId: undefined |
| | | }); |
| | | |
| | |
| | | }; |
| | | /** å¤éæ¡é䏿°æ® */ |
| | | const handleSelectionChange = (selection: RoleVO[]) => { |
| | | roleIds.value = selection.map(item => item.roleId); |
| | | roleIds.value = selection.map((item) => item.roleId); |
| | | }; |
| | | /** ä¿åéä¸çæ°æ®ç¼å· */ |
| | | const getRowKey = (row: RoleVO): string => { |
| | |
| | | }; |
| | | /** å
³éæé® */ |
| | | const close = () => { |
| | | const obj = { path: "/system/user" }; |
| | | const obj = { path: '/system/user' }; |
| | | proxy?.$tab.closeOpenPage(obj); |
| | | }; |
| | | /** æäº¤æé® */ |
| | | const submitForm = async () => { |
| | | const userId = form.value.userId; |
| | | const rIds = roleIds.value.join(","); |
| | | const rIds = roleIds.value.join(','); |
| | | await updateAuthRole({ userId: userId as string, roleIds: rIds }); |
| | | proxy?.$modal.msgSuccess("æææå"); |
| | | proxy?.$modal.msgSuccess('æææå'); |
| | | close(); |
| | | }; |
| | | |
| | |
| | | Object.assign(roles.value, res.data.roles); |
| | | total.value = roles.value.length; |
| | | await nextTick(() => { |
| | | roles.value.forEach(row => { |
| | | roles.value.forEach((row) => { |
| | | if (row?.flag) { |
| | | tableRef.value?.toggleRowSelection(row, true); |
| | | } |
| | |
| | | <el-card shadow="hover"> |
| | | <el-input v-model="deptName" placeholder="请è¾å
¥é¨é¨åç§°" prefix-icon="Search" clearable /> |
| | | <el-tree |
| | | class="mt-2" |
| | | ref="deptTreeRef" |
| | | class="mt-2" |
| | | node-key="id" |
| | | :data="deptOptions" |
| | | :props="{ label: 'label', children: 'children' }" |
| | |
| | | </el-col> |
| | | <el-col :lg="20" :xs="24"> |
| | | <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave"> |
| | | <div class="mb-[10px]" v-show="showSearch"> |
| | | <div v-show="showSearch" class="mb-[10px]"> |
| | | <el-card shadow="hover"> |
| | | <el-form ref="queryFormRef" :model="queryParams" :inline="true" label-width="68px"> |
| | | <el-form-item label="ç¨æ·åç§°" prop="userName"> |
| | |
| | | <el-option v-for="dict in sys_normal_disable" :key="dict.value" :label="dict.label" :value="dict.value" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="å建æ¶é´" style="width: 308px;"> |
| | | <el-form-item label="å建æ¶é´" style="width: 308px"> |
| | | <el-date-picker |
| | | v-model="dateRange" |
| | | value-format="YYYY-MM-DD" |
| | |
| | | ></el-date-picker> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button type="primary" @click="handleQuery" icon="Search">æç´¢</el-button> |
| | | <el-button @click="resetQuery" icon="Refresh">éç½®</el-button> |
| | | <el-button type="primary" icon="Search" @click="handleQuery">æç´¢</el-button> |
| | | <el-button icon="Refresh" @click="resetQuery">éç½®</el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | </el-card> |
| | |
| | | <template #header> |
| | | <el-row :gutter="10"> |
| | | <el-col :span="1.5"> |
| | | <el-button type="primary" plain @click="handleAdd()" v-has-permi="['system:user:add']" icon="Plus">æ°å¢</el-button> |
| | | <el-button v-has-permi="['system:user:add']" type="primary" plain icon="Plus" @click="handleAdd()">æ°å¢</el-button> |
| | | </el-col> |
| | | <el-col :span="1.5"> |
| | | <el-button type="success" plain @click="handleUpdate()" :disabled="single" v-has-permi="['system:user:add']" icon="Edit"> |
| | | <el-button v-has-permi="['system:user:add']" type="success" plain :disabled="single" icon="Edit" @click="handleUpdate()"> |
| | | ä¿®æ¹ |
| | | </el-button> |
| | | </el-col> |
| | | <el-col :span="1.5"> |
| | | <el-button type="danger" plain @click="handleDelete()" :disabled="multiple" v-has-permi="['system:user:delete']" icon="Delete"> |
| | | <el-button v-has-permi="['system:user:delete']" type="danger" plain :disabled="multiple" icon="Delete" @click="handleDelete()"> |
| | | å é¤ |
| | | </el-button> |
| | | </el-col> |
| | |
| | | ></el-button> |
| | | <template #dropdown> |
| | | <el-dropdown-menu> |
| | | <el-dropdown-item @click="importTemplate" icon="Download">ä¸è½½æ¨¡æ¿</el-dropdown-item> |
| | | <el-dropdown-item @click="handleImport" icon="Top"> 导å
¥æ°æ®</el-dropdown-item> |
| | | <el-dropdown-item @click="handleExport" icon="Download"> å¯¼åºæ°æ®</el-dropdown-item> |
| | | <el-dropdown-item icon="Download" @click="importTemplate">ä¸è½½æ¨¡æ¿</el-dropdown-item> |
| | | <el-dropdown-item icon="Top" @click="handleImport"> 导å
¥æ°æ®</el-dropdown-item> |
| | | <el-dropdown-item icon="Download" @click="handleExport"> å¯¼åºæ°æ®</el-dropdown-item> |
| | | </el-dropdown-menu> |
| | | </template> |
| | | </el-dropdown> |
| | | </el-col> |
| | | <right-toolbar v-model:showSearch="showSearch" @queryTable="getList" :columns="columns" :search="true"></right-toolbar> |
| | | <right-toolbar v-model:showSearch="showSearch" :columns="columns" :search="true" @query-table="getList"></right-toolbar> |
| | | </el-row> |
| | | </template> |
| | | |
| | | <el-table v-loading="loading" :data="userList" @selection-change="handleSelectionChange"> |
| | | <el-table-column type="selection" width="50" align="center" /> |
| | | <el-table-column label="ç¨æ·ç¼å·" align="center" key="userId" prop="userId" v-if="columns[0].visible" /> |
| | | <el-table-column label="ç¨æ·åç§°" align="center" key="userName" prop="userName" v-if="columns[1].visible" :show-overflow-tooltip="true" /> |
| | | <el-table-column label="ç¨æ·æµç§°" align="center" key="nickName" prop="nickName" v-if="columns[2].visible" :show-overflow-tooltip="true" /> |
| | | <el-table-column v-if="columns[0].visible" key="userId" label="ç¨æ·ç¼å·" align="center" prop="userId" /> |
| | | <el-table-column v-if="columns[1].visible" key="userName" label="ç¨æ·åç§°" align="center" prop="userName" :show-overflow-tooltip="true" /> |
| | | <el-table-column v-if="columns[2].visible" key="nickName" label="ç¨æ·æµç§°" align="center" prop="nickName" :show-overflow-tooltip="true" /> |
| | | <el-table-column |
| | | v-if="columns[3].visible" |
| | | key="deptName" |
| | | label="é¨é¨" |
| | | align="center" |
| | | key="deptName" |
| | | prop="dept.deptName" |
| | | v-if="columns[3].visible" |
| | | :show-overflow-tooltip="true" |
| | | /> |
| | | <el-table-column label="ææºå·ç " align="center" key="phonenumber" prop="phonenumber" v-if="columns[4].visible" width="120" /> |
| | | <el-table-column label="ç¶æ" align="center" key="status" v-if="columns[5].visible"> |
| | | <el-table-column v-if="columns[4].visible" key="phonenumber" label="ææºå·ç " align="center" prop="phonenumber" width="120" /> |
| | | <el-table-column v-if="columns[5].visible" key="status" label="ç¶æ" align="center"> |
| | | <template #default="scope"> |
| | | <el-switch v-model="scope.row.status" active-value="0" inactive-value="1" @change="handleStatusChange(scope.row)"></el-switch> |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <el-table-column label="å建æ¶é´" align="center" prop="createTime" v-if="columns[6].visible" width="160"> |
| | | <el-table-column v-if="columns[6].visible" label="å建æ¶é´" align="center" prop="createTime" width="160"> |
| | | <template #default="scope"> |
| | | <span>{{ scope.row.createTime }}</span> |
| | | </template> |
| | |
| | | |
| | | <el-table-column label="æä½" fixed="right" width="180" class-name="small-padding fixed-width"> |
| | | <template #default="scope"> |
| | | <el-tooltip content="ä¿®æ¹" placement="top" v-if="scope.row.userId !== 1"> |
| | | <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['system:user:edit']"></el-button> |
| | | <el-tooltip v-if="scope.row.userId !== 1" content="ä¿®æ¹" placement="top"> |
| | | <el-button v-hasPermi="['system:user:edit']" link type="primary" icon="Edit" @click="handleUpdate(scope.row)"></el-button> |
| | | </el-tooltip> |
| | | <el-tooltip content="å é¤" placement="top" v-if="scope.row.userId !== 1"> |
| | | <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['system:user:remove']"></el-button> |
| | | <el-tooltip v-if="scope.row.userId !== 1" content="å é¤" placement="top"> |
| | | <el-button v-hasPermi="['system:user:remove']" link type="primary" icon="Delete" @click="handleDelete(scope.row)"></el-button> |
| | | </el-tooltip> |
| | | |
| | | <el-tooltip content="éç½®å¯ç " placement="top" v-if="scope.row.userId !== 1"> |
| | | <el-button link type="primary" icon="Key" @click="handleResetPwd(scope.row)" v-hasPermi="['system:user:resetPwd']"></el-button> |
| | | <el-tooltip v-if="scope.row.userId !== 1" content="éç½®å¯ç " placement="top"> |
| | | <el-button v-hasPermi="['system:user:resetPwd']" link type="primary" icon="Key" @click="handleResetPwd(scope.row)"></el-button> |
| | | </el-tooltip> |
| | | |
| | | <el-tooltip content="åé
è§è²" placement="top" v-if="scope.row.userId !== 1"> |
| | | <el-button link type="primary" icon="CircleCheck" @click="handleAuthRole(scope.row)" v-hasPermi="['system:user:edit']"></el-button> |
| | | <el-tooltip v-if="scope.row.userId !== 1" content="åé
è§è²" placement="top"> |
| | | <el-button v-hasPermi="['system:user:edit']" link type="primary" icon="CircleCheck" @click="handleAuthRole(scope.row)"></el-button> |
| | | </el-tooltip> |
| | | </template> |
| | | </el-table-column> |
| | |
| | | |
| | | <pagination |
| | | v-show="total > 0" |
| | | :total="total" |
| | | v-model:page="queryParams.pageNum" |
| | | v-model:limit="queryParams.pageSize" |
| | | :total="total" |
| | | @pagination="getList" |
| | | /> |
| | | </el-card> |
| | |
| | | </el-row> |
| | | |
| | | <!-- æ·»å æä¿®æ¹ç¨æ·é
ç½®å¯¹è¯æ¡ --> |
| | | <el-dialog ref="formDialogRef" :title="dialog.title" v-model="dialog.visible" width="600px" append-to-body @close="closeDialog"> |
| | | <el-form :model="form" :rules="rules" ref="userFormRef" label-width="80px"> |
| | | <el-dialog ref="formDialogRef" v-model="dialog.visible" :title="dialog.title" width="600px" append-to-body @close="closeDialog"> |
| | | <el-form ref="userFormRef" :model="form" :rules="rules" label-width="80px"> |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ç¨æ·æµç§°" prop="nickName"> |
| | |
| | | <el-col :span="12"> |
| | | <el-form-item label="ç¶æ"> |
| | | <el-radio-group v-model="form.status"> |
| | | <el-radio v-for="dict in sys_normal_disable" :key="dict.value" :label="dict.value">{{ |
| | | dict.label }}</el-radio> |
| | | <el-radio v-for="dict in sys_normal_disable" :key="dict.value" :label="dict.value">{{ dict.label }}</el-radio> |
| | | </el-radio-group> |
| | | </el-form-item> |
| | | </el-col> |
| | |
| | | </el-dialog> |
| | | |
| | | <!-- ç¨æ·å¯¼å
¥å¯¹è¯æ¡ --> |
| | | <el-dialog :title="upload.title" v-model="upload.open" width="400px" append-to-body> |
| | | <el-dialog v-model="upload.open" :title="upload.title" width="400px" append-to-body> |
| | | <el-upload |
| | | ref="uploadRef" |
| | | :limit="1" |
| | |
| | | <div class="text-center el-upload__tip"> |
| | | <div class="el-upload__tip"><el-checkbox v-model="upload.updateSupport" />æ¯å¦æ´æ°å·²ç»åå¨çç¨æ·æ°æ®</div> |
| | | <span>ä»
å
许导å
¥xlsãxlsxæ ¼å¼æä»¶ã</span> |
| | | <el-link type="primary" :underline="false" style="font-size:12px;vertical-align: baseline;" @click="importTemplate">ä¸è½½æ¨¡æ¿</el-link> |
| | | <el-link type="primary" :underline="false" style="font-size: 12px; vertical-align: baseline" @click="importTemplate">ä¸è½½æ¨¡æ¿</el-link> |
| | | </div> |
| | | </template> |
| | | </el-upload> |
| | |
| | | </template> |
| | | |
| | | <script setup name="User" lang="ts"> |
| | | import api from "@/api/system/user" |
| | | import api from '@/api/system/user'; |
| | | import { UserForm, UserQuery, UserVO } from '@/api/system/user/types'; |
| | | import { treeselect } from "@/api/system/dept"; |
| | | import { DeptVO } from "@/api/system/dept/types"; |
| | | import { RoleVO } from "@/api/system/role/types"; |
| | | import { PostVO } from "@/api/system/post/types"; |
| | | import { to } from "await-to-js"; |
| | | import { globalHeaders } from "@/utils/request"; |
| | | import { treeselect } from '@/api/system/dept'; |
| | | import { DeptVO } from '@/api/system/dept/types'; |
| | | import { RoleVO } from '@/api/system/role/types'; |
| | | import { PostVO } from '@/api/system/post/types'; |
| | | import { to } from 'await-to-js'; |
| | | import { globalHeaders } from '@/utils/request'; |
| | | |
| | | const router = useRouter(); |
| | | const { proxy } = getCurrentInstance() as ComponentInternalInstance |
| | | const { proxy } = getCurrentInstance() as ComponentInternalInstance; |
| | | const { sys_normal_disable, sys_user_sex } = toRefs<any>(proxy?.useDict('sys_normal_disable', 'sys_user_sex')); |
| | | |
| | | const userList = ref<UserVO[]>(); |
| | | const loading = ref(true); |
| | | const showSearch = ref(true) |
| | | const showSearch = ref(true); |
| | | const ids = ref<Array<number | string>>([]); |
| | | const single = ref(true); |
| | | const multiple = ref(true); |
| | |
| | | const dateRange = ref<[DateModelType, DateModelType]>(['', '']); |
| | | const deptName = ref(''); |
| | | const deptOptions = ref<DeptVO[]>([]); |
| | | const initPassword = ref<String>(''); |
| | | const initPassword = ref<string>(''); |
| | | const postOptions = ref<PostVO[]>([]); |
| | | const roleOptions = ref<RoleVO[]>([]); |
| | | /*** ç¨æ·å¯¼å
¥åæ° */ |
| | |
| | | // æ¯å¦æ¾ç¤ºå¼¹åºå±ï¼ç¨æ·å¯¼å
¥ï¼ |
| | | open: false, |
| | | // å¼¹åºå±æ é¢ï¼ç¨æ·å¯¼å
¥ï¼ |
| | | title: "", |
| | | title: '', |
| | | // æ¯å¦ç¦ç¨ä¸ä¼ |
| | | isUploading: false, |
| | | // æ¯å¦æ´æ°å·²ç»åå¨çç¨æ·æ°æ® |
| | |
| | | // 设置ä¸ä¼ ç请æ±å¤´é¨ |
| | | headers: globalHeaders(), |
| | | // ä¸ä¼ çå°å |
| | | url: import.meta.env.VITE_APP_BASE_API + "/system/user/importData" |
| | | }) |
| | | url: import.meta.env.VITE_APP_BASE_API + '/system/user/importData' |
| | | }); |
| | | // åæ¾éä¿¡æ¯ |
| | | const columns = ref<FieldOption[]>([ |
| | | { key: 0, label: `ç¨æ·ç¼å·`, visible: false,children: [] }, |
| | | { key: 1, label: `ç¨æ·åç§°`, visible: true,children: [] }, |
| | | { key: 2, label: `ç¨æ·æµç§°`, visible: true,children: [] }, |
| | | { key: 3, label: `é¨é¨`, visible: true,children: [] }, |
| | | { key: 4, label: `ææºå·ç `, visible: true,children: [] }, |
| | | { key: 5, label: `ç¶æ`, visible: true,children: [] }, |
| | | { key: 6, label: `å建æ¶é´`, visible: true,children: [] } |
| | | ]) |
| | | |
| | | { key: 0, label: `ç¨æ·ç¼å·`, visible: false, children: [] }, |
| | | { key: 1, label: `ç¨æ·åç§°`, visible: true, children: [] }, |
| | | { key: 2, label: `ç¨æ·æµç§°`, visible: true, children: [] }, |
| | | { key: 3, label: `é¨é¨`, visible: true, children: [] }, |
| | | { key: 4, label: `ææºå·ç `, visible: true, children: [] }, |
| | | { key: 5, label: `ç¶æ`, visible: true, children: [] }, |
| | | { key: 6, label: `å建æ¶é´`, visible: true, children: [] } |
| | | ]); |
| | | |
| | | const deptTreeRef = ref<ElTreeInstance>(); |
| | | const queryFormRef = ref<ElFormInstance>(); |
| | |
| | | phonenumber: undefined, |
| | | email: undefined, |
| | | sex: undefined, |
| | | status: "0", |
| | | status: '0', |
| | | remark: '', |
| | | postIds: [], |
| | | roleIds: [] |
| | | } |
| | | }; |
| | | const data = reactive<PageData<UserForm, UserQuery>>({ |
| | | form: { ...initFormData }, |
| | | queryParams: { |
| | |
| | | deptId: '' |
| | | }, |
| | | rules: { |
| | | userName: [{ required: true, message: "ç¨æ·åç§°ä¸è½ä¸ºç©º", trigger: "blur" }, { min: 2, max: 20, message: "ç¨æ·åç§°é¿åº¦å¿
é¡»ä»äº 2 å 20 ä¹é´", trigger: "blur" }], |
| | | nickName: [{ required: true, message: "ç¨æ·æµç§°ä¸è½ä¸ºç©º", trigger: "blur" }], |
| | | password: [{ required: true, message: "ç¨æ·å¯ç ä¸è½ä¸ºç©º", trigger: "blur" }, { min: 5, max: 20, message: "ç¨æ·å¯ç é¿åº¦å¿
é¡»ä»äº 5 å 20 ä¹é´", trigger: "blur" }], |
| | | email: [{ type: "email", message: "请è¾å
¥æ£ç¡®çé®ç®±å°å", trigger: ["blur", "change"] }], |
| | | phonenumber: [{ pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/, message: "请è¾å
¥æ£ç¡®çææºå·ç ", trigger: "blur" }] |
| | | userName: [ |
| | | { required: true, message: 'ç¨æ·åç§°ä¸è½ä¸ºç©º', trigger: 'blur' }, |
| | | { |
| | | min: 2, |
| | | max: 20, |
| | | message: 'ç¨æ·åç§°é¿åº¦å¿
é¡»ä»äº 2 å 20 ä¹é´', |
| | | trigger: 'blur' |
| | | } |
| | | ], |
| | | nickName: [{ required: true, message: 'ç¨æ·æµç§°ä¸è½ä¸ºç©º', trigger: 'blur' }], |
| | | password: [ |
| | | { required: true, message: 'ç¨æ·å¯ç ä¸è½ä¸ºç©º', trigger: 'blur' }, |
| | | { |
| | | min: 5, |
| | | max: 20, |
| | | message: 'ç¨æ·å¯ç é¿åº¦å¿
é¡»ä»äº 5 å 20 ä¹é´', |
| | | trigger: 'blur' |
| | | } |
| | | ], |
| | | email: [ |
| | | { |
| | | type: 'email', |
| | | message: '请è¾å
¥æ£ç¡®çé®ç®±å°å', |
| | | trigger: ['blur', 'change'] |
| | | } |
| | | ], |
| | | phonenumber: [ |
| | | { |
| | | pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/, |
| | | message: '请è¾å
¥æ£ç¡®çææºå·ç ', |
| | | trigger: 'blur' |
| | | } |
| | | ] |
| | | } |
| | | }) |
| | | }); |
| | | |
| | | const { queryParams, form, rules } = toRefs<PageData<UserForm, UserQuery>>(data) |
| | | const { queryParams, form, rules } = toRefs<PageData<UserForm, UserQuery>>(data); |
| | | |
| | | /** éè¿æ¡ä»¶è¿æ»¤èç¹ */ |
| | | const filterNode = (value: string, data: any) => { |
| | | if (!value) return true |
| | | return data.label.indexOf(value) !== -1 |
| | | } |
| | | if (!value) return true; |
| | | return data.label.indexOf(value) !== -1; |
| | | }; |
| | | /** æ ¹æ®åç§°çéé¨é¨æ */ |
| | | watchEffect( |
| | | () => { deptTreeRef.value?.filter(deptName.value); }, |
| | | () => { |
| | | deptTreeRef.value?.filter(deptName.value); |
| | | }, |
| | | { |
| | | flush: 'post' // watchEffectä¼å¨DOMæè½½æè
æ´æ°ä¹åå°±ä¼è§¦åï¼æ¤å±æ§æ§å¶å¨DOMå
ç´ æ´æ°åè¿è¡ |
| | | } |
| | |
| | | loading.value = false; |
| | | userList.value = res.rows; |
| | | total.value = res.total; |
| | | } |
| | | }; |
| | | |
| | | /** èç¹åå»äºä»¶ */ |
| | | const handleNodeClick = (data: DeptVO) => { |
| | | queryParams.value.deptId = data.id; |
| | | handleQuery() |
| | | } |
| | | |
| | | handleQuery(); |
| | | }; |
| | | |
| | | /** æç´¢æé®æä½ */ |
| | | const handleQuery = () => { |
| | | queryParams.value.pageNum = 1 |
| | | getList() |
| | | } |
| | | queryParams.value.pageNum = 1; |
| | | getList(); |
| | | }; |
| | | /** éç½®æé®æä½ */ |
| | | const resetQuery = () => { |
| | | dateRange.value = ['', ''] |
| | | dateRange.value = ['', '']; |
| | | queryFormRef.value?.resetFields(); |
| | | queryParams.value.pageNum = 1; |
| | | queryParams.value.deptId = undefined; |
| | | deptTreeRef.value?.setCurrentKey(undefined); |
| | | handleQuery(); |
| | | } |
| | | }; |
| | | |
| | | /** å é¤æé®æä½ */ |
| | | const handleDelete = async (row?: UserVO) => { |
| | |
| | | if (!err) { |
| | | await api.delUser(userIds); |
| | | await getList(); |
| | | proxy?.$modal.msgSuccess("å 餿å"); |
| | | proxy?.$modal.msgSuccess('å 餿å'); |
| | | } |
| | | } |
| | | }; |
| | | |
| | | /** ç¨æ·ç¶æä¿®æ¹ */ |
| | | const handleStatusChange = async (row: UserVO) => { |
| | | let text = row.status === "0" ? "å¯ç¨" : "åç¨" |
| | | let text = row.status === '0' ? 'å¯ç¨' : 'åç¨'; |
| | | try { |
| | | await proxy?.$modal.confirm('确认è¦"' + text + '""' + row.userName + '"ç¨æ·å?'); |
| | | await api.changeUserStatus(row.userId, row.status); |
| | | proxy?.$modal.msgSuccess(text + "æå"); |
| | | proxy?.$modal.msgSuccess(text + 'æå'); |
| | | } catch (err) { |
| | | row.status = row.status === "0" ? "1" : "0"; |
| | | row.status = row.status === '0' ? '1' : '0'; |
| | | } |
| | | } |
| | | }; |
| | | /** 跳转è§è²åé
*/ |
| | | const handleAuthRole = (row: UserVO) => { |
| | | const userId = row.userId; |
| | | router.push("/system/user-auth/role/" + userId); |
| | | } |
| | | router.push('/system/user-auth/role/' + userId); |
| | | }; |
| | | |
| | | /** éç½®å¯ç æé®æä½ */ |
| | | const handleResetPwd = async (row: UserVO) => { |
| | | const [err, res] = await to(ElMessageBox.prompt('请è¾å
¥"' + row.userName + '"çæ°å¯ç ', "æç¤º", { |
| | | confirmButtonText: "ç¡®å®", |
| | | cancelButtonText: "åæ¶", |
| | | closeOnClickModal: false, |
| | | inputPattern: /^.{5,20}$/, |
| | | inputErrorMessage: "ç¨æ·å¯ç é¿åº¦å¿
é¡»ä»äº 5 å 20 ä¹é´", |
| | | })) |
| | | const [err, res] = await to( |
| | | ElMessageBox.prompt('请è¾å
¥"' + row.userName + '"çæ°å¯ç ', 'æç¤º', { |
| | | confirmButtonText: 'ç¡®å®', |
| | | cancelButtonText: 'åæ¶', |
| | | closeOnClickModal: false, |
| | | inputPattern: /^.{5,20}$/, |
| | | inputErrorMessage: 'ç¨æ·å¯ç é¿åº¦å¿
é¡»ä»äº 5 å 20 ä¹é´' |
| | | }) |
| | | ); |
| | | if (!err) { |
| | | await api.resetUserPwd(row.userId, res.value); |
| | | proxy?.$modal.msgSuccess("ä¿®æ¹æåï¼æ°å¯ç æ¯ï¼" + res.value); |
| | | proxy?.$modal.msgSuccess('ä¿®æ¹æåï¼æ°å¯ç æ¯ï¼' + res.value); |
| | | } |
| | | } |
| | | }; |
| | | |
| | | /** éæ©æ¡æ° */ |
| | | const handleSelectionChange = (selection: UserVO[]) => { |
| | | ids.value = selection.map((item) => item.userId); |
| | | single.value = selection.length != 1; |
| | | multiple.value = !selection.length; |
| | | } |
| | | }; |
| | | |
| | | /** 导å
¥æé®æä½ */ |
| | | const handleImport = () => { |
| | | upload.title = "ç¨æ·å¯¼å
¥"; |
| | | upload.title = 'ç¨æ·å¯¼å
¥'; |
| | | upload.open = true; |
| | | } |
| | | }; |
| | | /** å¯¼åºæé®æä½ */ |
| | | const handleExport = () => { |
| | | proxy?.download("system/user/export", { |
| | | ...queryParams.value, |
| | | }, `user_${new Date().getTime()}.xlsx`); |
| | | proxy?.download( |
| | | 'system/user/export', |
| | | { |
| | | ...queryParams.value |
| | | }, |
| | | `user_${new Date().getTime()}.xlsx` |
| | | ); |
| | | }; |
| | | /** ä¸è½½æ¨¡æ¿æä½ */ |
| | | const importTemplate = () => { |
| | | proxy?.download("system/user/importTemplate", { |
| | | }, `user_template_${new Date().getTime()}.xlsx`); |
| | | } |
| | | proxy?.download('system/user/importTemplate', {}, `user_template_${new Date().getTime()}.xlsx`); |
| | | }; |
| | | |
| | | /**æä»¶ä¸ä¼ ä¸å¤ç */ |
| | | const handleFileUploadProgress = () => { |
| | | upload.isUploading = true; |
| | | } |
| | | }; |
| | | /** æä»¶ä¸ä¼ æåå¤ç */ |
| | | const handleFileSuccess = (response: any, file: UploadFile) => { |
| | | upload.open = false; |
| | | upload.isUploading = false; |
| | | uploadRef.value?.handleRemove(file); |
| | | ElMessageBox.alert("<div style='overflow: auto;overflow-x: hidden;max-height: 70vh;padding: 10px 20px 0;'>" + response.msg + "</div>", "导å
¥ç»æ", { dangerouslyUseHTMLString: true }); |
| | | ElMessageBox.alert("<div style='overflow: auto;overflow-x: hidden;max-height: 70vh;padding: 10px 20px 0;'>" + response.msg + '</div>', '导å
¥ç»æ', { |
| | | dangerouslyUseHTMLString: true |
| | | }); |
| | | getList(); |
| | | } |
| | | }; |
| | | |
| | | /** æäº¤ä¸ä¼ æä»¶ */ |
| | | function submitFileForm() { |
| | |
| | | const { data } = await treeselect(); |
| | | deptOptions.value = data; |
| | | } |
| | | } |
| | | |
| | | }; |
| | | |
| | | /** éç½®æä½è¡¨å */ |
| | | const reset = () => { |
| | | form.value = { ...initFormData }; |
| | | userFormRef.value?.resetFields(); |
| | | } |
| | | }; |
| | | /** åæ¶æé® */ |
| | | const cancel = () => { |
| | | dialog.visible = false; |
| | | reset(); |
| | | } |
| | | }; |
| | | |
| | | /** æ°å¢æé®æä½ */ |
| | | const handleAdd = async () => { |
| | | reset(); |
| | | const { data } = await api.getUser(); |
| | | dialog.visible = true; |
| | | dialog.title = "æ°å¢ç¨æ·"; |
| | | dialog.title = 'æ°å¢ç¨æ·'; |
| | | await initTreeData(); |
| | | postOptions.value = data.posts; |
| | | roleOptions.value = data.roles; |
| | | form.value.password = initPassword.value.toString(); |
| | | } |
| | | }; |
| | | /** ä¿®æ¹æé®æä½ */ |
| | | const handleUpdate = async (row?: UserForm) => { |
| | | reset(); |
| | | const userId = row?.userId || ids.value[0] |
| | | const { data } = await api.getUser(userId) |
| | | const userId = row?.userId || ids.value[0]; |
| | | const { data } = await api.getUser(userId); |
| | | dialog.visible = true; |
| | | dialog.title = "ä¿®æ¹ç¨æ·"; |
| | | dialog.title = 'ä¿®æ¹ç¨æ·'; |
| | | await initTreeData(); |
| | | Object.assign(form.value, data.user); |
| | | postOptions.value = data.posts; |
| | | roleOptions.value = data.roles; |
| | | form.value.postIds = data.postIds; |
| | | form.value.roleIds = data.roleIds; |
| | | form.value.password = ""; |
| | | } |
| | | form.value.password = ''; |
| | | }; |
| | | |
| | | /** æäº¤æé® */ |
| | | const submitForm = () => { |
| | | userFormRef.value?.validate(async (valid: boolean) => { |
| | | if (valid) { |
| | | form.value.userId ? await api.updateUser(form.value) : await api.addUser(form.value); |
| | | proxy?.$modal.msgSuccess("æä½æå"); |
| | | proxy?.$modal.msgSuccess('æä½æå'); |
| | | dialog.visible = false; |
| | | await getList(); |
| | | } |
| | | }) |
| | | } |
| | | |
| | | }); |
| | | }; |
| | | |
| | | /** |
| | | * å
³éç¨æ·å¼¹çª |
| | |
| | | const closeDialog = () => { |
| | | dialog.visible = false; |
| | | resetForm(); |
| | | } |
| | | }; |
| | | |
| | | /** |
| | | * é置表å |
| | |
| | | |
| | | form.value.id = undefined; |
| | | form.value.status = '1'; |
| | | } |
| | | }; |
| | | onMounted(() => { |
| | | getTreeSelect() // åå§åé¨é¨æ°æ® |
| | | getList() // åå§ååè¡¨æ°æ® |
| | | proxy?.getConfigKey("sys.user.initPassword").then(response => { |
| | | getTreeSelect(); // åå§åé¨é¨æ°æ® |
| | | getList(); // åå§ååè¡¨æ°æ® |
| | | proxy?.getConfigKey('sys.user.initPassword').then((response) => { |
| | | initPassword.value = response.data; |
| | | }); |
| | | }); |
| | |
| | | <el-row :gutter="20"> |
| | | <el-col :span="6" :xs="24"> |
| | | <el-card class="box-card"> |
| | | <template v-slot:header> |
| | | <template #header> |
| | | <div class="clearfix"> |
| | | <span>个人信æ¯</span> |
| | | </div> |
| | | </template> |
| | | <div> |
| | | <div class="text-center"> |
| | | <userAvatar/> |
| | | <userAvatar /> |
| | | </div> |
| | | <ul class="list-group list-group-striped"> |
| | | <li class="list-group-item"> |
| | |
| | | </li> |
| | | <li class="list-group-item"> |
| | | <svg-icon icon-class="tree" />æå±é¨é¨ |
| | | <div class="pull-right" v-if="state.user.dept">{{ state.user.dept.deptName }} / {{ state.postGroup }}</div> |
| | | <div v-if="state.user.dept" class="pull-right">{{ state.user.dept.deptName }} / {{ state.postGroup }}</div> |
| | | </li> |
| | | <li class="list-group-item"> |
| | | <svg-icon icon-class="peoples" />æå±è§è² |
| | |
| | | </el-col> |
| | | <el-col :span="18" :xs="24"> |
| | | <el-card> |
| | | <template v-slot:header> |
| | | <template #header> |
| | | <div class="clearfix"> |
| | | <span>åºæ¬èµæ</span> |
| | | </div> |
| | |
| | | </template> |
| | | |
| | | <script setup name="Profile" lang="ts"> |
| | | import UserAvatar from "./userAvatar.vue"; |
| | | import UserInfo from "./userInfo.vue"; |
| | | import ResetPwd from "./resetPwd.vue"; |
| | | import ThirdParty from "./thirdParty.vue"; |
| | | import { getAuthList } from "@/api/system/social/auth"; |
| | | import { getUserProfile } from "@/api/system/user"; |
| | | import UserAvatar from './userAvatar.vue'; |
| | | import UserInfo from './userInfo.vue'; |
| | | import ResetPwd from './resetPwd.vue'; |
| | | import ThirdParty from './thirdParty.vue'; |
| | | import { getAuthList } from '@/api/system/social/auth'; |
| | | import { getUserProfile } from '@/api/system/user'; |
| | | |
| | | const activeTab = ref("userinfo"); |
| | | const activeTab = ref('userinfo'); |
| | | const state = ref<Record<string, any>>({ |
| | | user: {}, |
| | | roleGroup: '', |
| | | postGroup: '', |
| | | auths: [] |
| | | user: {}, |
| | | roleGroup: '', |
| | | postGroup: '', |
| | | auths: [] |
| | | }); |
| | | |
| | | const userForm = ref({}); |
| | | |
| | | const getUser = async () => { |
| | | const res = await getUserProfile(); |
| | | state.value.user = res.data.user; |
| | | userForm.value = { ...res.data.user } |
| | | state.value.roleGroup = res.data.roleGroup; |
| | | state.value.postGroup = res.data.postGroup; |
| | | const res = await getUserProfile(); |
| | | state.value.user = res.data.user; |
| | | userForm.value = { ...res.data.user }; |
| | | state.value.roleGroup = res.data.roleGroup; |
| | | state.value.postGroup = res.data.postGroup; |
| | | }; |
| | | |
| | | const getAuths = async () => { |
| | | const res = await getAuthList(); |
| | | state.value.auths = res.data; |
| | | const res = await getAuthList(); |
| | | state.value.auths = res.data; |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | getUser(); |
| | | getAuths(); |
| | | }) |
| | | getUser(); |
| | | getAuths(); |
| | | }); |
| | | </script> |
| | |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import { updateUserPwd } from "@/api/system/user"; |
| | | import type { ResetPwdForm } from "@/api/system/user/types"; |
| | | import { updateUserPwd } from '@/api/system/user'; |
| | | import type { ResetPwdForm } from '@/api/system/user/types'; |
| | | |
| | | const { proxy } = getCurrentInstance() as ComponentInternalInstance; |
| | | const pwdRef = ref<ElFormInstance>(); |
| | | const user = ref<ResetPwdForm>({ |
| | | oldPassword: "", |
| | | newPassword: "", |
| | | confirmPassword: "" |
| | | oldPassword: '', |
| | | newPassword: '', |
| | | confirmPassword: '' |
| | | }); |
| | | |
| | | const equalToPassword = (rule: any, value: string, callback: any) => { |
| | | if (user.value.newPassword !== value) { |
| | | callback(new Error("两次è¾å
¥çå¯ç ä¸ä¸è´")); |
| | | callback(new Error('两次è¾å
¥çå¯ç ä¸ä¸è´')); |
| | | } else { |
| | | callback(); |
| | | } |
| | | }; |
| | | const rules = ref({ |
| | | oldPassword: [{ required: true, message: "æ§å¯ç ä¸è½ä¸ºç©º", trigger: "blur" }], |
| | | newPassword: [{ required: true, message: "æ°å¯ç ä¸è½ä¸ºç©º", trigger: "blur" }, { |
| | | min: 6, |
| | | max: 20, |
| | | message: "é¿åº¦å¨ 6 å° 20 个å符", |
| | | trigger: "blur" |
| | | }], |
| | | confirmPassword: [{ required: true, message: "确认å¯ç ä¸è½ä¸ºç©º", trigger: "blur" }, { |
| | | required: true, |
| | | validator: equalToPassword, |
| | | trigger: "blur" |
| | | }] |
| | | oldPassword: [{ required: true, message: 'æ§å¯ç ä¸è½ä¸ºç©º', trigger: 'blur' }], |
| | | newPassword: [ |
| | | { required: true, message: 'æ°å¯ç ä¸è½ä¸ºç©º', trigger: 'blur' }, |
| | | { |
| | | min: 6, |
| | | max: 20, |
| | | message: 'é¿åº¦å¨ 6 å° 20 个å符', |
| | | trigger: 'blur' |
| | | } |
| | | ], |
| | | confirmPassword: [ |
| | | { required: true, message: '确认å¯ç ä¸è½ä¸ºç©º', trigger: 'blur' }, |
| | | { |
| | | required: true, |
| | | validator: equalToPassword, |
| | | trigger: 'blur' |
| | | } |
| | | ] |
| | | }); |
| | | |
| | | /** æäº¤æé® */ |
| | |
| | | pwdRef.value?.validate(async (valid: boolean) => { |
| | | if (valid) { |
| | | await updateUserPwd(user.value.oldPassword, user.value.newPassword); |
| | | proxy?.$modal.msgSuccess("ä¿®æ¹æå"); |
| | | proxy?.$modal.msgSuccess('ä¿®æ¹æå'); |
| | | } |
| | | }); |
| | | }; |
| | |
| | | <el-table-column label="åºå·" width="50" type="index"></el-table-column> |
| | | <el-table-column label="ç»å®è´¦å·å¹³å°" width="140" align="center" prop="source" show-overflow-tooltip /> |
| | | <el-table-column label="头å" width="120" align="center" prop="avatar"> |
| | | <template v-slot="scope"> |
| | | <template #default="scope"> |
| | | <img :src="scope.row.avatar" style="width: 45px; height: 45px" /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="ç³»ç»è´¦å·" width="180" align="center" prop="userName" :show-overflow-tooltip="true" /> |
| | | <el-table-column label="ç»å®æ¶é´" width="180" align="center" prop="createTime" /> |
| | | <el-table-column label="æä½" width="80" align="center" class-name="small-padding fixed-width"> |
| | | <template v-slot="scope"> |
| | | <template #default="scope"> |
| | | <el-button size="small" type="text" @click="unlockAuth(scope.row)">è§£ç»</el-button> |
| | | </template> |
| | | </el-table-column> |
| | |
| | | <div id="git-user-binding"> |
| | | <h4 class="provider-desc">ä½ å¯ä»¥ç»å®ä»¥ä¸ç¬¬ä¸æ¹å¸å·</h4> |
| | | <div id="authlist" class="user-bind"> |
| | | <a class="third-app" href="#" @click="authUrl('wechat');" title="ä½¿ç¨ å¾®ä¿¡ è´¦å·ææç»å½"> |
| | | <a class="third-app" href="#" title="ä½¿ç¨ å¾®ä¿¡ è´¦å·ææç»å½" @click="authUrl('wechat')"> |
| | | <div class="git-other-login-icon"> |
| | | <svg-icon icon-class="wechat" /> |
| | | </div> |
| | | <span class="app-name">WeiXin</span> |
| | | </a> |
| | | <a class="third-app" href="#" @click="authUrl('maxkey');" title="ä½¿ç¨ MaxKey è´¦å·ææç»å½"> |
| | | <a class="third-app" href="#" title="ä½¿ç¨ MaxKey è´¦å·ææç»å½" @click="authUrl('maxkey')"> |
| | | <div class="git-other-login-icon"> |
| | | <svg-icon icon-class="maxkey" /> |
| | | </div> |
| | | <span class="app-name">MaxKey</span> |
| | | </a> |
| | | <a class="third-app" href="#" @click="authUrl('gitee');" title="ä½¿ç¨ Gitee è´¦å·ææç»å½"> |
| | | <a class="third-app" href="#" title="ä½¿ç¨ Gitee è´¦å·ææç»å½" @click="authUrl('gitee')"> |
| | | <div class="git-other-login-icon"> |
| | | <svg-icon icon-class="gitee" /> |
| | | </div> |
| | | <span class="app-name">Gitee</span> |
| | | </a> |
| | | <a class="third-app" href="#" @click="authUrl('github');" title="ä½¿ç¨ GitHub è´¦å·ææç»å½"> |
| | | <a class="third-app" href="#" title="ä½¿ç¨ GitHub è´¦å·ææç»å½" @click="authUrl('github')"> |
| | | <div class="git-other-login-icon"> |
| | | <svg-icon icon-class="github" /> |
| | | </div> |
| | |
| | | </template> |
| | | |
| | | <script lang="ts" setup> |
| | | import { authUnlock, authBinding } from "@/api/system/social/auth"; |
| | | import { PropType } from "vue"; |
| | | import { authUnlock, authBinding } from '@/api/system/social/auth'; |
| | | import { PropType } from 'vue'; |
| | | |
| | | const { proxy } = getCurrentInstance() as ComponentInternalInstance; |
| | | |
| | | const props = defineProps({ |
| | | auths: { |
| | | type: Object as PropType<any>, |
| | | type: Object as PropType<any> |
| | | } |
| | | }); |
| | | const auths = computed(() => props.auths); |
| | | |
| | | |
| | | const unlockAuth = (row: any) => { |
| | | ElMessageBox.confirm('æ¨ç¡®å®è¦è§£é¤"' + row.source + '"çè´¦å·ç»å®åï¼') |
| | | .then(() => { |
| | | return authUnlock(row.id); |
| | | }).then((res: any) => { |
| | | }) |
| | | .then((res: any) => { |
| | | if (res.code === 200) { |
| | | proxy?.$modal.msgSuccess("è§£ç»æå"); |
| | | proxy?.$modal.msgSuccess('è§£ç»æå'); |
| | | proxy?.$tab.refreshPage(); |
| | | } else { |
| | | proxy?.$modal.msgError(res.msg); |
| | | } |
| | | }).catch(() => { }); |
| | | }) |
| | | .catch(() => {}); |
| | | }; |
| | | |
| | | const authUrl = (source: string) => { |
| | |
| | | margin-top: 10px; |
| | | } |
| | | |
| | | .git-other-login-icon>img { |
| | | .git-other-login-icon > img { |
| | | height: 32px; |
| | | } |
| | | |
| | |
| | | } |
| | | |
| | | .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, "WenQuanYi Zen Hei Sharp", |
| | | sans-serif; |
| | | 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; |
| | | } |
| | | |
| | | td>img { |
| | | td > img { |
| | | height: 20px; |
| | | width: 20px; |
| | | display: inline-block; |
| | |
| | | <el-row> |
| | | <el-col :xs="24" :md="12" :style="{ height: '350px' }"> |
| | | <vue-cropper |
| | | v-if="visible" |
| | | ref="cropper" |
| | | :img="options.img" |
| | | :info="true" |
| | | :autoCrop="options.autoCrop" |
| | | :autoCropWidth="options.autoCropWidth" |
| | | :autoCropHeight="options.autoCropHeight" |
| | | :fixedBox="options.fixedBox" |
| | | :outputType="options.outputType" |
| | | @realTime="realTime" |
| | | v-if="visible" |
| | | :auto-crop="options.autoCrop" |
| | | :auto-crop-width="options.autoCropWidth" |
| | | :auto-crop-height="options.autoCropHeight" |
| | | :fixed-box="options.fixedBox" |
| | | :output-type="options.outputType" |
| | | @real-time="realTime" |
| | | /> |
| | | </el-col> |
| | | <el-col :xs="24" :md="12" :style="{ height: '350px' }"> |
| | |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import "vue-cropper/dist/index.css"; |
| | | import { VueCropper } from "vue-cropper"; |
| | | import { uploadAvatar } from "@/api/system/user"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | import 'vue-cropper/dist/index.css'; |
| | | import { VueCropper } from 'vue-cropper'; |
| | | import { uploadAvatar } from '@/api/system/user'; |
| | | import useUserStore from '@/store/modules/user'; |
| | | |
| | | interface Options { |
| | | img: string | any; // è£åªå¾ççå°å |
| | |
| | | visible: boolean; |
| | | } |
| | | |
| | | |
| | | const userStore = useUserStore(); |
| | | const { proxy } = getCurrentInstance() as ComponentInternalInstance; |
| | | |
| | | const open = ref(false); |
| | | const visible = ref(false); |
| | | const title = ref("ä¿®æ¹å¤´å"); |
| | | const title = ref('ä¿®æ¹å¤´å'); |
| | | |
| | | const cropper = ref<any>({}); |
| | | //å¾çè£åªæ°æ® |
| | |
| | | autoCropWidth: 200, |
| | | autoCropHeight: 200, |
| | | fixedBox: true, |
| | | outputType: "png", |
| | | fileName: "", |
| | | outputType: 'png', |
| | | fileName: '', |
| | | previews: {}, |
| | | visible: false |
| | | }); |
| | |
| | | visible.value = true; |
| | | }; |
| | | /** è¦çé»è®¤ä¸ä¼ è¡ä¸º */ |
| | | const requestUpload = (): any => { |
| | | }; |
| | | const requestUpload = (): any => {}; |
| | | /** åå·¦æè½¬ */ |
| | | const rotateLeft = () => { |
| | | cropper.value.rotateLeft(); |
| | |
| | | }; |
| | | /** ä¸ä¼ é¢å¤ç */ |
| | | const beforeUpload = (file: any) => { |
| | | if (file.type.indexOf("image/") == -1) { |
| | | proxy?.$modal.msgError("æä»¶æ ¼å¼é误ï¼è¯·ä¸ä¼ å¾çç±»å,å¦ï¼JPGï¼PNGåç¼çæä»¶ã"); |
| | | if (file.type.indexOf('image/') == -1) { |
| | | proxy?.$modal.msgError('æä»¶æ ¼å¼é误ï¼è¯·ä¸ä¼ å¾çç±»å,å¦ï¼JPGï¼PNGåç¼çæä»¶ã'); |
| | | } else { |
| | | const reader = new FileReader(); |
| | | reader.readAsDataURL(file); |
| | |
| | | const uploadImg = async () => { |
| | | cropper.value.getCropBlob(async (data: any) => { |
| | | let formData = new FormData(); |
| | | formData.append("avatarfile", data, options.fileName); |
| | | formData.append('avatarfile', data, options.fileName); |
| | | const res = await uploadAvatar(formData); |
| | | open.value = false; |
| | | options.img = res.data.imgUrl; |
| | |
| | | } |
| | | |
| | | .user-info-head:hover:after { |
| | | content: "+"; |
| | | content: '+'; |
| | | position: absolute; |
| | | left: 0; |
| | | right: 0; |
| | |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import { updateUserProfile } from "@/api/system/user"; |
| | | import { updateUserProfile } from '@/api/system/user'; |
| | | |
| | | const props = defineProps({ |
| | | user: { |
| | |
| | | const { proxy } = getCurrentInstance() as ComponentInternalInstance; |
| | | const userRef = ref<ElFormInstance>(); |
| | | const rules = ref<ElFormRules>({ |
| | | nickName: [{ required: true, message: "ç¨æ·æµç§°ä¸è½ä¸ºç©º", trigger: "blur" }], |
| | | email: [{ required: true, message: "é®ç®±å°åä¸è½ä¸ºç©º", trigger: "blur" }, { |
| | | type: "email", |
| | | message: "请è¾å
¥æ£ç¡®çé®ç®±å°å", |
| | | trigger: ["blur", "change"] |
| | | }], |
| | | phonenumber: [{ |
| | | required: true, |
| | | message: "ææºå·ç ä¸è½ä¸ºç©º", |
| | | trigger: "blur" |
| | | }, { pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/, message: "请è¾å
¥æ£ç¡®çææºå·ç ", trigger: "blur" }] |
| | | nickName: [{ required: true, message: 'ç¨æ·æµç§°ä¸è½ä¸ºç©º', trigger: 'blur' }], |
| | | email: [ |
| | | { required: true, message: 'é®ç®±å°åä¸è½ä¸ºç©º', trigger: 'blur' }, |
| | | { |
| | | type: 'email', |
| | | message: '请è¾å
¥æ£ç¡®çé®ç®±å°å', |
| | | trigger: ['blur', 'change'] |
| | | } |
| | | ], |
| | | phonenumber: [ |
| | | { |
| | | required: true, |
| | | message: 'ææºå·ç ä¸è½ä¸ºç©º', |
| | | trigger: 'blur' |
| | | }, |
| | | { pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/, message: '请è¾å
¥æ£ç¡®çææºå·ç ', trigger: 'blur' } |
| | | ] |
| | | }); |
| | | |
| | | |
| | | /** æäº¤æé® */ |
| | | const submit = () => { |
| | | userRef.value?.validate(async (valid: boolean) => { |
| | | if (valid) { |
| | | await updateUserProfile(props.user); |
| | | proxy?.$modal.msgSuccess("ä¿®æ¹æå"); |
| | | proxy?.$modal.msgSuccess('ä¿®æ¹æå'); |
| | | } |
| | | }); |
| | | }; |
| | |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <el-form-item label="表åç§°" prop="tableName"> |
| | | <el-input placeholder="请è¾å
¥ä»åºåç§°" v-model="infoForm.tableName" /> |
| | | <el-input v-model="infoForm.tableName" placeholder="请è¾å
¥ä»åºåç§°" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="表æè¿°" prop="tableComment"> |
| | | <el-input placeholder="请è¾å
¥" v-model="infoForm.tableComment" /> |
| | | <el-input v-model="infoForm.tableComment" placeholder="请è¾å
¥" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å®ä½ç±»åç§°" prop="className"> |
| | | <el-input placeholder="请è¾å
¥" v-model="infoForm.className" /> |
| | | <el-input v-model="infoForm.className" placeholder="请è¾å
¥" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ä½è
" prop="functionAuthor"> |
| | | <el-input placeholder="请è¾å
¥" v-model="infoForm.functionAuthor" /> |
| | | <el-input v-model="infoForm.functionAuthor" placeholder="请è¾å
¥" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="24"> |
| | | <el-form-item label="夿³¨" prop="remark"> |
| | | <el-input type="textarea" :rows="3" v-model="infoForm.remark"></el-input> |
| | | <el-input v-model="infoForm.remark" type="textarea" :rows="3"></el-input> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import { propTypes } from "@/utils/propTypes"; |
| | | import { propTypes } from '@/utils/propTypes'; |
| | | |
| | | const prop = defineProps({ |
| | | info: propTypes.any.def({}) |
| | | }); |
| | | |
| | | const infoForm = computed(() => prop.info) |
| | | const infoForm = computed(() => prop.info); |
| | | |
| | | // è¡¨åæ ¡éª |
| | | const rules = ref({ |
| | | tableName: [{ required: true, message: "请è¾å
¥è¡¨åç§°", trigger: "blur" }], |
| | | tableComment: [{ required: true, message: "请è¾å
¥è¡¨æè¿°", trigger: "blur" }], |
| | | className: [{ required: true, message: "请è¾å
¥å®ä½ç±»åç§°", trigger: "blur" }], |
| | | functionAuthor: [{ required: true, message: "请è¾å
¥ä½è
", trigger: "blur" }] |
| | | tableName: [{ required: true, message: '请è¾å
¥è¡¨åç§°', trigger: 'blur' }], |
| | | tableComment: [{ required: true, message: '请è¾å
¥è¡¨æè¿°', trigger: 'blur' }], |
| | | className: [{ required: true, message: '请è¾å
¥å®ä½ç±»åç§°', trigger: 'blur' }], |
| | | functionAuthor: [{ required: true, message: '请è¾å
¥ä½è
', trigger: 'blur' }] |
| | | }); |
| | | </script> |
| | |
| | | |
| | | <el-table-column label="æå
¥" min-width="5%"> |
| | | <template #default="scope"> |
| | | <el-checkbox true-label="1" false-label="0" v-model="scope.row.isInsert"></el-checkbox> |
| | | <el-checkbox v-model="scope.row.isInsert" true-label="1" false-label="0"></el-checkbox> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="ç¼è¾" min-width="5%"> |
| | | <template #default="scope"> |
| | | <el-checkbox true-label="1" false-label="0" v-model="scope.row.isEdit"></el-checkbox> |
| | | <el-checkbox v-model="scope.row.isEdit" true-label="1" false-label="0"></el-checkbox> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="å表" min-width="5%"> |
| | | <template #default="scope"> |
| | | <el-checkbox true-label="1" false-label="0" v-model="scope.row.isList"></el-checkbox> |
| | | <el-checkbox v-model="scope.row.isList" true-label="1" false-label="0"></el-checkbox> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="æ¥è¯¢" min-width="5%"> |
| | | <template #default="scope"> |
| | | <el-checkbox true-label="1" false-label="0" v-model="scope.row.isQuery"></el-checkbox> |
| | | <el-checkbox v-model="scope.row.isQuery" true-label="1" false-label="0"></el-checkbox> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="æ¥è¯¢æ¹å¼" min-width="10%"> |
| | |
| | | </el-table-column> |
| | | <el-table-column label="å¿
å¡«" min-width="5%"> |
| | | <template #default="scope"> |
| | | <el-checkbox true-label="1" false-label="0" v-model="scope.row.isRequired"></el-checkbox> |
| | | <el-checkbox v-model="scope.row.isRequired" true-label="1" false-label="0"></el-checkbox> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="æ¾ç¤ºç±»å" min-width="12%"> |
| | |
| | | </el-tab-pane> |
| | | </el-tabs> |
| | | <el-form label-width="100px"> |
| | | <div style="text-align: center;margin-left:-100px;margin-top:10px;"> |
| | | <div style="text-align: center; margin-left: -100px; margin-top: 10px"> |
| | | <el-button type="primary" @click="submitForm()">æäº¤</el-button> |
| | | <el-button @click="close()">è¿å</el-button> |
| | | </div> |
| | |
| | | import { optionselect as getDictOptionselect } from '@/api/system/dict/type'; |
| | | import { DictTypeVO } from '@/api/system/dict/type/types'; |
| | | import BasicInfoForm from './basicInfoForm.vue'; |
| | | import GenInfoForm from "./genInfoForm.vue"; |
| | | import GenInfoForm from './genInfoForm.vue'; |
| | | |
| | | const route = useRoute(); |
| | | const { proxy } = getCurrentInstance() as ComponentInternalInstance; |
| | |
| | | const basicForm = basicInfo.value?.$refs.basicInfoForm; |
| | | const genForm = genInfo.value?.$refs.genInfoForm; |
| | | |
| | | Promise.all([basicForm, genForm].map(getFormPromise)).then(async res => { |
| | | const validateResult = res.every(item => !!item); |
| | | Promise.all([basicForm, genForm].map(getFormPromise)).then(async (res) => { |
| | | const validateResult = res.every((item) => !!item); |
| | | if (validateResult) { |
| | | const genTable: any = Object.assign({}, info.value); |
| | | genTable.columns = columns.value; |
| | |
| | | close(); |
| | | } |
| | | } else { |
| | | proxy?.$modal.msgError("è¡¨åæ ¡éªæªéè¿ï¼è¯·éæ°æ£æ¥æäº¤å
容"); |
| | | proxy?.$modal.msgError('è¡¨åæ ¡éªæªéè¿ï¼è¯·éæ°æ£æ¥æäº¤å
容'); |
| | | } |
| | | }); |
| | | } |
| | | }; |
| | | const getFormPromise = (form: any) => { |
| | | return new Promise(resolve => { |
| | | return new Promise((resolve) => { |
| | | form.validate((res: any) => { |
| | | resolve(res); |
| | | }); |
| | | }); |
| | | } |
| | | }; |
| | | const close = () => { |
| | | const obj = { path: "/tool/gen", query: { t: Date.now(), pageNum: route.query.pageNum } }; |
| | | const obj = { path: '/tool/gen', query: { t: Date.now(), pageNum: route.query.pageNum } }; |
| | | proxy?.$tab.closeOpenPage(obj); |
| | | } |
| | | }; |
| | | |
| | | (async () => { |
| | | const tableId = route.params && route.params.tableId as string; |
| | | const tableId = route.params && (route.params.tableId as string); |
| | | if (tableId) { |
| | | // è·å表详ç»ä¿¡æ¯ |
| | | const res = await getGenTable(tableId); |
| | |
| | | </el-form-item> |
| | | </el-col> |
| | | |
| | | <el-col :span="24" v-if="infoForm.genType == '1'"> |
| | | <el-col v-if="infoForm.genType == '1'" :span="24"> |
| | | <el-form-item prop="genPath"> |
| | | <template #label> |
| | | èªå®ä¹è·¯å¾ |
| | |
| | | |
| | | <script setup lang="ts"> |
| | | import { listMenu } from '@/api/system/menu'; |
| | | import { propTypes } from "@/utils/propTypes"; |
| | | import { propTypes } from '@/utils/propTypes'; |
| | | |
| | | interface MenuOptionsType { |
| | | menuId: number | string; |
| | |
| | | |
| | | // è¡¨åæ ¡éª |
| | | const rules = ref({ |
| | | tplCategory: [{ required: true, message: "è¯·éæ©çææ¨¡æ¿", trigger: "blur" }], |
| | | packageName: [{ required: true, message: "请è¾å
¥çæå
è·¯å¾", trigger: "blur" }], |
| | | moduleName: [{ required: true, message: "请è¾å
¥çææ¨¡åå", trigger: "blur" }], |
| | | businessName: [{ required: true, message: "请è¾å
¥çæä¸å¡å", trigger: "blur" }], |
| | | functionName: [{ required: true, message: "请è¾å
¥çæåè½å", trigger: "blur" }] |
| | | tplCategory: [{ required: true, message: 'è¯·éæ©çææ¨¡æ¿', trigger: 'blur' }], |
| | | packageName: [{ required: true, message: '请è¾å
¥çæå
è·¯å¾', trigger: 'blur' }], |
| | | moduleName: [{ required: true, message: '请è¾å
¥çææ¨¡åå', trigger: 'blur' }], |
| | | businessName: [{ required: true, message: '请è¾å
¥çæä¸å¡å', trigger: 'blur' }], |
| | | functionName: [{ required: true, message: '请è¾å
¥çæåè½å', trigger: 'blur' }] |
| | | }); |
| | | const subSelectChange = () => { |
| | | infoForm.value.subTableFkName = ""; |
| | | } |
| | | infoForm.value.subTableFkName = ''; |
| | | }; |
| | | const tplSelectChange = (value: string) => { |
| | | if (value !== "sub") { |
| | | infoForm.value.subTableName = ""; |
| | | infoForm.value.subTableFkName = ""; |
| | | if (value !== 'sub') { |
| | | infoForm.value.subTableName = ''; |
| | | infoForm.value.subTableFkName = ''; |
| | | } |
| | | } |
| | | }; |
| | | const setSubTableColumns = (value: string) => { |
| | | table.value.forEach((item: any) => { |
| | | const name = item.tableName; |
| | |
| | | subColumns.value = item.columns; |
| | | return; |
| | | } |
| | | }) |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | /** æ¥è¯¢èå䏿æ ç»æ */ |
| | | const getMenuTreeselect = async () => { |
| | | const res = await listMenu(); |
| | | res.data.forEach(m => m.menuId = m.menuId.toString()); |
| | | const data = proxy?.handleTree<MenuOptionsType>(res.data, "menuId"); |
| | | res.data.forEach((m) => (m.menuId = m.menuId.toString())); |
| | | const data = proxy?.handleTree<MenuOptionsType>(res.data, 'menuId'); |
| | | if (data) { |
| | | menuOptions.value = data |
| | | menuOptions.value = data; |
| | | } |
| | | } |
| | | }; |
| | | |
| | | watch(() => props.info.subTableName, val => { |
| | | setSubTableColumns(val); |
| | | }); |
| | | watch( |
| | | () => props.info.subTableName, |
| | | (val) => { |
| | | setSubTableColumns(val); |
| | | } |
| | | ); |
| | | |
| | | onMounted(() => { |
| | | getMenuTreeselect(); |
| | | }) |
| | | }); |
| | | </script> |
| | |
| | | <template> |
| | | <!-- 导å
¥è¡¨ --> |
| | | <el-dialog title="导å
¥è¡¨" v-model="visible" width="1100px" top="5vh" append-to-body> |
| | | <el-form :model="queryParams" ref="queryFormRef" :inline="true"> |
| | | <el-dialog v-model="visible" title="导å
¥è¡¨" width="1100px" top="5vh" append-to-body> |
| | | <el-form ref="queryFormRef" :model="queryParams" :inline="true"> |
| | | <el-form-item label="æ°æ®æº" prop="dataName"> |
| | | <el-select v-model="queryParams.dataName" filterable placeholder="è¯·éæ©/è¾å
¥æ°æ®æºåç§°" style="width: 200px"> |
| | | <el-option v-for="item in dataNameList" :key="item" :label="item" :value="item"> </el-option> |
| | |
| | | </el-form-item> |
| | | </el-form> |
| | | <el-row> |
| | | <el-table @row-click="clickRow" ref="tableRef" :data="dbTableList" @selection-change="handleSelectionChange" height="260px"> |
| | | <el-table ref="tableRef" :data="dbTableList" height="260px" @row-click="clickRow" @selection-change="handleSelectionChange"> |
| | | <el-table-column type="selection" width="55"></el-table-column> |
| | | <el-table-column prop="tableName" label="表åç§°" :show-overflow-tooltip="true"></el-table-column> |
| | | <el-table-column prop="tableComment" label="表æè¿°" :show-overflow-tooltip="true"></el-table-column> |
| | | <el-table-column prop="createTime" label="å建æ¶é´"></el-table-column> |
| | | <el-table-column prop="updateTime" label="æ´æ°æ¶é´"></el-table-column> |
| | | </el-table> |
| | | <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" /> |
| | | <pagination v-show="total > 0" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" :total="total" @pagination="getList" /> |
| | | </el-row> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | |
| | | }); |
| | | const dataNameList = ref<Array<string>>([]); |
| | | |
| | | const emit = defineEmits(["ok"]); |
| | | const emit = defineEmits(['ok']); |
| | | |
| | | /** æ¥è¯¢åæ°å表 */ |
| | | const show = (dataName: string) => { |
| | |
| | | } |
| | | getList(); |
| | | visible.value = true; |
| | | } |
| | | }; |
| | | /** åå»éæ©è¡ */ |
| | | const clickRow = (row: DbTableVO) => { |
| | | // ele bug |
| | | tableRef.value?.toggleRowSelection(row, false); |
| | | } |
| | | }; |
| | | /** å¤éæ¡é䏿°æ® */ |
| | | const handleSelectionChange = (selection: DbTableVO[]) => { |
| | | tables.value = selection.map(item => item.tableName); |
| | | } |
| | | tables.value = selection.map((item) => item.tableName); |
| | | }; |
| | | /** æ¥è¯¢è¡¨æ°æ® */ |
| | | const getList = async () => { |
| | | const res = await listDbTable(queryParams); |
| | | dbTableList.value = res.rows; |
| | | total.value = res.total; |
| | | } |
| | | }; |
| | | /** æç´¢æé®æä½ */ |
| | | const handleQuery = () => { |
| | | queryParams.pageNum = 1; |
| | | getList(); |
| | | } |
| | | }; |
| | | /** éç½®æé®æä½ */ |
| | | const resetQuery = () => { |
| | | queryFormRef.value?.resetFields(); |
| | | handleQuery(); |
| | | } |
| | | }; |
| | | /** 导å
¥æé®æä½ */ |
| | | const handleImportTable = async () => { |
| | | const tableNames = tables.value.join(","); |
| | | if (tableNames == "") { |
| | | proxy?.$modal.msgError("è¯·éæ©è¦å¯¼å
¥ç表"); |
| | | const tableNames = tables.value.join(','); |
| | | if (tableNames == '') { |
| | | proxy?.$modal.msgError('è¯·éæ©è¦å¯¼å
¥ç表'); |
| | | return; |
| | | } |
| | | const res = await importTable({ tables: tableNames, dataName: queryParams.dataName }); |
| | | proxy?.$modal.msgSuccess(res.msg); |
| | | if (res.code === 200) { |
| | | visible.value = false; |
| | | emit("ok"); |
| | | emit('ok'); |
| | | } |
| | | } |
| | | }; |
| | | /** æ¥è¯¢å¤æ°æ®æºåç§° */ |
| | | const getDataNameList = async () => { |
| | | const res = await getDataNames() |
| | | const res = await getDataNames(); |
| | | dataNameList.value = res.data; |
| | | } |
| | | }; |
| | | |
| | | defineExpose({ |
| | | show, |
| | | show |
| | | }); |
| | | </script> |
| | |
| | | <template> |
| | | <div class="p-2"> |
| | | <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave"> |
| | | <div class="mb-[10px]" v-show="showSearch"> |
| | | <div v-show="showSearch" class="mb-[10px]"> |
| | | <el-card shadow="hover"> |
| | | <el-form :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px"> |
| | | <el-form ref="queryFormRef" :model="queryParams" :inline="true" label-width="68px"> |
| | | <el-form-item label="æ°æ®æº" prop="dataName"> |
| | | <el-select v-model="queryParams.dataName" filterable clearable placeholder="è¯·éæ©/è¾å
¥æ°æ®æºåç§°" style="width: 200px"> |
| | | <el-option key="" label="å
¨é¨" value="" /> |
| | |
| | | <template #header> |
| | | <el-row :gutter="10" class="mb8"> |
| | | <el-col :span="1.5"> |
| | | <el-button type="primary" plain icon="Download" @click="handleGenTable()" v-hasPermi="['tool:gen:code']">çæ</el-button> |
| | | <el-button v-hasPermi="['tool:gen:code']" type="primary" plain icon="Download" @click="handleGenTable()">çæ</el-button> |
| | | </el-col> |
| | | <el-col :span="1.5"> |
| | | <el-button type="info" plain icon="Upload" @click="openImportTable" v-hasPermi="['tool:gen:import']">导å
¥</el-button> |
| | | <el-button v-hasPermi="['tool:gen:import']" type="info" plain icon="Upload" @click="openImportTable">导å
¥</el-button> |
| | | </el-col> |
| | | <el-col :span="1.5"> |
| | | <el-button type="success" plain icon="Edit" :disabled="single" @click="handleEditTable()" v-hasPermi="['tool:gen:edit']">ä¿®æ¹</el-button> |
| | | <el-button v-hasPermi="['tool:gen:edit']" type="success" plain icon="Edit" :disabled="single" @click="handleEditTable()">ä¿®æ¹</el-button> |
| | | </el-col> |
| | | <el-col :span="1.5"> |
| | | <el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['tool:gen:remove']"> |
| | | <el-button v-hasPermi="['tool:gen:remove']" type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()"> |
| | | å é¤ |
| | | </el-button> |
| | | </el-col> |
| | | <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar> |
| | | <right-toolbar v-model:showSearch="showSearch" @query-table="getList"></right-toolbar> |
| | | </el-row> |
| | | </template> |
| | | |
| | |
| | | <el-table-column label="æä½" align="center" width="330" class-name="small-padding fixed-width"> |
| | | <template #default="scope"> |
| | | <el-tooltip content="é¢è§" placement="top"> |
| | | <el-button link type="primary" icon="View" @click="handlePreview(scope.row)" v-hasPermi="['tool:gen:preview']"></el-button> |
| | | <el-button v-hasPermi="['tool:gen:preview']" link type="primary" icon="View" @click="handlePreview(scope.row)"></el-button> |
| | | </el-tooltip> |
| | | <el-tooltip content="ç¼è¾" placement="top"> |
| | | <el-button link type="primary" icon="Edit" @click="handleEditTable(scope.row)" v-hasPermi="['tool:gen:edit']"></el-button> |
| | | <el-button v-hasPermi="['tool:gen:edit']" link type="primary" icon="Edit" @click="handleEditTable(scope.row)"></el-button> |
| | | </el-tooltip> |
| | | <el-tooltip content="å é¤" placement="top"> |
| | | <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['tool:gen:remove']"></el-button> |
| | | <el-button v-hasPermi="['tool:gen:remove']" link type="primary" icon="Delete" @click="handleDelete(scope.row)"></el-button> |
| | | </el-tooltip> |
| | | <el-tooltip content="忥" placement="top"> |
| | | <el-button link type="primary" icon="Refresh" @click="handleSynchDb(scope.row)" v-hasPermi="['tool:gen:edit']"></el-button> |
| | | <el-button v-hasPermi="['tool:gen:edit']" link type="primary" icon="Refresh" @click="handleSynchDb(scope.row)"></el-button> |
| | | </el-tooltip> |
| | | <el-tooltip content="çæä»£ç " placement="top"> |
| | | <el-button link type="primary" icon="Download" @click="handleGenTable(scope.row)" v-hasPermi="['tool:gen:code']"></el-button> |
| | | <el-button v-hasPermi="['tool:gen:code']" link type="primary" icon="Download" @click="handleGenTable(scope.row)"></el-button> |
| | | </el-tooltip> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" /> |
| | | <pagination v-show="total > 0" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" :total="total" @pagination="getList" /> |
| | | </el-card> |
| | | |
| | | <!-- é¢è§çé¢ --> |
| | | <el-dialog :title="dialog.title" v-model="dialog.visible" width="80%" top="5vh" append-to-body class="scrollbar"> |
| | | <el-dialog v-model="dialog.visible" :title="dialog.title" width="80%" top="5vh" append-to-body class="scrollbar"> |
| | | <el-tabs v-model="preview.activeName"> |
| | | <el-tab-pane |
| | | v-for="(value, key) in preview.data" |
| | |
| | | :name="key.substring(key.lastIndexOf('/') + 1, key.indexOf('.vm'))" |
| | | :key="value" |
| | | > |
| | | <el-link :underline="false" icon="DocumentCopy" v-copyText="value" v-copyText:callback="copyTextSuccess" style="float:right"> |
| | | <el-link v-copyText="value" v-copyText:callback="copyTextSuccess" :underline="false" icon="DocumentCopy" style="float: right"> |
| | | å¤å¶ |
| | | </el-link> |
| | | <pre>{{ value }}</pre> |
| | |
| | | const multiple = ref(true); |
| | | const total = ref(0); |
| | | const dateRange = ref<[DateModelType, DateModelType]>(['', '']); |
| | | const uniqueId = ref(""); |
| | | const uniqueId = ref(''); |
| | | const dataNameList = ref<Array<string>>([]); |
| | | |
| | | const queryFormRef = ref<ElFormInstance>(); |
| | |
| | | pageSize: 10, |
| | | tableName: '', |
| | | tableComment: '', |
| | | dataName: "" |
| | | }) |
| | | dataName: '' |
| | | }); |
| | | |
| | | const preview = ref<any>({ |
| | | data: {}, |
| | | activeName: 'domain.java' |
| | | }) |
| | | }); |
| | | const dialog = reactive<DialogOption>({ |
| | | visible: false, |
| | | title: '代ç é¢è§' |
| | |
| | | queryFormRef.value?.resetFields(); |
| | | getList(); |
| | | } |
| | | }) |
| | | }); |
| | | |
| | | /** æ¥è¯¢å¤æ°æ®æºåç§° */ |
| | | const getDataNameList = async () => { |
| | | const res = await getDataNames() |
| | | const res = await getDataNames(); |
| | | dataNameList.value = res.data; |
| | | } |
| | | }; |
| | | |
| | | /** æ¥è¯¢è¡¨éå */ |
| | | const getList = async () => { |
| | |
| | | tableList.value = res.rows; |
| | | total.value = res.total; |
| | | loading.value = false; |
| | | } |
| | | }; |
| | | /** æç´¢æé®æä½ */ |
| | | const handleQuery = () => { |
| | | queryParams.value.pageNum = 1; |
| | | getList(); |
| | | } |
| | | }; |
| | | /** çæä»£ç æä½ */ |
| | | const handleGenTable = async (row?: TableVO) => { |
| | | const tbIds = row?.tableId || ids.value; |
| | | if (tbIds == "") { |
| | | if (tbIds == '') { |
| | | proxy?.$modal.msgError('è¯·éæ©è¦çæçæ°æ®'); |
| | | return; |
| | | } |
| | | if (row?.genType === "1") { |
| | | if (row?.genType === '1') { |
| | | await genCode(row.tableId); |
| | | proxy?.$modal.msgSuccess('æåçæå°èªå®ä¹è·¯å¾ï¼' + row.genPath); |
| | | } else { |
| | | proxy?.$download.zip('/tool/gen/batchGenCode?tableIdStr=' + tbIds, 'ruoyi.zip'); |
| | | } |
| | | } |
| | | }; |
| | | /** åæ¥æ°æ®åºæä½ */ |
| | | const handleSynchDb = async (row: TableVO) => { |
| | | const tableId = row.tableId; |
| | | await proxy?.$modal.confirm('确认è¦å¼ºå¶åæ¥"' + row.tableName + '"è¡¨ç»æåï¼'); |
| | | await synchDb(tableId); |
| | | proxy?.$modal.msgSuccess('忥æå'); |
| | | } |
| | | }; |
| | | /** æå¼å¯¼å
¥è¡¨å¼¹çª */ |
| | | const openImportTable = () => { |
| | | importRef.value?.show(queryParams.value.dataName); |
| | | } |
| | | }; |
| | | /** éç½®æé®æä½ */ |
| | | const resetQuery = () => { |
| | | dateRange.value = ['', '']; |
| | | queryFormRef.value?.resetFields(); |
| | | handleQuery(); |
| | | } |
| | | }; |
| | | /** é¢è§æé® */ |
| | | const handlePreview = async (row: TableVO) => { |
| | | const res = await previewTable(row.tableId); |
| | | preview.value.data = res.data; |
| | | dialog.visible = true; |
| | | preview.value.activeName = 'domain.java'; |
| | | } |
| | | }; |
| | | /** å¤å¶ä»£ç æå */ |
| | | const copyTextSuccess = () => { |
| | | proxy?.$modal.msgSuccess('å¤å¶æå'); |
| | | } |
| | | }; |
| | | // å¤éæ¡é䏿°æ® |
| | | const handleSelectionChange = (selection: TableVO[]) => { |
| | | ids.value = selection.map(item => item.tableId); |
| | | ids.value = selection.map((item) => item.tableId); |
| | | single.value = selection.length != 1; |
| | | multiple.value = !selection.length; |
| | | } |
| | | }; |
| | | /** ä¿®æ¹æé®æä½ */ |
| | | const handleEditTable = (row?: TableVO) => { |
| | | const tableId = row?.tableId || ids.value[0]; |
| | | router.push({ path: '/tool/gen-edit/index/' + tableId, query: { pageNum: queryParams.value.pageNum } }); |
| | | } |
| | | }; |
| | | /** å é¤æé®æä½ */ |
| | | const handleDelete = async (row?: TableVO) => { |
| | | const tableIds = row?.tableId || ids.value; |
| | |
| | | await delTable(tableIds); |
| | | await getList(); |
| | | proxy?.$modal.msgSuccess('å 餿å'); |
| | | } |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | getList(); |
| | | getDataNameList(); |
| | | }) |
| | | }); |
| | | </script> |
| | |
| | | { |
| | | "compilerOptions": { |
| | | "target": "es2022", |
| | | "useDefineForClassFields": true, |
| | | "target": "esnext", |
| | | "module": "esnext", |
| | | "useDefineForClassFields": true, |
| | | "moduleResolution": "node", |
| | | "strict": true, |
| | | "jsx": "preserve", |
| | |
| | | "allowSyntheticDefaultImports": true, |
| | | "forceConsistentCasingInFileNames": true |
| | | }, |
| | | "include": ["src/**/*.ts", "src/**/*.vue", "src/types/**/*.d.ts"], |
| | | "exclude": ["node_modules", "dist", "**/*.js"] |
| | | "include": ["src/**/*.ts", "src/**/*.vue", "src/types/**/*.d.ts", "vite.config.ts"], |
| | | "exclude": ["node_modules", "dist", "**/*.js", "**/*.md", "src/**/*.md"] |
| | | } |