From 40905cbd04c2e332cd4bc2b9e0c5b3e1da9cccfa Mon Sep 17 00:00:00 2001
From: zhou zhou <3272660260@qq.com>
Date: 星期一, 30 三月 2026 08:17:32 +0800
Subject: [PATCH] feat: complete rsf-design phase 1 integration
---
rsf-design/src/views/system/menu/modules/menu-dialog.vue | 412 +++++++++++++++++++++++++++++-----------------------------
1 files changed, 208 insertions(+), 204 deletions(-)
diff --git a/rsf-design/src/views/system/menu/modules/menu-dialog.vue b/rsf-design/src/views/system/menu/modules/menu-dialog.vue
index 7c928de..c2a5dc9 100644
--- a/rsf-design/src/views/system/menu/modules/menu-dialog.vue
+++ b/rsf-design/src/views/system/menu/modules/menu-dialog.vue
@@ -3,7 +3,7 @@
:title="dialogTitle"
:model-value="visible"
@update:model-value="handleCancel"
- width="860px"
+ width="760px"
align-center
class="menu-dialog"
@closed="handleClosed"
@@ -13,7 +13,7 @@
v-model="form"
:items="formItems"
:rules="rules"
- :span="width > 640 ? 12 : 24"
+ :span="24"
:gutter="20"
label-width="100px"
:show-reset="false"
@@ -21,16 +21,16 @@
>
<template #menuType>
<ElRadioGroup v-model="form.menuType" :disabled="disableMenuType">
- <ElRadioButton value="menu" label="menu">鑿滃崟</ElRadioButton>
- <ElRadioButton value="button" label="button">鎸夐挳</ElRadioButton>
+ <ElRadioButton value="menu">鑿滃崟</ElRadioButton>
+ <ElRadioButton value="button">鎸夐挳</ElRadioButton>
</ElRadioGroup>
</template>
</ArtForm>
<template #footer>
<span class="dialog-footer">
- <ElButton @click="handleCancel">鍙� 娑�</ElButton>
- <ElButton type="primary" @click="handleSubmit">纭� 瀹�</ElButton>
+ <ElButton @click="handleCancel">鍙栨秷</ElButton>
+ <ElButton type="primary" @click="handleSubmit">纭畾</ElButton>
</span>
</template>
</ElDialog>
@@ -39,248 +39,252 @@
<script setup>
import ArtForm from '@/components/core/forms/art-form/index.vue'
- import { ElIcon, ElTooltip } from 'element-plus'
- import { QuestionFilled } from '@element-plus/icons-vue'
- import { formatMenuTitle } from '@/utils/router'
- import { useWindowSize } from '@vueuse/core'
- const { width } = useWindowSize()
- const createLabelTooltip = (label, tooltip) => {
- return () =>
- h('span', { class: 'flex items-center' }, [
- h('span', label),
- h(
- ElTooltip,
- {
- content: tooltip,
- placement: 'top'
- },
- () => h(ElIcon, { class: 'ml-0.5 cursor-help' }, () => h(QuestionFilled))
- )
- ])
- }
+ const createMenuFormState = () => ({
+ menuType: 'menu',
+ id: null,
+ parentId: 0,
+ name: '',
+ route: '',
+ component: '',
+ authority: '',
+ icon: '',
+ sort: 0,
+ status: 1,
+ memo: ''
+ })
+
const props = defineProps({
visible: { required: false, default: false },
type: { required: false, default: 'menu' },
- lockType: { required: false, default: false }
+ lockType: { required: false, default: false },
+ editData: { required: false, default: null },
+ menuTreeOptions: { required: false, default: () => [] }
})
+
const emit = defineEmits(['update:visible', 'submit'])
const formRef = ref()
- const isEdit = ref(false)
- const form = reactive({
- menuType: 'menu',
- id: 0,
- name: '',
- path: '',
- label: '',
- component: '',
- icon: '',
- isEnable: true,
- sort: 1,
- isMenu: true,
- keepAlive: true,
- isHide: false,
- isHideTab: false,
- link: '',
- isIframe: false,
- showBadge: false,
- showTextBadge: '',
- fixedTab: false,
- activePath: '',
- roles: [],
- isFullPage: false,
- authName: '',
- authLabel: '',
- authIcon: '',
- authSort: 1
- })
- const rules = reactive({
- name: [
- { required: true, message: '璇疯緭鍏ヨ彍鍗曞悕绉�', trigger: 'blur' },
- { min: 2, max: 20, message: '闀垮害鍦� 2 鍒� 20 涓瓧绗�', trigger: 'blur' }
- ],
- path: [{ required: true, message: '璇疯緭鍏ヨ矾鐢卞湴鍧�', trigger: 'blur' }],
- label: [{ required: true, message: '杈撳叆鏉冮檺鏍囪瘑', trigger: 'blur' }],
- authName: [{ required: true, message: '璇疯緭鍏ユ潈闄愬悕绉�', trigger: 'blur' }],
- authLabel: [{ required: true, message: '璇疯緭鍏ユ潈闄愭爣璇�', trigger: 'blur' }]
- })
+ const form = reactive(createMenuFormState())
+
+ const isEdit = computed(() => Boolean(form.id))
+ const dialogTitle = computed(() => `${isEdit.value ? '缂栬緫' : '鏂板缓'}${form.menuType === 'button' ? '鎸夐挳' : '鑿滃崟'}`)
+ const disableMenuType = computed(() => props.lockType || isEdit.value)
+
+ const rules = computed(() => ({
+ name: [{ required: true, message: form.menuType === 'button' ? '璇疯緭鍏ユ潈闄愬悕绉�' : '璇疯緭鍏ヨ彍鍗曞悕绉�', trigger: 'blur' }],
+ route:
+ form.menuType === 'menu'
+ ? [{ required: true, message: '璇疯緭鍏ヨ矾鐢卞湴鍧�', trigger: 'blur' }]
+ : [],
+ authority:
+ form.menuType === 'button'
+ ? [{ required: true, message: '璇疯緭鍏ユ潈闄愭爣璇�', trigger: 'blur' }]
+ : []
+ }))
+
const formItems = computed(() => {
- const baseItems = [{ label: '鑿滃崟绫诲瀷', key: 'menuType', span: 24 }]
- const switchSpan = width.value < 640 ? 12 : 6
+ const items = [
+ { label: '鑿滃崟绫诲瀷', key: 'menuType', span: 24 },
+ {
+ label: '涓婄骇鑿滃崟',
+ key: 'parentId',
+ type: 'treeselect',
+ span: 24,
+ props: {
+ data: props.menuTreeOptions,
+ props: {
+ label: 'label',
+ value: 'value',
+ children: 'children'
+ },
+ placeholder: '璇烽�夋嫨涓婄骇鑿滃崟',
+ checkStrictly: true,
+ clearable: false,
+ defaultExpandAll: true
+ }
+ },
+ {
+ label: form.menuType === 'button' ? '鏉冮檺鍚嶇О' : '鑿滃崟鍚嶇О',
+ key: 'name',
+ type: 'input',
+ span: 24,
+ props: {
+ placeholder: form.menuType === 'button' ? '璇疯緭鍏ユ潈闄愬悕绉�' : '璇疯緭鍏ヨ彍鍗曞悕绉�',
+ clearable: true
+ }
+ }
+ ]
+
if (form.menuType === 'menu') {
- return [
- ...baseItems,
- { label: '鑿滃崟鍚嶇О', key: 'name', type: 'input', props: { placeholder: '鑿滃崟鍚嶇О' } },
+ items.push(
{
- label: createLabelTooltip(
- '璺敱鍦板潃',
- '涓�绾ц彍鍗曪細浠� / 寮�澶寸殑缁濆璺緞锛堝 /dashboard锛塡n浜岀骇鍙婁互涓嬶細鐩稿璺緞锛堝 console銆乽ser锛�'
- ),
- key: 'path',
+ label: '璺敱鍦板潃',
+ key: 'route',
type: 'input',
- props: { placeholder: '濡傦細/dashboard 鎴� console' }
+ span: 24,
+ props: {
+ placeholder: '璇疯緭鍏ヨ矾鐢卞湴鍧�',
+ clearable: true
+ }
},
- { label: '鏉冮檺鏍囪瘑', key: 'label', type: 'input', props: { placeholder: '濡傦細User' } },
{
- label: createLabelTooltip(
- '缁勪欢璺緞',
- '涓�绾х埗绾ц彍鍗曪細濉啓 /index/index\n鍏蜂綋椤甸潰锛氬~鍐欑粍浠惰矾寰勶紙濡� /system/user锛塡n鐩綍鑿滃崟锛氱暀绌�'
- ),
+ label: '缁勪欢鏍囪瘑',
key: 'component',
type: 'input',
- props: { placeholder: '濡傦細/system/user 鎴栫暀绌�' }
- },
- { label: '鍥炬爣', key: 'icon', type: 'input', props: { placeholder: '濡傦細ri:user-line' } },
- {
- label: createLabelTooltip(
- '瑙掕壊鏉冮檺',
- '浠呯敤浜庡墠绔潈闄愭ā寮忥細閰嶇疆瑙掕壊鏍囪瘑锛堝 R_SUPER銆丷_ADMIN锛塡n鍚庣鏉冮檺妯″紡锛氭棤闇�閰嶇疆'
- ),
- key: 'roles',
- type: 'inputtag',
- props: { placeholder: '杈撳叆瑙掕壊鏍囪瘑鍚庢寜鍥炶溅锛屽锛歊_SUPER' }
- },
- {
- label: '鑿滃崟鎺掑簭',
- key: 'sort',
- type: 'number',
- props: { min: 1, controlsPosition: 'right', style: { width: '100%' } }
- },
- {
- label: '澶栭儴閾炬帴',
- key: 'link',
- type: 'input',
- props: { placeholder: '濡傦細https://www.example.com' }
- },
- {
- label: '鏂囨湰寰界珷',
- key: 'showTextBadge',
- type: 'input',
- props: { placeholder: '濡傦細New銆丠ot' }
- },
- {
- label: createLabelTooltip(
- '婵�娲昏矾寰�',
- '鐢ㄤ簬璇︽儏椤电瓑闅愯棌鑿滃崟锛屾寚瀹氶珮浜樉绀虹殑鐖剁骇鑿滃崟璺緞\n渚嬪锛氱敤鎴疯鎯呴〉楂樹寒鏄剧ず"鐢ㄦ埛绠$悊"鑿滃崟'
- ),
- key: 'activePath',
- type: 'input',
- props: { placeholder: '濡傦細/system/user' }
- },
- { label: '鏄惁鍚敤', key: 'isEnable', type: 'switch', span: switchSpan },
- { label: '椤甸潰缂撳瓨', key: 'keepAlive', type: 'switch', span: switchSpan },
- { label: '闅愯棌鑿滃崟', key: 'isHide', type: 'switch', span: switchSpan },
- { label: '鏄惁鍐呭祵', key: 'isIframe', type: 'switch', span: switchSpan },
- { label: '鏄剧ず寰界珷', key: 'showBadge', type: 'switch', span: switchSpan },
- { label: '鍥哄畾鏍囩', key: 'fixedTab', type: 'switch', span: switchSpan },
- { label: '鏍囩闅愯棌', key: 'isHideTab', type: 'switch', span: switchSpan },
- { label: '鍏ㄥ睆椤甸潰', key: 'isFullPage', type: 'switch', span: switchSpan }
- ]
- } else {
- return [
- ...baseItems,
- {
- label: '鏉冮檺鍚嶇О',
- key: 'authName',
- type: 'input',
- props: { placeholder: '濡傦細鏂板銆佺紪杈戙�佸垹闄�' }
- },
- {
- label: '鏉冮檺鏍囪瘑',
- key: 'authLabel',
- type: 'input',
- props: { placeholder: '濡傦細add銆乪dit銆乨elete' }
- },
- {
- label: '鏉冮檺鎺掑簭',
- key: 'authSort',
- type: 'number',
- props: { min: 1, controlsPosition: 'right', style: { width: '100%' } }
+ span: 24,
+ props: {
+ placeholder: '璇疯緭鍏ョ粍浠舵爣璇�',
+ clearable: true
+ }
}
- ]
+ )
}
+
+ items.push(
+ {
+ label: '鏉冮檺鏍囪瘑',
+ key: 'authority',
+ type: 'input',
+ span: 24,
+ props: {
+ placeholder: '璇疯緭鍏ユ潈闄愭爣璇�',
+ clearable: true
+ }
+ },
+ {
+ label: '鍥炬爣',
+ key: 'icon',
+ type: 'input',
+ span: 24,
+ props: {
+ placeholder: '璇疯緭鍏ュ浘鏍囧悕绉�',
+ clearable: true
+ }
+ },
+ {
+ label: '鎺掑簭',
+ key: 'sort',
+ type: 'number',
+ span: 24,
+ props: {
+ min: 0,
+ controlsPosition: 'right',
+ style: { width: '100%' }
+ }
+ },
+ {
+ label: '鐘舵��',
+ key: 'status',
+ type: 'select',
+ span: 24,
+ props: {
+ placeholder: '璇烽�夋嫨鐘舵��',
+ options: [
+ { label: '鍚敤', value: 1 },
+ { label: '绂佺敤', value: 0 }
+ ]
+ }
+ },
+ {
+ label: '澶囨敞',
+ key: 'memo',
+ type: 'input',
+ span: 24,
+ props: {
+ type: 'textarea',
+ rows: 3,
+ placeholder: '璇疯緭鍏ュ娉�',
+ clearable: true
+ }
+ }
+ )
+
+ return items
})
- const dialogTitle = computed(() => {
- const type = form.menuType === 'menu' ? '鑿滃崟' : '鎸夐挳'
- return isEdit.value ? `缂栬緫${type}` : `鏂板缓${type}`
- })
- const disableMenuType = computed(() => {
- if (isEdit.value) return true
- if (!isEdit.value && form.menuType === 'menu' && props.lockType) return true
- return false
- })
+
+ const normalizeNumber = (value, fallback = 0) => {
+ if (value === '' || value === null || value === undefined) {
+ return fallback
+ }
+ const normalized = Number(value)
+ return Number.isNaN(normalized) ? fallback : normalized
+ }
+
const resetForm = () => {
- formRef.value?.reset()
- form.menuType = 'menu'
+ Object.assign(form, createMenuFormState())
+ formRef.value?.clearValidate?.()
}
+
const loadFormData = () => {
- if (!props.editData) return
- isEdit.value = true
- if (form.menuType === 'menu') {
- const row = props.editData
- form.id = row.id || 0
- form.name = formatMenuTitle(row.meta?.title || '')
- form.path = row.path || ''
- form.label = row.name || ''
- form.component = row.component || ''
- form.icon = row.meta?.icon || ''
- form.sort = row.meta?.sort || 1
- form.isMenu = row.meta?.isMenu ?? true
- form.keepAlive = row.meta?.keepAlive ?? false
- form.isHide = row.meta?.isHide ?? false
- form.isHideTab = row.meta?.isHideTab ?? false
- form.isEnable = row.meta?.isEnable ?? true
- form.link = row.meta?.link || ''
- form.isIframe = row.meta?.isIframe ?? false
- form.showBadge = row.meta?.showBadge ?? false
- form.showTextBadge = row.meta?.showTextBadge || ''
- form.fixedTab = row.meta?.fixedTab ?? false
- form.activePath = row.meta?.activePath || ''
- form.roles = row.meta?.roles || []
- form.isFullPage = row.meta?.isFullPage ?? false
- } else {
- const row = props.editData
- form.authName = row.title || ''
- form.authLabel = row.authMark || ''
- form.authIcon = row.icon || ''
- form.authSort = row.sort || 1
+ resetForm()
+ form.menuType = props.type || 'menu'
+
+ const row = props.editData
+ if (!row || typeof row !== 'object') {
+ return
}
+
+ form.menuType = Number(row.type) === 1 ? 'button' : props.type || 'menu'
+ form.id = row.id ?? null
+ form.parentId = normalizeNumber(row.parentId, 0)
+ form.name = row.name || ''
+ form.route = row.route || ''
+ form.component = row.component || ''
+ form.authority = row.authority || row.meta?.authMark || ''
+ form.icon = row.icon || row.meta?.icon || ''
+ form.sort = normalizeNumber(row.sort ?? row.meta?.sort, 0)
+ form.status = normalizeNumber(row.status, row.meta?.isEnable === false ? 0 : 1)
+ form.memo = row.memo || ''
}
+
const handleSubmit = async () => {
if (!formRef.value) return
try {
await formRef.value.validate()
- emit('submit', { ...form })
- ElMessage.success(`${isEdit.value ? '缂栬緫' : '鏂板'}鎴愬姛`)
- handleCancel()
+ emit('submit', {
+ ...form,
+ type: form.menuType === 'button' ? 1 : 0
+ })
} catch {
- ElMessage.error('琛ㄥ崟鏍¢獙澶辫触锛岃妫�鏌ヨ緭鍏�')
+ return
}
}
+
const handleCancel = () => {
emit('update:visible', false)
}
+
const handleClosed = () => {
resetForm()
- isEdit.value = false
}
+
watch(
() => props.visible,
- (newVal) => {
- if (newVal) {
- form.menuType = props.type
+ (visible) => {
+ if (visible) {
+ loadFormData()
nextTick(() => {
- if (props.editData) {
- loadFormData()
- }
+ formRef.value?.clearValidate?.()
})
}
- }
+ },
+ { immediate: true }
)
+
+ watch(
+ () => props.editData,
+ () => {
+ if (props.visible) {
+ loadFormData()
+ }
+ },
+ { deep: true }
+ )
+
watch(
() => props.type,
- (newType) => {
+ () => {
if (props.visible) {
- form.menuType = newType
+ loadFormData()
}
}
)
--
Gitblit v1.9.1