From e9283ffe6822b12ec5dd2ccf4dc13a369b227a61 Mon Sep 17 00:00:00 2001
From: zhou zhou <3272660260@qq.com>
Date: 星期一, 30 三月 2026 08:32:06 +0800
Subject: [PATCH] chore: sync rsf-design from isolated worktree

---
 rsf-design/src/views/system/user/modules/user-dialog.vue |  355 +++++++++++++++++++++++++++++++++++++++++++++-------------
 1 files changed, 275 insertions(+), 80 deletions(-)

diff --git a/rsf-design/src/views/system/user/modules/user-dialog.vue b/rsf-design/src/views/system/user/modules/user-dialog.vue
index 706c5c3..72725a3 100644
--- a/rsf-design/src/views/system/user/modules/user-dialog.vue
+++ b/rsf-design/src/views/system/user/modules/user-dialog.vue
@@ -1,106 +1,301 @@
 <template>
   <ElDialog
-    v-model="dialogVisible"
-    :title="dialogType === 'add' ? '娣诲姞鐢ㄦ埛' : '缂栬緫鐢ㄦ埛'"
-    width="30%"
+    :title="dialogTitle"
+    :model-value="visible"
+    @update:model-value="handleCancel"
+    width="960px"
     align-center
+    class="user-dialog"
+    @closed="handleClosed"
   >
-    <ElForm ref="formRef" :model="formData" :rules="rules" label-width="80px">
-      <ElFormItem label="鐢ㄦ埛鍚�" prop="username">
-        <ElInput v-model="formData.username" placeholder="璇疯緭鍏ョ敤鎴峰悕" />
-      </ElFormItem>
-      <ElFormItem label="鎵嬫満鍙�" prop="phone">
-        <ElInput v-model="formData.phone" placeholder="璇疯緭鍏ユ墜鏈哄彿" />
-      </ElFormItem>
-      <ElFormItem label="鎬у埆" prop="gender">
-        <ElSelect v-model="formData.gender">
-          <ElOption label="鐢�" value="鐢�" />
-          <ElOption label="濂�" value="濂�" />
-        </ElSelect>
-      </ElFormItem>
-      <ElFormItem label="瑙掕壊" prop="role">
-        <ElSelect v-model="formData.role" multiple>
-          <ElOption
-            v-for="role in roleList"
-            :key="role.roleCode"
-            :value="role.roleCode"
-            :label="role.roleName"
-          />
-        </ElSelect>
-      </ElFormItem>
-    </ElForm>
+    <ArtForm
+      ref="formRef"
+      v-model="form"
+      :items="formItems"
+      :rules="rules"
+      :span="12"
+      :gutter="20"
+      label-width="110px"
+      :show-reset="false"
+      :show-submit="false"
+    />
+
     <template #footer>
-      <div class="dialog-footer">
-        <ElButton @click="dialogVisible = false">鍙栨秷</ElButton>
-        <ElButton type="primary" @click="handleSubmit">鎻愪氦</ElButton>
-      </div>
+      <span class="dialog-footer">
+        <ElButton @click="handleCancel">鍙栨秷</ElButton>
+        <ElButton type="primary" @click="handleSubmit">纭畾</ElButton>
+      </span>
     </template>
   </ElDialog>
 </template>
 
 <script setup>
-  import { ROLE_LIST_DATA } from '@/mock/temp/formData'
+  import ArtForm from '@/components/core/forms/art-form/index.vue'
+  import { buildUserDialogModel, createUserFormState } from '../userPage.helpers'
+
   const props = defineProps({
-    visible: { required: true },
-    type: { required: true },
-    userData: { required: false }
+    visible: { required: false, default: false },
+    type: { required: false, default: 'add' },
+    userData: { required: false, default: () => ({}) },
+    roleOptions: { required: false, default: () => [] },
+    deptTreeOptions: { required: false, default: () => [] }
   })
+
   const emit = defineEmits(['update:visible', 'submit'])
-  const roleList = ref(ROLE_LIST_DATA)
-  const dialogVisible = computed({
-    get: () => props.visible,
-    set: (value) => emit('update:visible', value)
-  })
-  const dialogType = computed(() => props.type)
   const formRef = ref()
