Explorar el Código

简化用户角色选项逻辑,确保只有管理员可以设置和修改角色;优化用户表单,移除不必要的角色修改提示;调整用户列表和表单组件的代码格式,提高可读性。

wuyi hace 4 días
padre
commit
1da835f6ae
Se han modificado 1 ficheros con 33 adiciones y 120 borrados
  1. 33 120
      src/views/UserView.vue

+ 33 - 120
src/views/UserView.vue

@@ -73,32 +73,12 @@ const getRoleName = (role) => {
   return UserRole[role] || role
 }
 
-// 用户角色选项 - 根据当前用户角色限制
+// 用户角色选项 - 只有 ADMIN 可以看到,所以只返回所有角色
 const roleOptions = computed(() => {
-  // ADMIN 可以创建所有角色
-  if (isAdmin.value) {
-    return ['admin', 'manager', 'user'].map((role) => ({
-      value: role,
-      label: UserRole[role]
-    }))
-  }
-  
-  // MANAGER 在创建模式下只能创建 user 角色
-  // 在编辑模式下,显示所有角色(但禁用),以便查看当前角色
-  if (isEditMode.value) {
-    return ['admin', 'manager', 'user'].map((role) => ({
-      value: role,
-      label: UserRole[role]
-    }))
-  }
-  
-  // MANAGER 创建新用户时只能选择 user
-  return [
-    {
-      value: 'user',
-      label: UserRole.user
-    }
-  ]
+  return ['admin', 'manager', 'user'].map((role) => ({
+    value: role,
+    label: UserRole[role]
+  }))
 })
 
 // 用户表单相关
@@ -128,8 +108,8 @@ const userFormResolver = computed(() => {
       .refine((val) => !userForm.value.password || val === userForm.value.password, { message: '密码不一致' })
   }
 
-  // ADMIN 可以修改角色,MANAGER 不能修改角色
-  if (isAdmin.value || !isEditMode.value) {
+  // 只有 ADMIN 可以设置角色
+  if (isAdmin.value) {
     baseSchema.role = z.string().min(1, { message: '请选择角色' })
   }
 
@@ -170,11 +150,11 @@ const saveUser = async ({ valid, values }) => {
       name: values.name
     }
 
-    // 只有 ADMIN 可以设置/修改角色,或者创建新用户时可以设置角色
-    if (isAdmin.value || !isEditMode.value) {
+    // 只有 ADMIN 可以设置/修改角色
+    if (isAdmin.value) {
       submitData.role = values.role
     }
-    // MANAGER 在编辑模式下不能修改角色,不传 role 字段
+    // 非 ADMIN 用户不传 role 字段,后端会根据权限自动设置(MANAGER 创建的用户默认为 user)
 
     if (values.password) {
       submitData.password = values.password
@@ -241,27 +221,15 @@ onMounted(() => {
             <InputIcon>
               <i class="pi pi-hashtag" />
             </InputIcon>
-            <InputNumber
-              v-model="searchId"
-              placeholder="搜索ID"
-              :useGrouping="false"
-              fluid
-              size="small"
-              @keyup.enter="fetchData"
-            />
+            <InputNumber v-model="searchId" placeholder="搜索ID" :useGrouping="false" fluid size="small"
+              @keyup.enter="fetchData" />
           </IconField>
         </div>
 
         <!-- 搜索按钮 -->
         <Button icon="pi pi-search" @click="fetchData" label="搜索" size="small" />
-        <Button
-          v-if="search || searchId"
-          icon="pi pi-times"
-          @click="clearSearch"
-          label="清除"
-          severity="secondary"
-          size="small"
-        />
+        <Button v-if="search || searchId" icon="pi pi-times" @click="clearSearch" label="清除" severity="secondary"
+          size="small" />
 
         <!-- 左侧按钮组 -->
         <div class="flex items-center gap-2 flex-nowrap">
@@ -271,31 +239,18 @@ onMounted(() => {
 
         <!-- 右侧按钮:新增用户 -->
         <div class="ml-auto">
-          <Button
-            icon="pi pi-plus"
-            @click="openNewUserDialog"
-            label="新增用户"
-            severity="success"
-            size="small"
-          />
+          <Button icon="pi pi-plus" @click="openNewUserDialog" label="新增用户" severity="success" size="small" />
         </div>
       </div>
     </div>
 
     <!-- 数据表格 -->
-    <DataTable
-      :value="tableData.content"
-      :paginator="true"
+    <DataTable :value="tableData.content" :paginator="true"
       paginatorTemplate="CurrentPageReport FirstPageLink PrevPageLink PageLinks NextPageLink LastPageLink RowsPerPageDropdown JumpToPageInput"
-      currentPageReportTemplate="{totalRecords} 条记录 "
-      :rows="tableData.metadata.size"
-      :rowsPerPageOptions="[10, 20, 50, 100]"
-      :totalRecords="tableData.metadata.total"
-      @page="handlePageChange"
-      lazy
-      scrollable
-    >
-      <Column field="id" header="ID"></Column>
+      currentPageReportTemplate="{totalRecords} 条记录 " :rows="tableData.metadata.size"
+      :rowsPerPageOptions="[10, 20, 50, 100]" :totalRecords="tableData.metadata.total" @page="handlePageChange" lazy
+      scrollable>
+      <Column v-if="isAdmin" field="id" header="ID"></Column>
       <Column field="name" header="用户名"></Column>
       <Column field="role" header="角色">
         <template #body="slotProps">
@@ -311,27 +266,15 @@ onMounted(() => {
       </Column>
       <Column header="操作" style="min-width: 150px">
         <template #body="slotProps">
-          <Button
-            icon="pi pi-pencil"
-            severity="info"
-            size="small"
-            text
-            rounded
-            aria-label="编辑"
-            @click="openEditUserDialog(slotProps.data)"
-          />
+          <Button icon="pi pi-pencil" severity="info" size="small" text rounded aria-label="编辑"
+            @click="openEditUserDialog(slotProps.data)" />
         </template>
       </Column>
     </DataTable>
 
     <!-- 用户表单对话框 -->
-    <Dialog
-      v-model:visible="userDialog"
-      :modal="true"
-      :header="isEditMode ? '编辑用户' : '创建用户'"
-      :style="{ width: '450px' }"
-      position="center"
-    >
+    <Dialog v-model:visible="userDialog" :modal="true" :header="isEditMode ? '编辑用户' : '创建用户'"
+      :style="{ width: '450px' }" position="center">
       <Form v-slot="$form" :resolver="userFormResolver" :initialValues="userForm" @submit="saveUser" class="p-fluid">
         <div class="field mt-4">
           <FloatLabel variant="on">
@@ -350,15 +293,8 @@ onMounted(() => {
           <FloatLabel variant="on">
             <IconField>
               <InputIcon class="pi pi-lock" />
-              <Password
-                id="password"
-                name="password"
-                v-model="userForm.password"
-                toggleMask
-                :feedback="false"
-                autocomplete="off"
-                fluid
-              />
+              <Password id="password" name="password" v-model="userForm.password" toggleMask :feedback="false"
+                autocomplete="off" fluid />
             </IconField>
             <label for="password">{{ isEditMode ? '密码 (可选)' : '密码' }}</label>
           </FloatLabel>
@@ -372,15 +308,8 @@ onMounted(() => {
           <FloatLabel variant="on">
             <IconField>
               <InputIcon class="pi pi-lock" />
-              <Password
-                id="confirmPassword"
-                name="confirmPassword"
-                v-model="userForm.confirmPassword"
-                toggleMask
-                :feedback="false"
-                fluid
-                autocomplete="off"
-              />
+              <Password id="confirmPassword" name="confirmPassword" v-model="userForm.confirmPassword" toggleMask
+                :feedback="false" fluid autocomplete="off" />
             </IconField>
             <label for="confirmPassword">确认密码</label>
           </FloatLabel>
@@ -390,36 +319,20 @@ onMounted(() => {
           <div v-if="isEditMode" class="text-sm text-gray-500 mt-1 ml-1">* 留空则不修改</div>
         </div>
 
-        <div class="field mt-4">
+        <div v-if="isAdmin" class="field mt-4">
           <FloatLabel variant="on">
-            <Select
-              id="role"
-              name="role"
-              v-model="userForm.role"
-              :options="roleOptions"
-              optionLabel="label"
-              optionValue="value"
-              :disabled="isEditMode && !isAdmin"
-              fluid
-            />
+            <Select id="role" name="role" v-model="userForm.role" :options="roleOptions" optionLabel="label"
+              optionValue="value" fluid />
             <label for="role">角色</label>
           </FloatLabel>
           <Message v-if="$form.role?.invalid" severity="error" size="small" variant="simple">
             {{ $form.role.error?.message }}
           </Message>
-          <div v-if="isEditMode && !isAdmin" class="text-sm text-gray-500 mt-1 ml-1">
-            * 您无权修改用户角色
-          </div>
         </div>
 
         <div class="flex justify-end gap-2 mt-4">
-          <Button
-            label="取消"
-            severity="secondary"
-            type="button"
-            @click="userDialog = false"
-            :disabled="userFormLoading"
-          />
+          <Button label="取消" severity="secondary" type="button" @click="userDialog = false"
+            :disabled="userFormLoading" />
           <Button label="保存" type="submit" :loading="userFormLoading" />
         </div>
       </Form>