-  const formData = reactive({
-    username: '',
-    phone: '',
-    gender: '鐢�',
-    role: []
-  })
-  const rules = {
-    username: [
-      { required: true, message: '璇疯緭鍏ョ敤鎴峰悕', trigger: 'blur' },
-      { min: 2, max: 20, message: '闀垮害鍦� 2 鍒� 20 涓瓧绗�', trigger: 'blur' }
-    ],
-    phone: [
-      { required: true, message: '璇疯緭鍏ユ墜鏈哄彿', trigger: 'blur' },
-      { pattern: /^1[3-9]\d{9}$/, message: '璇疯緭鍏ユ纭殑鎵嬫満鍙锋牸寮�', trigger: 'blur' }
-    ],
-    gender: [{ required: true, message: '璇烽�夋嫨鎬у埆', trigger: 'blur' }],
-    role: [{ required: true, message: '璇烽�夋嫨瑙掕壊', trigger: 'blur' }]
+  const form = reactive(createUserFormState())
+
+  const isEdit = computed(() => props.type === 'edit')
+  const dialogTitle = computed(() => (isEdit.value ? '缂栬緫鐢ㄦ埛' : '鏂板鐢ㄦ埛'))
+
+  const validatePassword = (_rule, value, callback) => {
+    if (!isEdit.value && !value) {
+      callback(new Error('璇疯緭鍏ュ瘑鐮�'))
+      return
+    }
+    if (value && String(value).length < 6) {
+      callback(new Error('瀵嗙爜闀垮害鑷冲皯 6 浣�'))
+      return
+    }
+    callback()
   }
-  const initFormData = () => {
-    const isEdit = props.type === 'edit' && props.userData
-    const row = props.userData
-    Object.assign(formData, {
-      username: isEdit && row ? row.userName || '' : '',
-      phone: isEdit && row ? row.userPhone || '' : '',
-      gender: isEdit && row ? row.userGender || '鐢�' : '鐢�',
-      role: isEdit && row ? (Array.isArray(row.userRoles) ? row.userRoles : []) : []
-    })
+
+  const validateConfirmPassword = (_rule, value, callback) => {
+    if (!form.password && !value && isEdit.value) {
+      callback()
+      return
+    }
+    if (!value) {
+      callback(new Error('璇峰啀娆¤緭鍏ュ瘑鐮�'))
+      return
+    }
+    if (value !== form.password) {
+      callback(new Error('涓ゆ杈撳叆鐨勫瘑鐮佷笉涓�鑷�'))
+      return
+    }
+    callback()
   }
+
+  const rules = computed(() => ({
+    username: [{ required: true, message: '璇疯緭鍏ョ敤鎴峰悕', trigger: 'blur' }],
+    nickname: [{ required: true, message: '璇疯緭鍏ユ樀绉�', trigger: 'blur' }],
+    roleIds: [{ type: 'array', required: true, message: '璇烽�夋嫨瑙掕壊', trigger: 'change' }],
+    password: [{ validator: validatePassword, trigger: 'blur' }],
+    confirmPassword: [{ validator: validateConfirmPassword, trigger: 'blur' }]
+  }))
+
+  const formItems = computed(() => [
+    {
+      label: '鐢ㄦ埛鍚�',
+      key: 'username',
+      type: 'input',
+      props: {
+        placeholder: '璇疯緭鍏ョ敤鎴峰悕',
+        clearable: true
+      }
+    },
+    {
+      label: '鏄电О',
+      key: 'nickname',
+      type: 'input',
+      props: {
+        placeholder: '璇疯緭鍏ユ樀绉�',
+        clearable: true
+      }
+    },
+    {
+      label: '閮ㄩ棬',
+      key: 'deptId',
+      type: 'treeselect',
+      props: {
+        data: props.deptTreeOptions,
+        props: {
+          label: 'label',
+          value: 'value',
+          children: 'children'
+        },
+        placeholder: '璇烽�夋嫨閮ㄩ棬',
+        clearable: true,
+        checkStrictly: true
+      }
+    },
+    {
+      label: '瑙掕壊',
+      key: 'roleIds',
+      type: 'select',
+      props: {
+        placeholder: '璇烽�夋嫨瑙掕壊',
+        clearable: true,
+        multiple: true,
+        collapseTags: true,
+        filterable: true,
+        options: props.roleOptions
+      }
+    },
+    {
+      label: '瀵嗙爜',
+      key: 'password',
+      type: 'input',
+      props: {
+        type: 'password',
+        showPassword: true,
+        placeholder: isEdit.value ? '涓嶄慨鏀瑰垯鐣欑┖' : '璇疯緭鍏ュ瘑鐮�',
+        clearable: true
+      }
+    },
+    {
+      label: '纭瀵嗙爜',
+      key: 'confirmPassword',
+      type: 'input',
+      props: {
+        type: 'password',
+        showPassword: true,
+        placeholder: '璇峰啀娆¤緭鍏ュ瘑鐮�',
+        clearable: true
+      }
+    },
+    {
+      label: '鎬у埆',
+      key: 'sex',
+      type: 'select',
+      props: {
+        placeholder: '璇烽�夋嫨鎬у埆',
+        clearable: true,
+        options: [
+          { label: '鏈煡', value: 0 },
+          { label: '鐢�', value: 1 },
+          { label: '濂�', value: 2 }
+        ]
+      }
+    },
+    {
+      label: '宸ュ彿',
+      key: 'code',
+      type: 'input',
+      props: {
+        placeholder: '璇疯緭鍏ュ伐鍙�',
+        clearable: true
+      }
+    },
+    {
+      label: '鎵嬫満鍙�',
+      key: 'phone',
+      type: 'input',
+      props: {
+        placeholder: '璇疯緭鍏ユ墜鏈哄彿',
+        clearable: true
+      }
+    },
+    {
+      label: '閭',
+      key: 'email',
+      type: 'input',
+      props: {
+        placeholder: '璇疯緭鍏ラ偖绠�',
+        clearable: true
+      }
+    },
+    {
+      label: '鐪熷疄濮撳悕',
+      key: 'realName',
+      type: 'input',
+      props: {
+        placeholder: '璇疯緭鍏ョ湡瀹炲鍚�',
+        clearable: true
+      }
+    },
+    {
+      label: '韬唤璇佸彿',
+      key: 'idCard',
+      type: 'input',
+      props: {
+        placeholder: '璇疯緭鍏ヨ韩浠借瘉鍙�',
+        clearable: true
+      }
+    },
+    {
+      label: '鐘舵��',
+      key: 'status',
+      type: 'select',
+      props: {
+        placeholder: '璇烽�夋嫨鐘舵��',
+        clearable: true,
+        options: [
+          { label: '姝e父', value: 1 },
+          { label: '绂佺敤', value: 0 }
+        ]
+      }
+    },
+    {
+      label: '澶囨敞',
+      key: 'memo',
+      type: 'input',
+      props: {
+        type: 'textarea',
+        rows: 3,
+        placeholder: '璇疯緭鍏ュ娉�',
+        clearable: true
+      },
+      span: 24
+    }
+  ])
+
+  const resetForm = () => {
+    Object.assign(form, createUserFormState())
+    formRef.value?.clearValidate?.()
+  }
+
+  const loadFormData = () => {
+    Object.assign(form, buildUserDialogModel(props.userData))
+  }
+
+  const handleSubmit = async () => {
+    if (!formRef.value) return
+    try {
+      await formRef.value.validate()
+      emit('submit', { ...form })
+    } catch {
+      return
+    }
+  }
+
+  const handleCancel = () => {
+    emit('update:visible', false)
+  }
+
+  const handleClosed = () => {
+    resetForm()
+  }
+
   watch(
-    () => [props.visible, props.type, props.userData],
-    ([visible]) => {
+    () => props.visible,
+    (visible) => {
       if (visible) {
-        initFormData()
+        loadFormData()
         nextTick(() => {
-          formRef.value?.clearValidate()
+          formRef.value?.clearValidate?.()
         })
       }
     },
     { immediate: true }
   )
-  const handleSubmit = async () => {
-    if (!formRef.value) return
-    await formRef.value.validate((valid) => {
-      if (valid) {
-        ElMessage.success(dialogType.value === 'add' ? '娣诲姞鎴愬姛' : '鏇存柊鎴愬姛')
-        dialogVisible.value = false
-        emit('submit')
+
+  watch(
+    () => props.userData,
+    () => {
+      if (props.visible) {
+        loadFormData()
       }
-    })
-  }
+    },
+    { deep: true }
+  )
+
+  watch(
+    () => props.type,
+    () => {
+      if (props.visible) {
+        loadFormData()
+      }
+    }
+  )
 </script>

--
Gitblit v1.9.1