diff --git a/src/api/infra/job/index.ts b/src/api/infra/job/index.ts
index 63f15da0..c1398d07 100644
--- a/src/api/infra/job/index.ts
+++ b/src/api/infra/job/index.ts
@@ -13,50 +13,38 @@ export interface JobVO {
   createTime: Date
 }
 
-export interface JobPageReqVO extends PageParam {
-  name?: string
-  status?: number
-  handlerName?: string
-}
-
-export interface JobExportReqVO {
-  name?: string
-  status?: number
-  handlerName?: string
-}
-
 // 任务列表
-export const getJobPageApi = (params: JobPageReqVO) => {
+export const getJobPage = (params: PageParam) => {
   return request.get({ url: '/infra/job/page', params })
 }
 
 // 任务详情
-export const getJobApi = (id: number) => {
+export const getJob = (id: number) => {
   return request.get({ url: '/infra/job/get?id=' + id })
 }
 
 // 新增任务
-export const createJobApi = (data: JobVO) => {
+export const createJob = (data: JobVO) => {
   return request.post({ url: '/infra/job/create', data })
 }
 
 // 修改定时任务调度
-export const updateJobApi = (data: JobVO) => {
+export const updateJob = (data: JobVO) => {
   return request.put({ url: '/infra/job/update', data })
 }
 
 // 删除定时任务调度
-export const deleteJobApi = (id: number) => {
+export const deleteJob = (id: number) => {
   return request.delete({ url: '/infra/job/delete?id=' + id })
 }
 
 // 导出定时任务调度
-export const exportJobApi = (params: JobExportReqVO) => {
+export const exportJob = (params) => {
   return request.download({ url: '/infra/job/export-excel', params })
 }
 
 // 任务状态修改
-export const updateJobStatusApi = (id: number, status: number) => {
+export const updateJobStatus = (id: number, status: number) => {
   const params = {
     id,
     status
@@ -70,6 +58,6 @@ export const runJobApi = (id: number) => {
 }
 
 // 获得定时任务的下 n 次执行时间
-export const getJobNextTimesApi = (id: number) => {
+export const getJobNextTimes = (id: number) => {
   return request.get({ url: '/infra/job/get_next_times?id=' + id })
 }
diff --git a/src/api/infra/jobLog/index.ts b/src/api/infra/jobLog/index.ts
index 84b74fbd..f429cd9e 100644
--- a/src/api/infra/jobLog/index.ts
+++ b/src/api/infra/jobLog/index.ts
@@ -14,34 +14,18 @@ export interface JobLogVO {
   createTime: string
 }
 
-export interface JobLogPageReqVO extends PageParam {
-  jobId?: number
-  handlerName?: string
-  beginTime?: string
-  endTime?: string
-  status?: number
-}
-
-export interface JobLogExportReqVO {
-  jobId?: number
-  handlerName?: string
-  beginTime?: string
-  endTime?: string
-  status?: number
-}
-
 // 任务日志列表
-export const getJobLogPageApi = (params: JobLogPageReqVO) => {
+export const getJobLogPage = (params: PageParam) => {
   return request.get({ url: '/infra/job-log/page', params })
 }
 
 // 任务日志详情
-export const getJobLogApi = (id: number) => {
+export const getJobLog = (id: number) => {
   return request.get({ url: '/infra/job-log/get?id=' + id })
 }
 
 // 导出定时任务日志
-export const exportJobLogApi = (params: JobLogExportReqVO) => {
+export const exportJobLog = (params) => {
   return request.download({
     url: '/infra/job-log/export-excel',
     params
diff --git a/src/api/mall/product/category.ts b/src/api/mall/product/category.ts
new file mode 100644
index 00000000..7ae81285
--- /dev/null
+++ b/src/api/mall/product/category.ts
@@ -0,0 +1,60 @@
+import request from '@/config/axios'
+
+/**
+ * 产品分类
+ */
+export interface CategoryVO {
+  /**
+   * 分类编号
+   */
+  id?: number
+  /**
+   * 父分类编号
+   */
+  parentId?: number
+  /**
+   * 分类名称
+   */
+  name: string
+  /**
+   * 分类图片
+   */
+  picUrl: string
+  /**
+   * 分类排序
+   */
+  sort?: number
+  /**
+   * 分类描述
+   */
+  description?: string
+  /**
+   * 开启状态
+   */
+  status: number
+}
+
+// 创建商品分类
+export const createCategory = (data: CategoryVO) => {
+  return request.post({ url: '/product/category/create', data })
+}
+
+// 更新商品分类
+export const updateCategory = (data: CategoryVO) => {
+  return request.put({ url: '/product/category/update', data })
+}
+
+// 删除商品分类
+export const deleteCategory = (id: number) => {
+  return request.delete({ url: `/product/category/delete?id=${id}` })
+}
+
+// 获得商品分类
+export const getCategory = (id: number) => {
+  return request.get({ url: `/product/category/get?id=${id}` })
+}
+
+// 获得商品分类列表
+export const getCategoryList = (params: any) => {
+  return request.get({ url: '/product/category/list', params })
+}
diff --git a/src/api/mall/product/property.ts b/src/api/mall/product/property.ts
new file mode 100644
index 00000000..01c79f9f
--- /dev/null
+++ b/src/api/mall/product/property.ts
@@ -0,0 +1,103 @@
+import request from '@/config/axios'
+
+/**
+ * 商品属性
+ */
+export interface PropertyVO {
+  id?: number
+  /** 名称 */
+  name: string
+  /** 备注 */
+  remark?: string
+}
+
+/**
+ * 属性值
+ */
+export interface PropertyValueVO {
+  id?: number
+  /** 属性项的编号 */
+  propertyId?: number
+  /** 名称 */
+  name: string
+  /** 备注 */
+  remark?: string
+}
+
+/**
+ * 商品属性值的明细
+ */
+export interface PropertyValueDetailVO {
+  /** 属性项的编号 */
+  propertyId: number // 属性的编号
+  /** 属性的名称 */
+  propertyName: string
+  /** 属性值的编号 */
+  valueId: number
+  /** 属性值的名称 */
+  valueName: string
+}
+
+// ------------------------ 属性项 -------------------
+
+// 创建属性项
+export const createProperty = (data: PropertyVO) => {
+  return request.post({ url: '/product/property/create', data })
+}
+
+// 更新属性项
+export const updateProperty = (data: PropertyVO) => {
+  return request.put({ url: '/product/property/update', data })
+}
+
+// 删除属性项
+export const deleteProperty = (id: number) => {
+  return request.delete({ url: `/product/property/delete?id=${id}` })
+}
+
+// 获得属性项
+export const getProperty = (id: number): Promise<PropertyVO> => {
+  return request.get({ url: `/product/property/get?id=${id}` })
+}
+
+// 获得属性项分页
+export const getPropertyPage = (params: PageParam) => {
+  return request.get({ url: '/product/property/page', params })
+}
+
+// 获得属性项列表
+export const getPropertyList = (params: any) => {
+  return request.get({ url: '/product/property/list', params })
+}
+
+// 获得属性项列表
+export const getPropertyListAndValue = (params: any) => {
+  return request.get({ url: '/product/property/get-value-list', params })
+}
+
+// ------------------------ 属性值 -------------------
+
+// 获得属性值分页
+export const getPropertyValuePage = (params: PageParam & any) => {
+  return request.get({ url: '/product/property/value/page', params })
+}
+
+// 获得属性值
+export const getPropertyValue = (id: number): Promise<PropertyValueVO> => {
+  return request.get({ url: `/product/property/value/get?id=${id}` })
+}
+
+// 创建属性值
+export const createPropertyValue = (data: PropertyValueVO) => {
+  return request.post({ url: '/product/property/value/create', data })
+}
+
+// 更新属性值
+export const updatePropertyValue = (data: PropertyValueVO) => {
+  return request.put({ url: '/product/property/value/update', data })
+}
+
+// 删除属性值
+export const deletePropertyValue = (id: number) => {
+  return request.delete({ url: `/product/property/value/delete?id=${id}` })
+}
diff --git a/src/api/pay/merchant/index.ts b/src/api/pay/merchant/index.ts
index b4b6ba51..bfb8f5e4 100644
--- a/src/api/pay/merchant/index.ts
+++ b/src/api/pay/merchant/index.ts
@@ -29,17 +29,17 @@ export interface MerchantExportReqVO {
 }
 
 // 查询列表支付商户
-export const getMerchantPageApi = (params: MerchantPageReqVO) => {
+export const getMerchantPage = (params: MerchantPageReqVO) => {
   return request.get({ url: '/pay/merchant/page', params })
 }
 
 // 查询详情支付商户
-export const getMerchantApi = (id: number) => {
+export const getMerchant = (id: number) => {
   return request.get({ url: '/pay/merchant/get?id=' + id })
 }
 
 // 根据商户名称搜索商户列表
-export const getMerchantListByNameApi = (name: string) => {
+export const getMerchantListByName = (name: string) => {
   return request.get({
     url: '/pay/merchant/list-by-name?id=',
     params: {
@@ -49,26 +49,27 @@ export const getMerchantListByNameApi = (name: string) => {
 }
 
 // 新增支付商户
-export const createMerchantApi = (data: MerchantVO) => {
+export const createMerchant = (data: MerchantVO) => {
   return request.post({ url: '/pay/merchant/create', data })
 }
 
 // 修改支付商户
-export const updateMerchantApi = (data: MerchantVO) => {
+export const updateMerchant = (data: MerchantVO) => {
   return request.put({ url: '/pay/merchant/update', data })
 }
 
 // 删除支付商户
-export const deleteMerchantApi = (id: number) => {
+export const deleteMerchant = (id: number) => {
   return request.delete({ url: '/pay/merchant/delete?id=' + id })
 }
 
 // 导出支付商户
-export const exportMerchantApi = (params: MerchantExportReqVO) => {
+export const exportMerchant = (params: MerchantExportReqVO) => {
   return request.download({ url: '/pay/merchant/export-excel', params })
 }
+
 // 支付商户状态修改
-export const changeMerchantStatusApi = (id: number, status: number) => {
+export const updateMerchantStatus = (id: number, status: number) => {
   const data = {
     id,
     status
diff --git a/src/api/system/dict/dict.data.ts b/src/api/system/dict/dict.data.ts
index 6d981326..87e7dce7 100644
--- a/src/api/system/dict/dict.data.ts
+++ b/src/api/system/dict/dict.data.ts
@@ -44,6 +44,6 @@ export const deleteDictData = (id: number) => {
 }
 
 // 导出字典类型数据
-export const exportDictDataApi = (params) => {
+export const exportDictData = (params) => {
   return request.get({ url: '/system/dict-data/export', params })
 }
diff --git a/src/api/system/oauth2/client.ts b/src/api/system/oauth2/client.ts
index 4c06386d..6f71acad 100644
--- a/src/api/system/oauth2/client.ts
+++ b/src/api/system/oauth2/client.ts
@@ -21,31 +21,27 @@ export interface OAuth2ClientVO {
   createTime: Date
 }
 
-export interface OAuth2ClientPageReqVO extends PageParam {
-  name?: string
-  status?: number
-}
-// 查询 OAuth2列表
-export const getOAuth2ClientPageApi = (params: OAuth2ClientPageReqVO) => {
+// 查询 OAuth2 客户端的列表
+export const getOAuth2ClientPage = (params: PageParam) => {
   return request.get({ url: '/system/oauth2-client/page', params })
 }
 
-// 查询 OAuth2详情
-export const getOAuth2ClientApi = (id: number) => {
+// 查询 OAuth2 客户端的详情
+export const getOAuth2Client = (id: number) => {
   return request.get({ url: '/system/oauth2-client/get?id=' + id })
 }
 
-// 新增 OAuth2
-export const createOAuth2ClientApi = (data: OAuth2ClientVO) => {
+// 新增 OAuth2 客户端
+export const createOAuth2Client = (data: OAuth2ClientVO) => {
   return request.post({ url: '/system/oauth2-client/create', data })
 }
 
-// 修改 OAuth2
-export const updateOAuth2ClientApi = (data: OAuth2ClientVO) => {
+// 修改 OAuth2 客户端
+export const updateOAuth2Client = (data: OAuth2ClientVO) => {
   return request.put({ url: '/system/oauth2-client/update', data })
 }
 
 // 删除 OAuth2
-export const deleteOAuth2ClientApi = (id: number) => {
+export const deleteOAuth2Client = (id: number) => {
   return request.delete({ url: '/system/oauth2-client/delete?id=' + id })
 }
diff --git a/src/api/system/permission/index.ts b/src/api/system/permission/index.ts
index c529f884..baf2805b 100644
--- a/src/api/system/permission/index.ts
+++ b/src/api/system/permission/index.ts
@@ -17,26 +17,26 @@ export interface PermissionAssignRoleDataScopeReqVO {
 }
 
 // 查询角色拥有的菜单权限
-export const listRoleMenusApi = async (roleId: number) => {
+export const getRoleMenuList = async (roleId: number) => {
   return await request.get({ url: '/system/permission/list-role-resources?roleId=' + roleId })
 }
 
 // 赋予角色菜单权限
-export const assignRoleMenuApi = async (data: PermissionAssignRoleMenuReqVO) => {
+export const assignRoleMenu = async (data: PermissionAssignRoleMenuReqVO) => {
   return await request.post({ url: '/system/permission/assign-role-menu', data })
 }
 
 // 赋予角色数据权限
-export const assignRoleDataScopeApi = async (data: PermissionAssignRoleDataScopeReqVO) => {
+export const assignRoleDataScope = async (data: PermissionAssignRoleDataScopeReqVO) => {
   return await request.post({ url: '/system/permission/assign-role-data-scope', data })
 }
 
 // 查询用户拥有的角色数组
-export const listUserRolesApi = async (userId: number) => {
+export const getUserRoleList = async (userId: number) => {
   return await request.get({ url: '/system/permission/list-user-roles?userId=' + userId })
 }
 
 // 赋予用户角色
-export const assignUserRoleApi = async (data: PermissionAssignUserRoleReqVO) => {
+export const assignUserRole = async (data: PermissionAssignUserRoleReqVO) => {
   return await request.post({ url: '/system/permission/assign-user-role', data })
 }
diff --git a/src/api/system/role/index.ts b/src/api/system/role/index.ts
index 902d5ca6..93636ff0 100644
--- a/src/api/system/role/index.ts
+++ b/src/api/system/role/index.ts
@@ -7,6 +7,8 @@ export interface RoleVO {
   sort: number
   status: number
   type: number
+  dataScope: number
+  dataScopeDeptIds: number[]
   createTime: Date
 }
 
@@ -49,6 +51,7 @@ export const updateRoleStatus = async (data: UpdateStatusReqVO) => {
 export const deleteRole = async (id: number) => {
   return await request.delete({ url: '/system/role/delete?id=' + id })
 }
+
 // 导出角色
 export const exportRole = (params) => {
   return request.download({
diff --git a/src/api/system/user/index.ts b/src/api/system/user/index.ts
index e488c0d7..6224f0e8 100644
--- a/src/api/system/user/index.ts
+++ b/src/api/system/user/index.ts
@@ -17,58 +17,43 @@ export interface UserVO {
   createTime: Date
 }
 
-export interface UserPageReqVO extends PageParam {
-  deptId?: number
-  username?: string
-  mobile?: string
-  status?: number
-  createTime?: Date[]
-}
-
-export interface UserExportReqVO {
-  code?: string
-  name?: string
-  status?: number
-  createTime?: Date[]
-}
-
 // 查询用户管理列表
-export const getUserPageApi = (params: UserPageReqVO) => {
+export const getUserPage = (params: PageParam) => {
   return request.get({ url: '/system/user/page', params })
 }
 
 // 查询用户详情
-export const getUserApi = (id: number) => {
+export const getUser = (id: number) => {
   return request.get({ url: '/system/user/get?id=' + id })
 }
 
 // 新增用户
-export const createUserApi = (data: UserVO | Recordable) => {
+export const createUser = (data: UserVO) => {
   return request.post({ url: '/system/user/create', data })
 }
 
 // 修改用户
-export const updateUserApi = (data: UserVO | Recordable) => {
+export const updateUser = (data: UserVO) => {
   return request.put({ url: '/system/user/update', data })
 }
 
 // 删除用户
-export const deleteUserApi = (id: number) => {
+export const deleteUser = (id: number) => {
   return request.delete({ url: '/system/user/delete?id=' + id })
 }
 
 // 导出用户
-export const exportUserApi = (params: UserExportReqVO) => {
+export const exportUser = (params) => {
   return request.download({ url: '/system/user/export', params })
 }
 
 // 下载用户导入模板
-export const importUserTemplateApi = () => {
+export const importUserTemplate = () => {
   return request.download({ url: '/system/user/get-import-template' })
 }
 
 // 用户密码重置
-export const resetUserPwdApi = (id: number, password: string) => {
+export const resetUserPwd = (id: number, password: string) => {
   const data = {
     id,
     password
@@ -77,7 +62,7 @@ export const resetUserPwdApi = (id: number, password: string) => {
 }
 
 // 用户状态修改
-export const updateUserStatusApi = (id: number, status: number) => {
+export const updateUserStatus = (id: number, status: number) => {
   const data = {
     id,
     status
diff --git a/src/components/Crontab/src/Crontab.vue b/src/components/Crontab/src/Crontab.vue
index fe33bd5f..0e474fb2 100644
--- a/src/components/Crontab/src/Crontab.vue
+++ b/src/components/Crontab/src/Crontab.vue
@@ -6,7 +6,10 @@ interface shortcutsType {
   value: string
 }
 const props = defineProps({
-  modelValue: { type: String, default: '* * * * * ?' },
+  modelValue: {
+    type: String,
+    default: '* * * * * ?'
+  },
   shortcuts: { type: Array as PropType<shortcutsType[]>, default: () => [] }
 })
 const defaultValue = ref('')
diff --git a/src/router/modules/remaining.ts b/src/router/modules/remaining.ts
index 4d8c3dac..2dc9522d 100644
--- a/src/router/modules/remaining.ts
+++ b/src/router/modules/remaining.ts
@@ -162,7 +162,7 @@ const remainingRouter: AppRouteRecordRaw[] = [
     children: [
       {
         path: 'job-log',
-        component: () => import('@/views/infra/job/JobLog.vue'),
+        component: () => import('@/views/infra/job/logger/index.vue'),
         name: 'JobLog',
         meta: {
           noCache: true,
@@ -319,6 +319,22 @@ const remainingRouter: AppRouteRecordRaw[] = [
         }
       }
     ]
+  },
+  {
+    path: '/property',
+    component: Layout,
+    name: 'property',
+    meta: {
+      hidden: true
+    },
+    children: [
+      {
+        path: 'value/:propertyId(\\d+)',
+        component: () => import('@/views/mall/product/property/value/index.vue'),
+        name: 'PropertyValue',
+        meta: { title: '商品属性值', icon: '', activeMenu: '/product/property' }
+      }
+    ]
   }
 ]
 
diff --git a/src/types/auto-components.d.ts b/src/types/auto-components.d.ts
index 2a42203d..80a5900f 100644
--- a/src/types/auto-components.d.ts
+++ b/src/types/auto-components.d.ts
@@ -23,6 +23,7 @@ declare module '@vue/runtime-core' {
     DictTag: typeof import('./../components/DictTag/src/DictTag.vue')['default']
     Echart: typeof import('./../components/Echart/src/Echart.vue')['default']
     Editor: typeof import('./../components/Editor/src/Editor.vue')['default']
+    ElAutoResizer: typeof import('element-plus/es')['ElAutoResizer']
     ElBadge: typeof import('element-plus/es')['ElBadge']
     ElButton: typeof import('element-plus/es')['ElButton']
     ElButtonGroup: typeof import('element-plus/es')['ElButtonGroup']
@@ -52,13 +53,16 @@ declare module '@vue/runtime-core' {
     ElForm: typeof import('element-plus/es')['ElForm']
     ElFormItem: typeof import('element-plus/es')['ElFormItem']
     ElIcon: typeof import('element-plus/es')['ElIcon']
+    ElImage: typeof import('element-plus/es')['ElImage']
     ElImageViewer: typeof import('element-plus/es')['ElImageViewer']
     ElInput: typeof import('element-plus/es')['ElInput']
+    ElInputNumber: typeof import('element-plus/es')['ElInputNumber']
     ElLink: typeof import('element-plus/es')['ElLink']
     ElOption: typeof import('element-plus/es')['ElOption']
     ElPagination: typeof import('element-plus/es')['ElPagination']
     ElPopover: typeof import('element-plus/es')['ElPopover']
     ElRadio: typeof import('element-plus/es')['ElRadio']
+    ElRadioButton: typeof import('element-plus/es')['ElRadioButton']
     ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup']
     ElRow: typeof import('element-plus/es')['ElRow']
     ElScrollbar: typeof import('element-plus/es')['ElScrollbar']
@@ -67,9 +71,15 @@ declare module '@vue/runtime-core' {
     ElSwitch: typeof import('element-plus/es')['ElSwitch']
     ElTable: typeof import('element-plus/es')['ElTable']
     ElTableColumn: typeof import('element-plus/es')['ElTableColumn']
+    ElTableV2: typeof import('element-plus/es')['ElTableV2']
     ElTabPane: typeof import('element-plus/es')['ElTabPane']
     ElTabs: typeof import('element-plus/es')['ElTabs']
+    ElTag: typeof import('element-plus/es')['ElTag']
+    ElTimeline: typeof import('element-plus/es')['ElTimeline']
+    ElTimelineItem: typeof import('element-plus/es')['ElTimelineItem']
     ElTooltip: typeof import('element-plus/es')['ElTooltip']
+    ElTransfer: typeof import('element-plus/es')['ElTransfer']
+    ElTree: typeof import('element-plus/es')['ElTree']
     ElTreeSelect: typeof import('element-plus/es')['ElTreeSelect']
     ElUpload: typeof import('element-plus/es')['ElUpload']
     Error: typeof import('./../components/Error/src/Error.vue')['default']
diff --git a/src/views/bpm/form/editor/index.vue b/src/views/bpm/form/editor/index.vue
index cb7d023f..3a28697f 100644
--- a/src/views/bpm/form/editor/index.vue
+++ b/src/views/bpm/form/editor/index.vue
@@ -11,7 +11,7 @@
   </ContentWrap>
 
   <!-- 表单保存的弹窗 -->
-  <Dialog title="保存表单" v-model="modelVisible" width="600">
+  <Dialog title="保存表单" v-model="dialogVisible" width="600">
     <el-form ref="formRef" :model="formData" :rules="formRules" label-width="80px">
       <el-form-item label="表单名" prop="name">
         <el-input v-model="formData.name" placeholder="请输入表单名" />
@@ -33,7 +33,7 @@
     </el-form>
     <template #footer>
       <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
-      <el-button @click="modelVisible = false">取 消</el-button>
+      <el-button @click="dialogVisible = false">取 消</el-button>
     </template>
   </Dialog>
 </template>
@@ -48,7 +48,7 @@ const message = useMessage() // 消息
 const { query } = useRoute() // 路由
 
 const designer = ref() // 表单设计器
-const modelVisible = ref(false) // 弹窗是否展示
+const dialogVisible = ref(false) // 弹窗是否展示
 const formLoading = ref(false) // 表单的加载中:提交的按钮禁用
 const formData = ref({
   name: '',
@@ -63,7 +63,7 @@ const formRef = ref() // 表单 Ref
 
 /** 处理保存按钮 */
 const handleSave = () => {
-  modelVisible.value = true
+  dialogVisible.value = true
 }
 
 /** 提交表单 */
@@ -85,7 +85,7 @@ const submitForm = async () => {
       await FormApi.updateForm(data)
       message.success(t('common.updateSuccess'))
     }
-    modelVisible.value = false
+    dialogVisible.value = false
   } finally {
     formLoading.value = false
   }
diff --git a/src/views/bpm/form/index.vue b/src/views/bpm/form/index.vue
index 616e60be..f8d94317 100644
--- a/src/views/bpm/form/index.vue
+++ b/src/views/bpm/form/index.vue
@@ -20,7 +20,7 @@
       <el-form-item>
         <el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
         <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
-        <el-button type="primary" @click="openForm()" v-hasPermi="['bpm:form:create']">
+        <el-button type="primary" plain @click="openForm" v-hasPermi="['bpm:form:create']">
           <Icon icon="ep:plus" class="mr-5px" /> 新增
         </el-button>
       </el-form-item>
diff --git a/src/views/bpm/group/UserGroupForm.vue b/src/views/bpm/group/UserGroupForm.vue
index 9496ad84..e8011d8c 100644
--- a/src/views/bpm/group/UserGroupForm.vue
+++ b/src/views/bpm/group/UserGroupForm.vue
@@ -1,5 +1,5 @@
 <template>
-  <Dialog :title="modelTitle" v-model="modelVisible">
+  <Dialog :title="dialogTitle" v-model="dialogVisible">
     <el-form
       ref="formRef"
       :model="formData"
@@ -37,7 +37,7 @@
     </el-form>
     <template #footer>
       <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
-      <el-button @click="modelVisible = false">取 消</el-button>
+      <el-button @click="dialogVisible = false">取 消</el-button>
     </template>
   </Dialog>
 </template>
@@ -50,8 +50,8 @@ import * as UserApi from '@/api/system/user'
 const { t } = useI18n() // 国际化
 const message = useMessage() // 消息弹窗
 
-const modelVisible = ref(false) // 弹窗的是否展示
-const modelTitle = ref('') // 弹窗的标题
+const dialogVisible = ref(false) // 弹窗的是否展示
+const dialogTitle = ref('') // 弹窗的标题
 const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
 const formType = ref('') // 表单的类型:create - 新增;update - 修改
 const formData = ref({
@@ -72,8 +72,8 @@ const userList = ref([]) // 用户列表
 
 /** 打开弹窗 */
 const open = async (type: string, id?: number) => {
-  modelVisible.value = true
-  modelTitle.value = t('action.' + type)
+  dialogVisible.value = true
+  dialogTitle.value = t('action.' + type)
   formType.value = type
   resetForm()
   // 修改时,设置数据
@@ -108,7 +108,7 @@ const submitForm = async () => {
       await UserGroupApi.updateUserGroup(data)
       message.success(t('common.updateSuccess'))
     }
-    modelVisible.value = false
+    dialogVisible.value = false
     // 发送操作成功的事件
     emit('success')
   } finally {
diff --git a/src/views/bpm/group/index.vue b/src/views/bpm/group/index.vue
index 0b52e9a2..0c731dbe 100644
--- a/src/views/bpm/group/index.vue
+++ b/src/views/bpm/group/index.vue
@@ -43,6 +43,7 @@
         <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
         <el-button
           type="primary"
+          plain
           @click="openForm('create')"
           v-hasPermi="['bpm:user-group:create']"
         >
diff --git a/src/views/bpm/model/ModelForm.vue b/src/views/bpm/model/ModelForm.vue
index ac536958..24484ec6 100644
--- a/src/views/bpm/model/ModelForm.vue
+++ b/src/views/bpm/model/ModelForm.vue
@@ -1,5 +1,5 @@
 <template>
-  <Dialog :title="modelTitle" v-model="modelVisible" width="600">
+  <Dialog :title="dialogTitle" v-model="dialogVisible" width="600">
     <el-form
       ref="formRef"
       :model="formData"
@@ -117,7 +117,7 @@
     </el-form>
     <template #footer>
       <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
-      <el-button @click="modelVisible = false">取 消</el-button>
+      <el-button @click="dialogVisible = false">取 消</el-button>
     </template>
   </Dialog>
 </template>
@@ -129,8 +129,8 @@ import * as FormApi from '@/api/bpm/form'
 const { t } = useI18n() // 国际化
 const message = useMessage() // 消息弹窗
 
-const modelVisible = ref(false) // 弹窗的是否展示
-const modelTitle = ref('') // 弹窗的标题
+const dialogVisible = ref(false) // 弹窗的是否展示
+const dialogTitle = ref('') // 弹窗的标题
 const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
 const formType = ref('') // 表单的类型:create - 新增;update - 修改
 const formData = ref({
@@ -154,8 +154,8 @@ const formList = ref([]) // 流程表单的下拉框的数据
 
 /** 打开弹窗 */
 const open = async (type: string, id?: number) => {
-  modelVisible.value = true
-  modelTitle.value = t('action.' + type)
+  dialogVisible.value = true
+  dialogTitle.value = t('action.' + type)
   formType.value = type
   resetForm()
   // 修改时,设置数据
@@ -203,7 +203,7 @@ const submitForm = async () => {
       await ModelApi.updateModel(data)
       message.success(t('common.updateSuccess'))
     }
-    modelVisible.value = false
+    dialogVisible.value = false
     // 发送操作成功的事件
     emit('success')
   } finally {
diff --git a/src/views/bpm/model/ModelImportForm.vue b/src/views/bpm/model/ModelImportForm.vue
index ac26ac08..76493c95 100644
--- a/src/views/bpm/model/ModelImportForm.vue
+++ b/src/views/bpm/model/ModelImportForm.vue
@@ -1,5 +1,5 @@
 <template>
-  <Dialog title="导入流程" v-model="modelVisible" width="400">
+  <Dialog title="导入流程" v-model="dialogVisible" width="400">
     <div>
       <el-upload
         ref="uploadRef"
@@ -8,7 +8,7 @@
         :data="formData"
         name="bpmnFile"
         v-model:file-list="fileList"
-        :drag="true"
+        drag
         :auto-upload="false"
         accept=".bpmn, .xml"
         :limit="1"
@@ -45,7 +45,7 @@
     </div>
     <template #footer>
       <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
-      <el-button @click="modelVisible = false">取 消</el-button>
+      <el-button @click="dialogVisible = false">取 消</el-button>
     </template>
   </Dialog>
 </template>
@@ -53,7 +53,7 @@
 import { getAccessToken, getTenantId } from '@/utils/auth'
 const message = useMessage() // 消息弹窗
 
-const modelVisible = ref(false) // 弹窗的是否展示
+const dialogVisible = ref(false) // 弹窗的是否展示
 const formLoading = ref(false) // 表单的加载中
 const formData = ref({
   key: '',
@@ -72,12 +72,12 @@ const fileList = ref([]) // 文件列表
 
 /** 打开弹窗 */
 const open = async () => {
-  modelVisible.value = true
+  dialogVisible.value = true
   resetForm()
 }
 defineExpose({ open }) // 提供 open 方法,用于打开弹窗
 
-/** 重置表单 */
+/** 提交表单 */
 const submitForm = async () => {
   // 校验表单
   if (!formRef) return
@@ -98,7 +98,7 @@ const submitForm = async () => {
 
 /** 文件上传成功 */
 const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
-const submitFormSuccess = async (response: any): Promise<void> => {
+const submitFormSuccess = async (response: any) => {
   if (response.code !== 0) {
     message.error(response.msg)
     formLoading.value = false
diff --git a/src/views/bpm/processInstance/detail/TaskUpdateAssigneeForm.vue b/src/views/bpm/processInstance/detail/TaskUpdateAssigneeForm.vue
index 7f9cfd48..0f16deeb 100644
--- a/src/views/bpm/processInstance/detail/TaskUpdateAssigneeForm.vue
+++ b/src/views/bpm/processInstance/detail/TaskUpdateAssigneeForm.vue
@@ -1,5 +1,5 @@
 <template>
-  <Dialog title="转派审批人" v-model="modelVisible" width="500">
+  <Dialog title="转派审批人" v-model="dialogVisible" width="500">
     <el-form
       ref="formRef"
       :model="formData"
@@ -20,7 +20,7 @@
     </el-form>
     <template #footer>
       <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
-      <el-button @click="modelVisible = false">取 消</el-button>
+      <el-button @click="dialogVisible = false">取 消</el-button>
     </template>
   </Dialog>
 </template>
@@ -28,7 +28,7 @@
 import * as TaskApi from '@/api/bpm/task'
 import * as UserApi from '@/api/system/user'
 
-const modelVisible = ref(false) // 弹窗的是否展示
+const dialogVisible = ref(false) // 弹窗的是否展示
 const formLoading = ref(false) // 表单的加载中
 const formData = ref({
   id: '',
@@ -43,7 +43,7 @@ const userList = ref<any[]>([]) // 用户列表
 
 /** 打开弹窗 */
 const open = async (id: string) => {
-  modelVisible.value = true
+  dialogVisible.value = true
   resetForm()
   formData.value.id = id
   // 获得用户列表
@@ -62,7 +62,7 @@ const submitForm = async () => {
   formLoading.value = true
   try {
     await TaskApi.updateTaskAssignee(formData.value)
-    modelVisible.value = false
+    dialogVisible.value = false
     // 发送操作成功的事件
     emit('success')
   } finally {
diff --git a/src/views/bpm/taskAssignRule/TaskAssignRuleForm.vue b/src/views/bpm/taskAssignRule/TaskAssignRuleForm.vue
index a452cab9..2ddebab1 100644
--- a/src/views/bpm/taskAssignRule/TaskAssignRuleForm.vue
+++ b/src/views/bpm/taskAssignRule/TaskAssignRuleForm.vue
@@ -1,5 +1,5 @@
 <template>
-  <Dialog title="修改任务规则" v-model="modelVisible" width="600">
+  <Dialog title="修改任务规则" v-model="dialogVisible" width="600">
     <el-form ref="formRef" :model="formData" :rules="formRules" label-width="80px">
       <el-form-item label="任务名称" prop="taskDefinitionName">
         <el-input v-model="formData.taskDefinitionName" placeholder="请输入流标标识" disabled />
@@ -93,7 +93,7 @@
     <!-- 操作按钮 -->
     <template #footer>
       <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
-      <el-button @click="modelVisible = false">取 消</el-button>
+      <el-button @click="dialogVisible = false">取 消</el-button>
     </template>
   </Dialog>
 </template>
@@ -109,7 +109,7 @@ import * as UserGroupApi from '@/api/bpm/userGroup'
 const { t } = useI18n() // 国际化
 const message = useMessage() // 消息弹窗
 
-const modelVisible = ref(false) // 弹窗的是否展示
+const dialogVisible = ref(false) // 弹窗的是否展示
 const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
 const formData = ref({
   type: Number(undefined),
@@ -171,7 +171,7 @@ const open = async (modelId: string, row: TaskAssignRuleApi.TaskAssignVO) => {
     formData.value.scripts.push(...row.options)
   }
   // 打开弹窗
-  modelVisible.value = true
+  dialogVisible.value = true
 
   // 获得角色列表
   roleOptions.value = await RoleApi.getSimpleRoleList()
@@ -232,7 +232,7 @@ const submitForm = async () => {
       await TaskAssignRuleApi.updateTaskAssignRule(data)
       message.success(t('common.updateSuccess'))
     }
-    modelVisible.value = false
+    dialogVisible.value = false
     // 发送操作成功的事件
     emit('success')
   } finally {
diff --git a/src/views/infra/apiAccessLog/ApiAccessLogDetail.vue b/src/views/infra/apiAccessLog/ApiAccessLogDetail.vue
index d046a521..4746b0c7 100644
--- a/src/views/infra/apiAccessLog/ApiAccessLogDetail.vue
+++ b/src/views/infra/apiAccessLog/ApiAccessLogDetail.vue
@@ -1,5 +1,5 @@
 <template>
-  <Dialog title="详情" v-model="modelVisible" :scroll="true" :max-height="500" width="800">
+  <Dialog title="详情" v-model="dialogVisible" :scroll="true" :max-height="500" width="800">
     <el-descriptions border :column="1">
       <el-descriptions-item label="日志主键" min-width="120">
         {{ detailData.id }}
@@ -45,13 +45,13 @@ import { DICT_TYPE } from '@/utils/dict'
 import { formatDate } from '@/utils/formatTime'
 import * as ApiAccessLog from '@/api/infra/apiAccessLog'
 
-const modelVisible = ref(false) // 弹窗的是否展示
+const dialogVisible = ref(false) // 弹窗的是否展示
 const detailLoading = ref(false) // 表单地加载中
 const detailData = ref() // 详情数据
 
 /** 打开弹窗 */
 const open = async (data: ApiAccessLog.ApiAccessLogVO) => {
-  modelVisible.value = true
+  dialogVisible.value = true
   // 设置数据
   detailLoading.value = true
   try {
diff --git a/src/views/infra/apiErrorLog/ApiErrorLogDetail.vue b/src/views/infra/apiErrorLog/ApiErrorLogDetail.vue
index 5076fe00..4b279924 100644
--- a/src/views/infra/apiErrorLog/ApiErrorLogDetail.vue
+++ b/src/views/infra/apiErrorLog/ApiErrorLogDetail.vue
@@ -1,5 +1,5 @@
 <template>
-  <Dialog title="详情" v-model="modelVisible" :scroll="true" :max-height="500" width="800">
+  <Dialog title="详情" v-model="dialogVisible" :scroll="true" :max-height="500" width="800">
     <el-descriptions border :column="1">
       <el-descriptions-item label="日志主键" min-width="120">
         {{ detailData.id }}
@@ -60,13 +60,13 @@ import { DICT_TYPE } from '@/utils/dict'
 import { formatDate } from '@/utils/formatTime'
 import * as ApiErrorLog from '@/api/infra/apiErrorLog'
 
-const modelVisible = ref(false) // 弹窗的是否展示
+const dialogVisible = ref(false) // 弹窗的是否展示
 const detailLoading = ref(false) // 表单的加载中
 const detailData = ref() // 详情数据
 
 /** 打开弹窗 */
 const open = async (data: ApiErrorLog.ApiErrorLogVO) => {
-  modelVisible.value = true
+  dialogVisible.value = true
   // 设置数据
   detailLoading.value = true
   try {
diff --git a/src/views/infra/codegen/ImportTable.vue b/src/views/infra/codegen/ImportTable.vue
index b89b2923..0146b6c3 100644
--- a/src/views/infra/codegen/ImportTable.vue
+++ b/src/views/infra/codegen/ImportTable.vue
@@ -1,5 +1,5 @@
 <template>
-  <Dialog title="导入表" v-model="modelVisible" width="800px">
+  <Dialog title="导入表" v-model="dialogVisible" width="800px">
     <!-- 搜索栏 -->
     <el-form :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px">
       <el-form-item label="数据源" prop="dataSourceConfigId">
@@ -69,7 +69,7 @@ import * as DataSourceConfigApi from '@/api/infra/dataSourceConfig'
 import { ElTable } from 'element-plus'
 const message = useMessage() // 消息弹窗
 
-const modelVisible = ref(false) // 弹窗的是否展示
+const dialogVisible = ref(false) // 弹窗的是否展示
 const dbTableLoading = ref(true) // 数据源的加载中
 const dbTableList = ref<CodegenApi.DatabaseTableVO[]>([]) // 表的列表
 const queryParams = reactive({
@@ -103,7 +103,7 @@ const open = async () => {
   // 加载数据源的列表
   dataSourceConfigList.value = await DataSourceConfigApi.getDataSourceConfigList()
   queryParams.dataSourceConfigId = dataSourceConfigList.value[0].id as number
-  modelVisible.value = true
+  dialogVisible.value = true
   // 加载表的列表
   await getList()
 }
@@ -111,7 +111,7 @@ defineExpose({ open }) // 提供 open 方法,用于打开弹窗
 
 /** 关闭弹窗 */
 const close = () => {
-  modelVisible.value = false
+  dialogVisible.value = false
   tableList.value = []
 }
 
diff --git a/src/views/infra/codegen/PreviewCode.vue b/src/views/infra/codegen/PreviewCode.vue
index df521f5a..6a81499d 100644
--- a/src/views/infra/codegen/PreviewCode.vue
+++ b/src/views/infra/codegen/PreviewCode.vue
@@ -1,7 +1,7 @@
 <template>
   <Dialog
     title="代码预览"
-    v-model="modelVisible"
+    v-model="dialogVisible"
     align-center
     width="80%"
     class="app-infra-codegen-preview-container"
@@ -61,7 +61,7 @@ import * as CodegenApi from '@/api/infra/codegen'
 const { t } = useI18n() // 国际化
 const message = useMessage() // 消息弹窗
 
-const modelVisible = ref(false) // 弹窗的是否展示
+const dialogVisible = ref(false) // 弹窗的是否展示
 const loading = ref(false) // 加载中的状态
 const preview = reactive({
   fileTree: [], // 文件树
@@ -86,7 +86,7 @@ interface filesType {
 
 /** 打开弹窗 */
 const open = async (id: number) => {
-  modelVisible.value = true
+  dialogVisible.value = true
   try {
     loading.value = true
     // 生成代码
diff --git a/src/views/infra/codegen/index.vue b/src/views/infra/codegen/index.vue
index 34c81e58..4325f702 100644
--- a/src/views/infra/codegen/index.vue
+++ b/src/views/infra/codegen/index.vue
@@ -163,7 +163,7 @@ const queryParams = reactive({
 const queryFormRef = ref() // 搜索的表单
 const dataSourceConfigList = ref<DataSourceConfigApi.DataSourceConfigVO[]>([]) // 数据源列表
 
-/** 查询参数列表 */
+/** 查询列表 */
 const getList = async () => {
   loading.value = true
   try {
diff --git a/src/views/infra/config/form.vue b/src/views/infra/config/form.vue
index 8d96b629..18ecfa3d 100644
--- a/src/views/infra/config/form.vue
+++ b/src/views/infra/config/form.vue
@@ -1,5 +1,5 @@
 <template>
-  <Dialog :title="modelTitle" v-model="modelVisible">
+  <Dialog :title="dialogTitle" v-model="dialogVisible">
     <el-form
       ref="formRef"
       :model="formData"
@@ -36,7 +36,7 @@
     </el-form>
     <template #footer>
       <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
-      <el-button @click="modelVisible = false">取 消</el-button>
+      <el-button @click="dialogVisible = false">取 消</el-button>
     </template>
   </Dialog>
 </template>
@@ -47,8 +47,8 @@ import * as ConfigApi from '@/api/infra/config'
 const { t } = useI18n() // 国际化
 const message = useMessage() // 消息弹窗
 
-const modelVisible = ref(false) // 弹窗的是否展示
-const modelTitle = ref('') // 弹窗的标题
+const dialogVisible = ref(false) // 弹窗的是否展示
+const dialogTitle = ref('') // 弹窗的标题
 const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
 const formType = ref('') // 表单的类型:create - 新增;update - 修改
 const formData = ref({
@@ -71,8 +71,8 @@ const formRef = ref() // 表单 Ref
 
 /** 打开弹窗 */
 const openModal = async (type: string, id?: number) => {
-  modelVisible.value = true
-  modelTitle.value = t('action.' + type)
+  dialogVisible.value = true
+  dialogTitle.value = t('action.' + type)
   formType.value = type
   resetForm()
   // 修改时,设置数据
@@ -105,7 +105,7 @@ const submitForm = async () => {
       await ConfigApi.updateConfig(data)
       message.success(t('common.updateSuccess'))
     }
-    modelVisible.value = false
+    dialogVisible.value = false
     // 发送操作成功的事件
     emit('success')
   } finally {
diff --git a/src/views/infra/config/index.vue b/src/views/infra/config/index.vue
index 5fcafc07..cbbabc4f 100644
--- a/src/views/infra/config/index.vue
+++ b/src/views/infra/config/index.vue
@@ -55,7 +55,12 @@
       <el-form-item>
         <el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
         <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
-        <el-button type="primary" @click="openModal('create')" v-hasPermi="['infra:config:create']">
+        <el-button
+          type="primary"
+          plain
+          @click="openModal('create')"
+          v-hasPermi="['infra:config:create']"
+        >
           <Icon icon="ep:plus" class="mr-5px" /> 新增
         </el-button>
         <el-button
diff --git a/src/views/infra/dataSourceConfig/form.vue b/src/views/infra/dataSourceConfig/form.vue
index cd79e24b..33f67c56 100644
--- a/src/views/infra/dataSourceConfig/form.vue
+++ b/src/views/infra/dataSourceConfig/form.vue
@@ -1,5 +1,5 @@
 <template>
-  <Dialog :title="modelTitle" v-model="modelVisible">
+  <Dialog :title="dialogTitle" v-model="dialogVisible">
     <el-form
       ref="formRef"
       :model="formData"
@@ -22,7 +22,7 @@
     </el-form>
     <template #footer>
       <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
-      <el-button @click="modelVisible = false">取 消</el-button>
+      <el-button @click="dialogVisible = false">取 消</el-button>
     </template>
   </Dialog>
 </template>
@@ -32,8 +32,8 @@ import * as DataSourceConfigApi from '@/api/infra/dataSourceConfig'
 const { t } = useI18n() // 国际化
 const message = useMessage() // 消息弹窗
 
-const modelVisible = ref(false) // 弹窗的是否展示
-const modelTitle = ref('') // 弹窗的标题
+const dialogVisible = ref(false) // 弹窗的是否展示
+const dialogTitle = ref('') // 弹窗的标题
 const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
 const formType = ref('') // 表单的类型:create - 新增;update - 修改
 const formData = ref<DataSourceConfigApi.DataSourceConfigVO>({
@@ -53,8 +53,8 @@ const formRef = ref() // 表单 Ref
 
 /** 打开弹窗 */
 const openModal = async (type: string, id?: number) => {
-  modelVisible.value = true
-  modelTitle.value = t('action.' + type)
+  dialogVisible.value = true
+  dialogTitle.value = t('action.' + type)
   formType.value = type
   resetForm()
   // 修改时,设置数据
@@ -87,7 +87,7 @@ const submitForm = async () => {
       await DataSourceConfigApi.updateDataSourceConfig(data)
       message.success(t('common.updateSuccess'))
     }
-    modelVisible.value = false
+    dialogVisible.value = false
     // 发送操作成功的事件
     emit('success')
   } finally {
diff --git a/src/views/infra/dataSourceConfig/index.vue b/src/views/infra/dataSourceConfig/index.vue
index ab3523e7..3b5eddba 100644
--- a/src/views/infra/dataSourceConfig/index.vue
+++ b/src/views/infra/dataSourceConfig/index.vue
@@ -5,6 +5,7 @@
       <el-form-item>
         <el-button
           type="primary"
+          plain
           @click="openModal('create')"
           v-hasPermi="['infra:data-source-config:create']"
         >
diff --git a/src/views/infra/file/form.vue b/src/views/infra/file/form.vue
index b0a76e0e..56dbf25f 100644
--- a/src/views/infra/file/form.vue
+++ b/src/views/infra/file/form.vue
@@ -1,5 +1,5 @@
 <template>
-  <Dialog :title="modelTitle" v-model="modelVisible">
+  <Dialog :title="dialogTitle" v-model="dialogVisible">
     <el-upload
       ref="uploadRef"
       :limit="1"
@@ -24,7 +24,7 @@
     </el-upload>
     <template #footer>
       <el-button @click="submitFileForm" type="primary" :disabled="formLoading">确 定</el-button>
-      <el-button @click="modelVisible = false">取 消</el-button>
+      <el-button @click="dialogVisible = false">取 消</el-button>
     </template>
   </Dialog>
 </template>
@@ -36,8 +36,8 @@ import { getAccessToken } from '@/utils/auth'
 const { t } = useI18n() // 国际化
 const message = useMessage() // 消息弹窗
 
-const modelVisible = ref(false) // 弹窗的是否展示
-const modelTitle = ref('') // 弹窗的标题
+const dialogVisible = ref(false) // 弹窗的是否展示
+const dialogTitle = ref('') // 弹窗的标题
 const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
 const url = import.meta.env.VITE_UPLOAD_URL
 const headers = { Authorization: 'Bearer ' + getAccessToken() }
@@ -46,8 +46,8 @@ const uploadRef = ref()
 
 /** 打开弹窗 */
 const openModal = async () => {
-  modelVisible.value = true
-  modelTitle.value = t('action.fileUpload')
+  dialogVisible.value = true
+  dialogTitle.value = t('action.fileUpload')
 }
 defineExpose({ openModal }) // 提供 openModal 方法,用于打开弹窗
 
@@ -71,7 +71,7 @@ const submitFileForm = () => {
 /** 文件上传成功处理 */
 const handleFileSuccess = () => {
   // 清理
-  modelVisible.value = false
+  dialogVisible.value = false
   formLoading.value = false
   unref(uploadRef)?.clearFiles()
   // 提示成功,并刷新
diff --git a/src/views/infra/fileConfig/form.vue b/src/views/infra/fileConfig/form.vue
index f08ba4c4..740d29ed 100644
--- a/src/views/infra/fileConfig/form.vue
+++ b/src/views/infra/fileConfig/form.vue
@@ -1,5 +1,5 @@
 <template>
-  <Dialog :title="modelTitle" v-model="modelVisible">
+  <Dialog :title="dialogTitle" v-model="dialogVisible">
     <el-form
       ref="formRef"
       :model="formData"
@@ -94,7 +94,7 @@
     </el-form>
     <template #footer>
       <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
-      <el-button @click="modelVisible = false">取 消</el-button>
+      <el-button @click="dialogVisible = false">取 消</el-button>
     </template>
   </Dialog>
 </template>
@@ -105,8 +105,8 @@ import * as FileConfigApi from '@/api/infra/fileConfig'
 const { t } = useI18n() // 国际化
 const message = useMessage() // 消息弹窗
 
-const modelVisible = ref(false) // 弹窗的是否展示
-const modelTitle = ref('') // 弹窗的标题
+const dialogVisible = ref(false) // 弹窗的是否展示
+const dialogTitle = ref('') // 弹窗的标题
 const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
 const formType = ref('') // 表单的类型:create - 新增;update - 修改
 const formData = ref({
@@ -137,8 +137,8 @@ const formRef = ref() // 表单 Ref
 
 /** 打开弹窗 */
 const openModal = async (type: string, id?: number) => {
-  modelVisible.value = true
-  modelTitle.value = t('action.' + type)
+  dialogVisible.value = true
+  dialogTitle.value = t('action.' + type)
   formType.value = type
   resetForm()
   // 修改时,设置数据
@@ -171,7 +171,7 @@ const submitForm = async () => {
       await FileConfigApi.updateFileConfig(data)
       message.success(t('common.updateSuccess'))
     }
-    modelVisible.value = false
+    dialogVisible.value = false
     // 发送操作成功的事件
     emit('success')
   } finally {
diff --git a/src/views/infra/fileConfig/index.vue b/src/views/infra/fileConfig/index.vue
index ca0fac15..245b7f5c 100644
--- a/src/views/infra/fileConfig/index.vue
+++ b/src/views/infra/fileConfig/index.vue
@@ -35,6 +35,7 @@
         <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
         <el-button
           type="primary"
+          plain
           @click="openModal('create')"
           v-hasPermi="['infra:file-config:create']"
         >
diff --git a/src/views/infra/job/JobDetail.vue b/src/views/infra/job/JobDetail.vue
new file mode 100644
index 00000000..18e4235b
--- /dev/null
+++ b/src/views/infra/job/JobDetail.vue
@@ -0,0 +1,71 @@
+<template>
+  <Dialog title="任务详细" v-model="dialogVisible" width="700px">
+    <el-descriptions border :column="1">
+      <el-descriptions-item label="任务编号" min-width="60">
+        {{ detailData.id }}
+      </el-descriptions-item>
+      <el-descriptions-item label="任务名称">
+        {{ detailData.name }}
+      </el-descriptions-item>
+      <el-descriptions-item label="任务名称">
+        <dict-tag :type="DICT_TYPE.INFRA_JOB_STATUS" :value="detailData.status" />
+      </el-descriptions-item>
+      <el-descriptions-item label="处理器的名字">
+        {{ detailData.handlerName }}
+      </el-descriptions-item>
+      <el-descriptions-item label="处理器的参数">
+        {{ detailData.handlerParam }}
+      </el-descriptions-item>
+      <el-descriptions-item label="Cron 表达式">
+        {{ detailData.cronExpression }}
+      </el-descriptions-item>
+      <el-descriptions-item label="重试次数">
+        {{ detailData.retryCount }}
+      </el-descriptions-item>
+      <el-descriptions-item label="重试间隔">
+        {{ detailData.retryInterval + ' 毫秒' }}
+      </el-descriptions-item>
+      <el-descriptions-item label="监控超时时间">
+        {{ detailData.monitorTimeout > 0 ? detailData.monitorTimeout + ' 毫秒' : '未开启' }}
+      </el-descriptions-item>
+      <el-descriptions-item label="后续执行时间">
+        <el-timeline>
+          <el-timeline-item
+            v-for="(nextTime, index) in nextTimes"
+            :key="index"
+            :timestamp="formatDate(nextTime)"
+          >
+            第 {{ index + 1 }} 次
+          </el-timeline-item>
+        </el-timeline>
+      </el-descriptions-item>
+    </el-descriptions>
+  </Dialog>
+</template>
+<script setup lang="ts">
+import { DICT_TYPE } from '@/utils/dict'
+import { formatDate } from '@/utils/formatTime'
+import * as JobApi from '@/api/infra/job'
+
+const dialogVisible = ref(false) // 弹窗的是否展示
+const detailLoading = ref(false) // 表单的加载中
+const detailData = ref({}) // 详情数据
+const nextTimes = ref([]) // 下一轮执行时间的数组
+
+/** 打开弹窗 */
+const open = async (id: number) => {
+  dialogVisible.value = true
+  // 查看,设置数据
+  if (id) {
+    detailLoading.value = true
+    try {
+      detailData.value = await JobApi.getJob(id)
+      // 获取下一次执行时间
+      nextTimes.value = await JobApi.getJobNextTimes(id)
+    } finally {
+      detailLoading.value = false
+    }
+  }
+}
+defineExpose({ open }) // 提供 open 方法,用于打开弹窗
+</script>
diff --git a/src/views/infra/job/form.vue b/src/views/infra/job/JobForm.vue
similarity index 60%
rename from src/views/infra/job/form.vue
rename to src/views/infra/job/JobForm.vue
index 24488fd7..9c03bd1c 100644
--- a/src/views/infra/job/form.vue
+++ b/src/views/infra/job/JobForm.vue
@@ -1,6 +1,5 @@
 <template>
-  <!-- 添加或修改定时任务对话框 -->
-  <Dialog :title="modelTitle" v-model="modelVisible">
+  <Dialog :title="dialogTitle" v-model="dialogVisible">
     <el-form
       ref="formRef"
       :model="formData"
@@ -22,14 +21,7 @@
         <el-input v-model="formData.handlerParam" placeholder="请输入处理器的参数" />
       </el-form-item>
       <el-form-item label="CRON 表达式" prop="cronExpression">
-        <el-input v-model="formData.cronExpression" placeholder="请输入CRON 表达式">
-          <template #append>
-            <el-button type="primary" @click="handleShowCron">
-              生成表达式
-              <i class="el-icon-time el-icon--right"></i>
-            </el-button>
-          </template>
-        </el-input>
+        <crontab v-model="formData.cronExpression" />
       </el-form-item>
       <el-form-item label="重试次数" prop="retryCount">
         <el-input
@@ -47,56 +39,28 @@
         <el-input v-model="formData.monitorTimeout" placeholder="请输入监控超时时间,单位:毫秒" />
       </el-form-item>
     </el-form>
-    <!-- 操作按钮 -->
     <template #footer>
-      <!-- 按钮:保存 -->
-      <div class="dialog-footer">
-        <el-button type="primary" @click="submitForm" :loading="formLoading">确 定</el-button>
-        <el-button @click="modelVisible = false">取 消</el-button>
-      </div>
+      <el-button type="primary" @click="submitForm" :loading="formLoading">确 定</el-button>
+      <el-button @click="dialogVisible = false">取 消</el-button>
     </template>
   </Dialog>
-  <el-dialog
-    title="Cron表达式生成器"
-    v-model="openCron"
-    append-to-body
-    class="scrollbar"
-    destroy-on-close
-  >
-    <crontab @hide="openCron = false" @fill="crontabFill" :expression="expression" />
-  </el-dialog>
 </template>
 <script setup lang="ts" name="JobForm">
 import * as JobApi from '@/api/infra/job'
-
-const emit = defineEmits(['success', 'crontabFill']) // 定义 success 事件,用于操作成功后的回调
-
 const { t } = useI18n() // 国际化
 const message = useMessage() // 消息弹窗
 
-const modelVisible = ref(false) // 弹窗的是否展示
-const modelTitle = ref('') // 弹窗的标题
+const dialogVisible = ref(false) // 弹窗的是否展示
+const dialogTitle = ref('') // 弹窗的标题
 const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
 const formType = ref('') // 表单的类型:create - 新增;update - 修改
-const defaultFormData = {
+const formData = ref({
   id: undefined,
   name: '',
-  status: 0,
   handlerName: '',
   handlerParam: '',
-  cronExpression: '',
-  retryCount: 0,
-  retryInterval: 0,
-  monitorTimeout: 0,
-  createTime: new Date()
-}
-const formData = ref({ ...defaultFormData })
-
-// 是否显示Cron表达式弹出层
-const openCron = ref(false)
-// 传入的表达式
-const expression = ref('')
-// 表单校验
+  cronExpression: ''
+})
 const formRules = reactive({
   name: [{ required: true, message: '任务名称不能为空', trigger: 'blur' }],
   handlerName: [{ required: true, message: '处理器的名字不能为空', trigger: 'blur' }],
@@ -107,37 +71,25 @@ const formRules = reactive({
 const formRef = ref() // 表单 Ref
 
 /** 打开弹窗 */
-const openModal = async (type: string, id?: number) => {
-  modelVisible.value = true
-  modelTitle.value = t('action.' + type)
+const open = async (type: string, id?: number) => {
+  dialogVisible.value = true
+  dialogTitle.value = t('action.' + type)
   formType.value = type
   resetForm()
   // 修改时,设置数据
   if (id) {
     formLoading.value = true
     try {
-      formData.value = await JobApi.getJobApi(id)
+      formData.value = await JobApi.getJob(id)
     } finally {
       formLoading.value = false
     }
   }
 }
-defineExpose({ openModal }) // 提供 openModal 方法,用于打开弹窗
+defineExpose({ open }) // 提供 open 方法,用于打开弹窗
 
-/** cron表达式按钮操作 */
-const handleShowCron = () => {
-  console.info(123333333333)
-  expression.value = formData.value.cronExpression
-  openCron.value = true
-}
-
-// cron表达式填充
-const crontabFill = (expression: string) => {
-  formData.value.cronExpression = expression
-  emit('crontabFill', expression)
-}
-
-// 提交按钮
+/** 提交按钮 */
+const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
 const submitForm = async () => {
   // 校验表单
   if (!formRef) return
@@ -148,13 +100,13 @@ const submitForm = async () => {
   try {
     const data = formData.value as unknown as JobApi.JobVO
     if (formType.value === 'create') {
-      await JobApi.createJobApi(data)
+      await JobApi.createJob(data)
       message.success(t('common.createSuccess'))
     } else {
-      await JobApi.updateJobApi(data)
+      await JobApi.updateJob(data)
       message.success(t('common.updateSuccess'))
     }
-    modelVisible.value = false
+    dialogVisible.value = false
     // 发送操作成功的事件
     emit('success')
   } finally {
@@ -165,7 +117,11 @@ const submitForm = async () => {
 /** 重置表单 */
 const resetForm = () => {
   formData.value = {
-    ...defaultFormData
+    id: undefined,
+    name: '',
+    handlerName: '',
+    handlerParam: '',
+    cronExpression: ''
   }
   formRef.value?.resetFields()
 }
diff --git a/src/views/infra/job/JobLogView.vue b/src/views/infra/job/JobLogView.vue
deleted file mode 100644
index c66e0d80..00000000
--- a/src/views/infra/job/JobLogView.vue
+++ /dev/null
@@ -1,74 +0,0 @@
-<template>
-  <!-- 调度日志详细 -->
-  <Dialog title="调度日志详细" v-model="modelVisible" width="700px" append-to-body>
-    <el-form ref="form" :model="formData" label-width="120px" size="mini">
-      <el-row>
-        <el-col :span="12">
-          <el-form-item label="日志编号:">{{ formData.id }}</el-form-item>
-          <el-form-item label="任务编号:">{{ formData.jobId }}</el-form-item>
-          <el-form-item label="处理器的名字:">{{ formData.handlerName }}</el-form-item>
-          <el-form-item label="处理器的参数:">{{ formData.handlerParam }}</el-form-item>
-          <el-form-item label="第几次执行:">{{ formData.executeIndex }}</el-form-item>
-          <el-form-item label="执行时间:">{{
-            parseTime(formData.beginTime) + ' ~ ' + parseTime(formData.endTime)
-          }}</el-form-item>
-          <el-form-item label="执行时长:">{{ formData.duration + ' 毫秒' }}</el-form-item>
-          <el-form-item label="任务状态:">
-            <dict-tag :type="DICT_TYPE.INFRA_JOB_LOG_STATUS" :value="formData.status" />
-          </el-form-item>
-          <el-form-item label="执行结果:">{{ formData.result }}</el-form-item>
-        </el-col>
-      </el-row>
-    </el-form>
-    <template #footer>
-      <div class="dialog-footer">
-        <el-button @click="close">关 闭</el-button>
-      </div>
-    </template>
-  </Dialog>
-</template>
-<script setup lang="ts" name="JobView">
-import * as JobLogApi from '@/api/infra/jobLog'
-import { DICT_TYPE } from '@/utils/dict'
-import { parseTime } from './utils'
-
-const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
-
-const { t } = useI18n() // 国际化
-
-const modelVisible = ref(false) // 弹窗的是否展示
-const modelTitle = ref('') // 弹窗的标题
-const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
-const formData = ref({
-  id: undefined,
-  jobId: undefined,
-  handlerParam: '',
-  handlerName: '',
-  executeIndex: '',
-  beginTime: undefined,
-  endTime: undefined,
-  duration: true,
-  result: '',
-  status: undefined
-})
-
-/** 打开弹窗 */
-const openModal = async (id?: number) => {
-  modelVisible.value = true
-  modelTitle.value = t('action.detail')
-  // 查看,设置数据
-  if (id) {
-    formLoading.value = true
-    try {
-      formData.value = await JobLogApi.getJobLogApi(id)
-    } finally {
-      formLoading.value = false
-    }
-  }
-}
-defineExpose({ openModal }) // 提供 openModal 方法,用于打开弹窗
-
-const close = () => {
-  emit('success')
-}
-</script>
diff --git a/src/views/infra/job/index.vue b/src/views/infra/job/index.vue
index 702b31fe..e113878a 100644
--- a/src/views/infra/job/index.vue
+++ b/src/views/infra/job/index.vue
@@ -1,19 +1,31 @@
 <template>
   <content-wrap>
-    <!-- 搜索栏 -->
-    <el-form :model="queryParams" ref="queryFormRef" :inline="true" label-width="100px">
+    <!-- 搜索工作栏 -->
+    <el-form
+      class="-mb-15px"
+      :model="queryParams"
+      ref="queryFormRef"
+      :inline="true"
+      label-width="100px"
+    >
       <el-form-item label="任务名称" prop="name">
         <el-input
           v-model="queryParams.name"
           placeholder="请输入任务名称"
           clearable
           @keyup.enter="handleQuery"
+          class="!w-240px"
         />
       </el-form-item>
       <el-form-item label="任务状态" prop="status">
-        <el-select v-model="queryParams.status" placeholder="请选择任务状态" clearable>
+        <el-select
+          v-model="queryParams.status"
+          placeholder="请选择任务状态"
+          clearable
+          class="!w-240px"
+        >
           <el-option
-            v-for="dict in getDictOptions(DICT_TYPE.INFRA_JOB_STATUS)"
+            v-for="dict in getIntDictOptions(DICT_TYPE.INFRA_JOB_STATUS)"
             :key="dict.value"
             :label="dict.label"
             :value="dict.value"
@@ -26,6 +38,7 @@
           placeholder="请输入处理器的名字"
           clearable
           @keyup.enter="handleQuery"
+          class="!w-240px"
         />
       </el-form-item>
       <el-form-item>
@@ -34,7 +47,7 @@
         <el-button
           type="primary"
           plain
-          @click="openModal('create')"
+          @click="openForm('create')"
           v-hasPermi="['infra:job:create']"
         >
           <Icon icon="ep:plus" class="mr-5px" /> 新增
@@ -48,63 +61,66 @@
         >
           <Icon icon="ep:download" class="mr-5px" /> 导出
         </el-button>
-
         <el-button type="info" plain @click="handleJobLog" v-hasPermi="['infra:job:query']">
           <Icon icon="ep:zoom-in" class="mr-5px" /> 执行日志
         </el-button>
       </el-form-item>
     </el-form>
+  </content-wrap>
 
+  <!-- 列表 -->
+  <content-wrap>
     <el-table v-loading="loading" :data="list">
       <el-table-column label="任务编号" align="center" prop="id" />
       <el-table-column label="任务名称" align="center" prop="name" />
       <el-table-column label="任务状态" align="center" prop="status">
         <template #default="scope">
           <dict-tag :type="DICT_TYPE.INFRA_JOB_STATUS" :value="scope.row.status" />
-        </template> </el-table-column
-      >>
+        </template>
+      </el-table-column>
       <el-table-column label="处理器的名字" align="center" prop="handlerName" />
       <el-table-column label="处理器的参数" align="center" prop="handlerParam" />
       <el-table-column label="CRON 表达式" align="center" prop="cronExpression" />
-      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+      <el-table-column label="操作" align="center" width="200">
         <template #default="scope">
           <el-button
+            type="primary"
             link
-            icon="el-icon-edit"
-            @click="openModal('update', scope.row.id)"
+            @click="openForm('update', scope.row.id)"
             v-hasPermi="['infra:job:update']"
-            >修改</el-button
           >
+            修改
+          </el-button>
           <el-button
+            type="primary"
             link
-            icon="el-icon-check"
             @click="handleChangeStatus(scope.row)"
             v-hasPermi="['infra:job:update']"
-            >{{ scope.row.status === InfraJobStatusEnum.STOP ? '开启' : '暂停' }}</el-button
           >
+            {{ scope.row.status === InfraJobStatusEnum.STOP ? '开启' : '暂停' }}
+          </el-button>
           <el-button
+            type="danger"
             link
-            icon="el-icon-delete"
             @click="handleDelete(scope.row)"
             v-hasPermi="['infra:job:delete']"
-            >删除</el-button
           >
+            删除
+          </el-button>
           <el-dropdown
-            class="mt-1"
-            :teleported="true"
             @command="(command) => handleCommand(command, scope.row)"
             v-hasPermi="['infra:job:trigger', 'infra:job:query']"
           >
-            <el-button link icon="el-icon-d-arrow-right">更多</el-button>
+            <el-button type="primary" link><Icon icon="ep:d-arrow-right" /> 更多</el-button>
             <template #dropdown>
               <el-dropdown-menu>
-                <el-dropdown-item command="handleRun" v-if="hasPermi(['infra:job:trigger'])">
+                <el-dropdown-item command="handleRun" v-if="checkPermi(['infra:job:trigger'])">
                   执行一次
                 </el-dropdown-item>
-                <el-dropdown-item command="handleView" v-if="hasPermi(['infra:job:query'])">
+                <el-dropdown-item command="openDetail" v-if="checkPermi(['infra:job:query'])">
                   任务详细
                 </el-dropdown-item>
-                <el-dropdown-item command="handleJobLog" v-if="hasPermi(['infra:job:query'])">
+                <el-dropdown-item command="handleJobLog" v-if="checkPermi(['infra:job:query'])">
                   调度日志
                 </el-dropdown-item>
               </el-dropdown-menu>
@@ -114,8 +130,7 @@
       </el-table-column>
     </el-table>
     <!-- 分页组件 -->
-    <pagination
-      v-show="total > 0"
+    <Pagination
       :total="total"
       v-model:page="queryParams.pageNo"
       v-model:limit="queryParams.pageSize"
@@ -124,23 +139,21 @@
   </content-wrap>
 
   <!-- 表单弹窗:添加/修改 -->
-  <job-form ref="modalRef" @success="getList" />
+  <JobForm ref="formRef" @success="getList" />
   <!-- 表单弹窗:查看 -->
-  <job-view ref="viewModalRef" @success="getList" />
+  <JobDetail ref="detailRef" />
 </template>
-
 <script setup lang="ts" name="Job">
-import { DICT_TYPE, getDictOptions } from '@/utils/dict'
-import JobForm from './form.vue'
-import JobView from './view.vue'
+import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
+import { checkPermi } from '@/utils/permission'
+import JobForm from './JobForm.vue'
+import JobDetail from './JobDetail.vue'
 import download from '@/utils/download'
 import * as JobApi from '@/api/infra/job'
 import { InfraJobStatusEnum } from '@/utils/constants'
-import { CACHE_KEY, useCache } from '@/hooks/web/useCache'
-
 const { t } = useI18n() // 国际化
 const message = useMessage() // 消息弹窗
-const { push } = useRouter()
+const { push } = useRouter() // 路由
 
 const loading = ref(true) // 列表的加载中
 const total = ref(0) // 列表的总页数
@@ -155,11 +168,11 @@ const queryParams = reactive({
 const queryFormRef = ref() // 搜索的表单
 const exportLoading = ref(false) // 导出的加载中
 
-/** 查询参数列表 */
+/** 查询列表 */
 const getList = async () => {
   loading.value = true
   try {
-    const data = await JobApi.getJobPageApi(queryParams)
+    const data = await JobApi.getJobPage(queryParams)
     list.value = data.list
     total.value = data.total
   } finally {
@@ -167,30 +180,6 @@ const getList = async () => {
   }
 }
 
-const handleChangeStatus = async (row: JobApi.JobVO) => {
-  const text = row.status === InfraJobStatusEnum.STOP ? '开启' : '关闭'
-
-  const status =
-    row.status === InfraJobStatusEnum.STOP ? InfraJobStatusEnum.NORMAL : InfraJobStatusEnum.STOP
-  message
-    .confirm('确认要' + text + '定时任务编号为"' + row.id + '"的数据项?', t('common.reminder'))
-    .then(async () => {
-      row.status =
-        row.status === InfraJobStatusEnum.NORMAL
-          ? InfraJobStatusEnum.NORMAL
-          : InfraJobStatusEnum.STOP
-      await JobApi.updateJobStatusApi(row.id, status)
-      message.success(text + '成功')
-      await getList()
-    })
-    .catch(() => {
-      row.status =
-        row.status === InfraJobStatusEnum.NORMAL
-          ? InfraJobStatusEnum.STOP
-          : InfraJobStatusEnum.NORMAL
-    })
-}
-
 /** 搜索按钮操作 */
 const handleQuery = () => {
   queryParams.pageNo = 1
@@ -203,10 +192,47 @@ const resetQuery = () => {
   handleQuery()
 }
 
+/** 导出按钮操作 */
+const handleExport = async () => {
+  try {
+    // 导出的二次确认
+    await message.exportConfirm()
+    // 发起导出
+    exportLoading.value = true
+    const data = await JobApi.exportJob(queryParams)
+    download.excel(data, '定时任务.xls')
+  } catch {
+  } finally {
+    exportLoading.value = false
+  }
+}
+
 /** 添加/修改操作 */
-const modalRef = ref()
-const openModal = (type: string, id?: number) => {
-  modalRef.value.openModal(type, id)
+const formRef = ref()
+const openForm = (type: string, id?: number) => {
+  formRef.value.open(type, id)
+}
+
+/** 修改状态操作 */
+const handleChangeStatus = async (row: JobApi.JobVO) => {
+  try {
+    // 修改状态的二次确认
+    const text = row.status === InfraJobStatusEnum.STOP ? '开启' : '关闭'
+    await message.confirm(
+      '确认要' + text + '定时任务编号为"' + row.id + '"的数据项?',
+      t('common.reminder')
+    )
+    const status =
+      row.status === InfraJobStatusEnum.STOP ? InfraJobStatusEnum.NORMAL : InfraJobStatusEnum.STOP
+    await JobApi.updateJobStatus(row.id, status)
+    message.success(text + '成功')
+    // 刷新列表
+    await getList()
+  } catch {
+    // 取消后,进行恢复按钮
+    row.status =
+      row.status === InfraJobStatusEnum.NORMAL ? InfraJobStatusEnum.STOP : InfraJobStatusEnum.NORMAL
+  }
 }
 
 /** 删除按钮操作 */
@@ -215,43 +241,21 @@ const handleDelete = async (id: number) => {
     // 删除的二次确认
     await message.delConfirm()
     // 发起删除
-    await JobApi.deleteJobApi(id)
+    await JobApi.deleteJob(id)
     message.success(t('common.delSuccess'))
     // 刷新列表
     await getList()
   } catch {}
 }
 
-/** 查看操作 */
-const viewModalRef = ref()
-const handleView = (rowId?: number) => {
-  viewModalRef.value.openModal(rowId)
-}
-// 执行日志
-const handleJobLog = (rowId?: number) => {
-  if (rowId) {
-    push('/job/job-log?id=' + rowId)
-  } else {
-    push('/job/job-log')
-  }
-}
-// 执行一次
-const handleRun = (row: JobApi.JobVO) => {
-  message.confirm('确认要立即执行一次' + row.name + '?', t('common.reminder')).then(async () => {
-    await JobApi.runJobApi(row.id)
-    message.success('执行成功')
-    await getList()
-  })
-}
-
 /** '更多'操作按钮 */
 const handleCommand = (command, row) => {
   switch (command) {
     case 'handleRun':
       handleRun(row)
       break
-    case 'handleView':
-      handleView(row?.id)
+    case 'openDetail':
+      openDetail(row.id)
       break
     case 'handleJobLog':
       handleJobLog(row?.id)
@@ -261,36 +265,32 @@ const handleCommand = (command, row) => {
   }
 }
 
-/** 导出按钮操作 */
-const handleExport = async () => {
+/** 执行一次 */
+const handleRun = async (row: JobApi.JobVO) => {
   try {
-    // 导出的二次确认
-    await message.exportConfirm()
-    // 发起导出
-    exportLoading.value = true
-    const data = await JobApi.exportJobApi(queryParams)
-    download.excel(data, '定时任务.xls')
-  } catch {
-  } finally {
-    exportLoading.value = false
-  }
+    // 二次确认
+    await message.confirm('确认要立即执行一次' + row.name + '?', t('common.reminder'))
+    // 提交执行
+    await JobApi.runJobApi(row.id)
+    message.success('执行成功')
+    // 刷新列表
+    await getList()
+  } catch {}
 }
 
-// 权限判断:dropdown 与 v-hasPermi有冲突会造成大量的waring,改用v-if调用此方法
-const hasPermi = (permiKeys: string[]) => {
-  const { wsCache } = useCache()
-  const all_permission = '*:*:*'
-  const permissions = wsCache.get(CACHE_KEY.USER).permissions
+/** 查看操作 */
+const detailRef = ref()
+const openDetail = (id: number) => {
+  detailRef.value.open(id)
+}
 
-  if (permiKeys && permiKeys instanceof Array && permiKeys.length > 0) {
-    const permissionFlag = permiKeys
-
-    const hasPermissions = permissions.some((permission: string) => {
-      return all_permission === permission || permissionFlag.includes(permission)
-    })
-    return hasPermissions
+/** 跳转执行日志 */
+const handleJobLog = (id: number) => {
+  if (id) {
+    push('/job/job-log?id=' + id)
+  } else {
+    push('/job/job-log')
   }
-  return false
 }
 
 /** 初始化 **/
diff --git a/src/views/infra/job/logger/JobLogDetail.vue b/src/views/infra/job/logger/JobLogDetail.vue
new file mode 100644
index 00000000..3b8795d9
--- /dev/null
+++ b/src/views/infra/job/logger/JobLogDetail.vue
@@ -0,0 +1,57 @@
+<template>
+  <Dialog title="任务详细" v-model="dialogVisible" width="700px">
+    <el-descriptions border :column="1">
+      <el-descriptions-item label="日志编号" min-width="60">
+        {{ detailData.id }}
+      </el-descriptions-item>
+      <el-descriptions-item label="任务编号">
+        {{ detailData.jobId }}
+      </el-descriptions-item>
+      <el-descriptions-item label="处理器的名字">
+        {{ detailData.handlerName }}
+      </el-descriptions-item>
+      <el-descriptions-item label="处理器的参数">
+        {{ detailData.handlerParam }}
+      </el-descriptions-item>
+      <el-descriptions-item label="第几次执行">
+        {{ detailData.executeIndex }}
+      </el-descriptions-item>
+      <el-descriptions-item label="执行时间">
+        {{ formatDate(detailData.beginTime) + ' ~ ' + formatDate(detailData.endTime) }}
+      </el-descriptions-item>
+      <el-descriptions-item label="执行时长">
+        {{ detailData.duration + ' 毫秒' }}
+      </el-descriptions-item>
+      <el-descriptions-item label="任务状态">
+        <dict-tag :type="DICT_TYPE.INFRA_JOB_LOG_STATUS" :value="detailData.status" />
+      </el-descriptions-item>
+      <el-descriptions-item label="执行结果">
+        {{ detailData.duration + ' result' }}
+      </el-descriptions-item>
+    </el-descriptions>
+  </Dialog>
+</template>
+<script setup lang="ts">
+import { DICT_TYPE } from '@/utils/dict'
+import { formatDate } from '@/utils/formatTime'
+import * as JobLogApi from '@/api/infra/jobLog'
+
+const dialogVisible = ref(false) // 弹窗的是否展示
+const detailLoading = ref(false) // 表单的加载中
+const detailData = ref({}) // 详情数据
+
+/** 打开弹窗 */
+const open = async (id: number) => {
+  dialogVisible.value = true
+  // 查看,设置数据
+  if (id) {
+    detailLoading.value = true
+    try {
+      detailData.value = await JobLogApi.getJobLog(id)
+    } finally {
+      detailLoading.value = false
+    }
+  }
+}
+defineExpose({ open }) // 提供 open 方法,用于打开弹窗
+</script>
diff --git a/src/views/infra/job/JobLog.vue b/src/views/infra/job/logger/index.vue
similarity index 74%
rename from src/views/infra/job/JobLog.vue
rename to src/views/infra/job/logger/index.vue
index daa20046..f55a0647 100644
--- a/src/views/infra/job/JobLog.vue
+++ b/src/views/infra/job/logger/index.vue
@@ -1,37 +1,52 @@
 <template>
   <content-wrap>
-    <!-- 搜索栏 -->
-    <el-form :model="queryParams" ref="queryFormRef" :inline="true" label-width="120px">
+    <!-- 搜索工作栏 -->
+    <el-form
+      class="-mb-15px"
+      :model="queryParams"
+      ref="queryFormRef"
+      :inline="true"
+      label-width="120px"
+    >
       <el-form-item label="处理器的名字" prop="handlerName">
         <el-input
           v-model="queryParams.handlerName"
           placeholder="请输入处理器的名字"
           clearable
           @keyup.enter="handleQuery"
+          class="!w-240px"
         />
       </el-form-item>
       <el-form-item label="开始执行时间" prop="beginTime">
         <el-date-picker
-          clearable
           v-model="queryParams.beginTime"
           type="date"
-          value-format="YYYY-MM-DD"
+          value-format="YYYY-MM-DD HH:mm:ss"
           placeholder="选择开始执行时间"
+          clearable
+          class="!w-240px"
         />
       </el-form-item>
       <el-form-item label="结束执行时间" prop="endTime">
         <el-date-picker
-          clearable
           v-model="queryParams.endTime"
           type="date"
-          value-format="YYYY-MM-DD"
+          value-format="YYYY-MM-DD HH:mm:ss"
           placeholder="选择结束执行时间"
+          clearable
+          :default-time="new Date('1 23:59:59')"
+          class="!w-240px"
         />
       </el-form-item>
       <el-form-item label="任务状态" prop="status">
-        <el-select v-model="queryParams.status" placeholder="请选择任务状态" clearable>
+        <el-select
+          v-model="queryParams.status"
+          placeholder="请选择任务状态"
+          clearable
+          class="!w-240px"
+        >
           <el-option
-            v-for="dict in getDictOptions(DICT_TYPE.INFRA_JOB_LOG_STATUS)"
+            v-for="dict in getIntDictOptions(DICT_TYPE.INFRA_JOB_LOG_STATUS)"
             :key="dict.value"
             :label="dict.label"
             :value="dict.value"
@@ -52,16 +67,19 @@
         </el-button>
       </el-form-item>
     </el-form>
+  </content-wrap>
 
+  <!-- 列表 -->
+  <content-wrap>
     <el-table v-loading="loading" :data="list">
       <el-table-column label="日志编号" align="center" prop="id" />
       <el-table-column label="任务编号" align="center" prop="jobId" />
       <el-table-column label="处理器的名字" align="center" prop="handlerName" />
       <el-table-column label="处理器的参数" align="center" prop="handlerParam" />
       <el-table-column label="第几次执行" align="center" prop="executeIndex" />
-      <el-table-column label="执行时间" align="center" width="180">
+      <el-table-column label="执行时间" align="center" width="170s">
         <template #default="scope">
-          <span>{{ parseTime(scope.row.beginTime) + ' ~ ' + parseTime(scope.row.endTime) }}</span>
+          <span>{{ formatDate(scope.row.beginTime) + ' ~ ' + formatDate(scope.row.endTime) }}</span>
         </template>
       </el-table-column>
       <el-table-column label="执行时长" align="center" prop="duration">
@@ -74,40 +92,39 @@
           <dict-tag :type="DICT_TYPE.INFRA_JOB_LOG_STATUS" :value="scope.row.status" />
         </template>
       </el-table-column>
-      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+      <el-table-column label="操作" align="center">
         <template #default="scope">
           <el-button
+            type="primary"
             link
-            icon="el-icon-view"
-            @click="handleView(scope.row.id)"
-            :loading="exportLoading"
+            @click="openDetail(scope.row.id)"
             v-hasPermi="['infra:job:query']"
-            >详细
+          >
+            详细
           </el-button>
         </template>
       </el-table-column>
     </el-table>
-
-    <pagination
-      v-show="total > 0"
+    <!-- 分页组件 -->
+    <Pagination
       :total="total"
       v-model:page="queryParams.pageNo"
       v-model:limit="queryParams.pageSize"
       @pagination="getList"
     />
   </content-wrap>
+
   <!-- 表单弹窗:查看 -->
-  <log-view ref="viewModalRef" @success="getList" />
+  <JobLogDetail ref="detailRef" />
 </template>
-
 <script setup lang="ts" name="JobLog">
-import { DICT_TYPE, getDictOptions } from '@/utils/dict'
+import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
+import { formatDate } from '@/utils/formatTime'
 import download from '@/utils/download'
-import LogView from './JobLogView.vue'
+import JobLogDetail from './JobLogDetail.vue'
 import * as JobLogApi from '@/api/infra/jobLog'
-import { parseTime } from './utils'
-
 const message = useMessage() // 消息弹窗
+const { query } = useRoute() // 查询参数
 
 const loading = ref(true) // 列表的加载中
 const total = ref(0) // 列表的总页数
@@ -115,6 +132,7 @@ const list = ref([]) // 列表的数据
 const queryParams = reactive({
   pageNo: 1,
   pageSize: 10,
+  jobId: query.id,
   handlerName: undefined,
   beginTime: undefined,
   endTime: undefined,
@@ -123,15 +141,11 @@ const queryParams = reactive({
 const queryFormRef = ref() // 搜索的表单
 const exportLoading = ref(false) // 导出的加载中
 
-/** 查询参数列表 */
+/** 查询列表 */
 const getList = async () => {
   loading.value = true
   try {
-    const data = await JobLogApi.getJobLogPageApi({
-      ...queryParams,
-      beginTime: queryParams.beginTime ? queryParams.beginTime + ' 00:00:00' : undefined,
-      endTime: queryParams.endTime ? queryParams.endTime + ' 23:59:59' : undefined
-    })
+    const data = await JobLogApi.getJobLogPage(queryParams)
     list.value = data.list
     total.value = data.total
   } finally {
@@ -152,9 +166,9 @@ const resetQuery = () => {
 }
 
 /** 查看操作 */
-const viewModalRef = ref()
-const handleView = (rowId?: number) => {
-  viewModalRef.value.openModal(rowId)
+const detailRef = ref()
+const openDetail = (rowId?: number) => {
+  detailRef.value.open(rowId)
 }
 
 /** 导出按钮操作 */
@@ -164,7 +178,7 @@ const handleExport = async () => {
     await message.exportConfirm()
     // 发起导出
     exportLoading.value = true
-    const data = await JobLogApi.exportJobLogApi(queryParams)
+    const data = await JobLogApi.exportJobLog(queryParams)
     download.excel(data, '定时任务执行日志.xls')
   } catch {
   } finally {
diff --git a/src/views/infra/job/utils.ts b/src/views/infra/job/utils.ts
deleted file mode 100644
index a3774f22..00000000
--- a/src/views/infra/job/utils.ts
+++ /dev/null
@@ -1,44 +0,0 @@
-export const parseTime = (time) => {
-  if (!time) {
-    return null
-  }
-  const format = '{y}-{m}-{d} {h}:{i}:{s}'
-  let date
-  if (typeof time === 'object') {
-    date = time
-  } else {
-    if (typeof time === 'string' && /^[0-9]+$/.test(time)) {
-      time = parseInt(time)
-    } else if (typeof time === 'string') {
-      time = time
-        .replace(new RegExp(/-/gm), '/')
-        .replace('T', ' ')
-        .replace(new RegExp(/\.[\d]{3}/gm), '')
-    }
-    if (typeof time === 'number' && time.toString().length === 10) {
-      time = time * 1000
-    }
-    date = new Date(time)
-  }
-  const formatObj = {
-    y: date.getFullYear(),
-    m: date.getMonth() + 1,
-    d: date.getDate(),
-    h: date.getHours(),
-    i: date.getMinutes(),
-    s: date.getSeconds(),
-    a: date.getDay()
-  }
-  const time_str = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => {
-    let value = formatObj[key]
-    // Note: getDay() returns 0 on Sunday
-    if (key === 'a') {
-      return ['日', '一', '二', '三', '四', '五', '六'][value]
-    }
-    if (result.length > 0 && value < 10) {
-      value = '0' + value
-    }
-    return value || 0
-  })
-  return time_str
-}
diff --git a/src/views/infra/job/view.vue b/src/views/infra/job/view.vue
deleted file mode 100644
index d195e0e3..00000000
--- a/src/views/infra/job/view.vue
+++ /dev/null
@@ -1,89 +0,0 @@
-<template>
-  <!-- 任务详细 -->
-  <Dialog title="任务详细" v-model="modelVisible" width="700px" append-to-body>
-    <el-form ref="formRef" :model="formData" label-width="200px">
-      <el-row>
-        <el-col :span="24">
-          <el-form-item label="任务编号:">{{ formData.id }}</el-form-item>
-          <el-form-item label="任务名称:">{{ formData.name }}</el-form-item>
-          <el-form-item label="任务名称:">
-            <dict-tag :type="DICT_TYPE.INFRA_JOB_STATUS" :value="formData.status" />
-          </el-form-item>
-          <el-form-item label="处理器的名字:">{{ formData.handlerName }}</el-form-item>
-          <el-form-item label="处理器的参数:">{{ formData.handlerParam }}</el-form-item>
-          <el-form-item label="cron表达式:">{{ formData.cronExpression }}</el-form-item>
-          <el-form-item label="重试次数:">{{ formData.retryCount }}</el-form-item>
-          <el-form-item label="重试间隔:">{{ formData.retryInterval + ' 毫秒' }}</el-form-item>
-          <el-form-item label="监控超时时间:">{{
-            formData.monitorTimeout > 0 ? formData.monitorTimeout + ' 毫秒' : '未开启'
-          }}</el-form-item>
-          <el-form-item label="后续执行时间:">
-            <el-timeline class="pt-3">
-              <el-timeline-item
-                v-for="(activity, index) in nextTimes"
-                :key="index"
-                :timestamp="parseTime(activity)"
-              >
-                第{{ index + 1 }}次
-              </el-timeline-item>
-            </el-timeline>
-          </el-form-item>
-        </el-col>
-      </el-row>
-    </el-form>
-    <template #footer>
-      <div class="dialog-footer">
-        <el-button @click="close">关 闭</el-button>
-      </div>
-    </template>
-  </Dialog>
-</template>
-<script setup lang="ts" name="JobView">
-import * as JobApi from '@/api/infra/job'
-import { parseTime } from './utils'
-import { DICT_TYPE } from '@/utils/dict'
-
-const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
-
-const { t } = useI18n() // 国际化
-
-const formRef = ref() // 表单 Ref
-const modelVisible = ref(false) // 弹窗的是否展示
-const modelTitle = ref('') // 弹窗的标题
-const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
-const formData = ref({
-  id: undefined,
-  name: '',
-  handlerParam: '',
-  handlerName: '',
-  cronExpression: '',
-  retryCount: true,
-  retryInterval: '',
-  monitorTimeout: 0,
-  status: 0
-})
-const nextTimes = ref([])
-
-/** 打开弹窗 */
-const openModal = async (id?: number) => {
-  modelVisible.value = true
-  modelTitle.value = t('action.detail')
-  // 查看,设置数据
-  if (id) {
-    formLoading.value = true
-    try {
-      formData.value = await JobApi.getJobApi(id)
-      // 获取下一次执行时间
-      nextTimes.value = await JobApi.getJobNextTimesApi(id)
-    } finally {
-      formLoading.value = false
-    }
-  }
-}
-defineExpose({ openModal }) // 提供 openModal 方法,用于打开弹窗
-
-const close = () => {
-  modelVisible.value = false
-  emit('success')
-}
-</script>
diff --git a/src/views/mall/product/category/CategoryForm.vue b/src/views/mall/product/category/CategoryForm.vue
new file mode 100644
index 00000000..db395a66
--- /dev/null
+++ b/src/views/mall/product/category/CategoryForm.vue
@@ -0,0 +1,147 @@
+<template>
+  <Dialog :title="dialogTitle" v-model="dialogVisible">
+    <el-form
+      ref="formRef"
+      :model="formData"
+      :rules="formRules"
+      label-width="80px"
+      v-loading="formLoading"
+    >
+      <el-form-item label="上级分类" prop="parentId">
+        <el-tree-select
+          v-model="formData.parentId"
+          :data="categoryTree"
+          :props="{ label: 'name', value: 'id' }"
+          :render-after-expand="false"
+          placeholder="请选择上级分类"
+          check-strictly
+          default-expand-all
+        />
+      </el-form-item>
+      <el-form-item label="分类名称" prop="name">
+        <el-input v-model="formData.name" placeholder="请输入分类名称" />
+      </el-form-item>
+      <el-form-item label="分类图片" prop="picUrl">
+        <UploadImg v-model="formData.picUrl" :limit="1" :is-show-tip="false" />
+        <div v-if="formData.parentId === 0" style="font-size: 10px">推荐 200x100 图片分辨率</div>
+        <div v-else style="font-size: 10px">推荐 100x100 图片分辨率</div>
+      </el-form-item>
+      <el-form-item label="分类排序" prop="sort">
+        <el-input-number v-model="formData.sort" controls-position="right" :min="0" />
+      </el-form-item>
+      <el-form-item label="开启状态" prop="status">
+        <el-radio-group v-model="formData.status">
+          <el-radio
+            v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)"
+            :key="dict.value"
+            :label="dict.value"
+          >
+            {{ dict.label }}
+          </el-radio>
+        </el-radio-group>
+      </el-form-item>
+      <el-form-item label="分类描述">
+        <el-input v-model="formData.description" type="textarea" placeholder="请输入分类描述" />
+      </el-form-item>
+    </el-form>
+    <template #footer>
+      <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
+      <el-button @click="dialogVisible = false">取 消</el-button>
+    </template>
+  </Dialog>
+</template>
+<script setup lang="ts">
+import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
+import { CommonStatusEnum } from '@/utils/constants'
+import { handleTree } from '@/utils/tree'
+import * as ProductCategoryApi from '@/api/mall/product/category'
+const { t } = useI18n() // 国际化
+const message = useMessage() // 消息弹窗
+
+const dialogVisible = ref(false) // 弹窗的是否展示
+const dialogTitle = ref('') // 弹窗的标题
+const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
+const formType = ref('') // 表单的类型:create - 新增;update - 修改
+const formData = ref({
+  id: undefined,
+  name: '',
+  picUrl: '',
+  status: CommonStatusEnum.ENABLE,
+  description: ''
+})
+const formRules = reactive({
+  parentId: [{ required: true, message: '请选择上级分类', trigger: 'blur' }],
+  name: [{ required: true, message: '分类名称不能为空', trigger: 'blur' }],
+  picUrl: [{ required: true, message: '分类图片不能为空', trigger: 'blur' }],
+  sort: [{ required: true, message: '分类排序不能为空', trigger: 'blur' }],
+  status: [{ required: true, message: '开启状态不能为空', trigger: 'blur' }]
+})
+const formRef = ref() // 表单 Ref
+const categoryTree = ref<any[]>([]) // 分类树
+
+/** 打开弹窗 */
+const open = async (type: string, id?: number) => {
+  dialogVisible.value = true
+  dialogTitle.value = t('action.' + type)
+  formType.value = type
+  resetForm()
+  // 修改时,设置数据
+  if (id) {
+    formLoading.value = true
+    try {
+      formData.value = await ProductCategoryApi.getCategory(id)
+    } finally {
+      formLoading.value = false
+    }
+  }
+  // 获得分类树
+  await getTree()
+}
+defineExpose({ open }) // 提供 open 方法,用于打开弹窗
+
+/** 提交表单 */
+const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
+const submitForm = async () => {
+  // 校验表单
+  if (!formRef) return
+  const valid = await formRef.value.validate()
+  if (!valid) return
+  // 提交请求
+  formLoading.value = true
+  try {
+    const data = formData.value as ProductCategoryApi.CategoryVO
+    if (formType.value === 'create') {
+      await ProductCategoryApi.createCategory(data)
+      message.success(t('common.createSuccess'))
+    } else {
+      await ProductCategoryApi.updateCategory(data)
+      message.success(t('common.updateSuccess'))
+    }
+    dialogVisible.value = false
+    // 发送操作成功的事件
+    emit('success')
+  } finally {
+    formLoading.value = false
+  }
+}
+
+/** 重置表单 */
+const resetForm = () => {
+  formData.value = {
+    id: undefined,
+    name: '',
+    picUrl: '',
+    status: CommonStatusEnum.ENABLE,
+    description: ''
+  }
+  formRef.value?.resetFields()
+}
+
+/** 获得分类树 */
+const getTree = async () => {
+  const data = await ProductCategoryApi.getCategoryList({})
+  const tree = handleTree(data, 'id', 'parentId')
+  const menu = { id: 0, name: '顶级分类', children: tree }
+  categoryTree.value = [menu]
+}
+</script>
diff --git a/src/views/mall/product/category/index.vue b/src/views/mall/product/category/index.vue
new file mode 100644
index 00000000..f57e35f8
--- /dev/null
+++ b/src/views/mall/product/category/index.vue
@@ -0,0 +1,144 @@
+<template>
+  <!-- 搜索工作栏 -->
+  <ContentWrap>
+    <el-form
+      class="-mb-15px"
+      :model="queryParams"
+      ref="queryFormRef"
+      :inline="true"
+      label-width="68px"
+    >
+      <el-form-item label="分类名称" prop="name">
+        <el-input
+          v-model="queryParams.name"
+          placeholder="请输入分类名称"
+          clearable
+          @keyup.enter="handleQuery"
+          class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item>
+        <el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
+        <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
+        <el-button
+          type="primary"
+          plain
+          @click="openForm('create')"
+          v-hasPermi="['product:category:create']"
+        >
+          <Icon icon="ep:plus" class="mr-5px" /> 新增
+        </el-button>
+      </el-form-item>
+    </el-form>
+  </ContentWrap>
+
+  <!-- 列表 -->
+  <ContentWrap>
+    <el-table v-loading="loading" :data="list" row-key="id" default-expand-all>
+      <el-table-column label="分类名称" prop="name" sortable />
+      <el-table-column label="分类图片" align="center" prop="picUrl">
+        <template #default="scope">
+          <img v-if="scope.row.picUrl" :src="scope.row.picUrl" alt="分类图片" class="h-100px" />
+        </template>
+      </el-table-column>
+      <el-table-column label="分类排序" align="center" prop="sort" />
+      <el-table-column label="开启状态" align="center" prop="status">
+        <template #default="scope">
+          <dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status" />
+        </template>
+      </el-table-column>
+      <el-table-column
+        label="创建时间"
+        align="center"
+        prop="createTime"
+        width="180"
+        :formatter="dateFormatter"
+      />
+      <el-table-column label="操作" align="center">
+        <template #default="scope">
+          <el-button
+            link
+            type="primary"
+            @click="openForm('update', scope.row.id)"
+            v-hasPermi="['product:category:update']"
+          >
+            编辑
+          </el-button>
+          <el-button
+            link
+            type="danger"
+            @click="handleDelete(scope.row.id)"
+            v-hasPermi="['product:category:delete']"
+          >
+            删除
+          </el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+  </ContentWrap>
+
+  <!-- 表单弹窗:添加/修改 -->
+  <CategoryForm ref="formRef" @success="getList" />
+</template>
+<script setup lang="ts" name="ProductCategory">
+import { DICT_TYPE } from '@/utils/dict'
+import { handleTree } from '@/utils/tree'
+import { dateFormatter } from '@/utils/formatTime'
+import * as ProductCategoryApi from '@/api/mall/product/category'
+import CategoryForm from './CategoryForm.vue'
+const message = useMessage() // 消息弹窗
+const { t } = useI18n() // 国际化
+
+const loading = ref(true) // 列表的加载中
+const list = ref<any[]>([]) // 列表的数据
+const queryParams = reactive({
+  name: undefined
+})
+const queryFormRef = ref() // 搜索的表单
+
+/** 查询列表 */
+const getList = async () => {
+  loading.value = true
+  try {
+    const data = await ProductCategoryApi.getCategoryList(queryParams)
+    list.value = handleTree(data, 'id', 'parentId')
+  } finally {
+    loading.value = false
+  }
+}
+
+/** 搜索按钮操作 */
+const handleQuery = () => {
+  getList()
+}
+
+/** 重置按钮操作 */
+const resetQuery = () => {
+  queryFormRef.value.resetFields()
+  handleQuery()
+}
+
+/** 添加/修改操作 */
+const formRef = ref()
+const openForm = (type: string, id?: number) => {
+  formRef.value.open(type, id)
+}
+
+/** 删除按钮操作 */
+const handleDelete = async (id: number) => {
+  try {
+    // 删除的二次确认
+    await message.delConfirm()
+    // 发起删除
+    await ProductCategoryApi.deleteCategory(id)
+    message.success(t('common.delSuccess'))
+    // 刷新列表
+    await getList()
+  } catch {}
+}
+
+/** 初始化 **/
+onMounted(() => {
+  getList()
+})
+</script>
diff --git a/src/views/mall/product/property/PropertyForm.vue b/src/views/mall/product/property/PropertyForm.vue
new file mode 100644
index 00000000..c9a21d64
--- /dev/null
+++ b/src/views/mall/product/property/PropertyForm.vue
@@ -0,0 +1,95 @@
+<template>
+  <Dialog :title="dialogTitle" v-model="dialogVisible">
+    <el-form
+      ref="formRef"
+      :model="formData"
+      :rules="formRules"
+      label-width="80px"
+      v-loading="formLoading"
+    >
+      <el-form-item label="名称" prop="name">
+        <el-input v-model="formData.name" placeholder="请输入名称" />
+      </el-form-item>
+      <el-form-item label="备注" prop="remark">
+        <el-input v-model="formData.remark" type="textarea" placeholder="请输入内容" />
+      </el-form-item>
+    </el-form>
+    <template #footer>
+      <div class="dialog-footer">
+        <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
+        <el-button @click="dialogVisible = false">取 消</el-button>
+      </div>
+    </template>
+  </Dialog>
+</template>
+<script setup lang="ts">
+import * as PropertyApi from '@/api/mall/product/property'
+const { t } = useI18n() // 国际化
+const message = useMessage() // 消息弹窗
+
+const dialogVisible = ref(false) // 弹窗的是否展示
+const dialogTitle = ref('') // 弹窗的标题
+const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
+const formType = ref('') // 表单的类型:create - 新增;update - 修改
+const formData = ref({
+  id: undefined,
+  name: ''
+})
+const formRules = reactive({
+  name: [{ required: true, message: '名称不能为空', trigger: 'blur' }]
+})
+const formRef = ref() // 表单 Ref
+
+/** 打开弹窗 */
+const open = async (type: string, id?: number) => {
+  dialogVisible.value = true
+  dialogTitle.value = t('action.' + type)
+  formType.value = type
+  resetForm()
+  // 修改时,设置数据
+  if (id) {
+    formLoading.value = true
+    try {
+      formData.value = await PropertyApi.getProperty(id)
+    } finally {
+      formLoading.value = false
+    }
+  }
+}
+defineExpose({ open }) // 提供 open 方法,用于打开弹窗
+
+/** 提交表单 */
+const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
+const submitForm = async () => {
+  // 校验表单
+  if (!formRef) return
+  const valid = await formRef.value.validate()
+  if (!valid) return
+  // 提交请求
+  formLoading.value = true
+  try {
+    const data = formData.value as PropertyApi.PropertyVO
+    if (formType.value === 'create') {
+      await PropertyApi.createProperty(data)
+      message.success(t('common.createSuccess'))
+    } else {
+      await PropertyApi.updateProperty(data)
+      message.success(t('common.updateSuccess'))
+    }
+    dialogVisible.value = false
+    // 发送操作成功的事件
+    emit('success')
+  } finally {
+    formLoading.value = false
+  }
+}
+
+/** 重置表单 */
+const resetForm = () => {
+  formData.value = {
+    id: undefined,
+    name: ''
+  }
+  formRef.value?.resetFields()
+}
+</script>
diff --git a/src/views/mall/product/property/index.vue b/src/views/mall/product/property/index.vue
new file mode 100644
index 00000000..6c2e6e97
--- /dev/null
+++ b/src/views/mall/product/property/index.vue
@@ -0,0 +1,160 @@
+<template>
+  <!-- 搜索工作栏 -->
+  <ContentWrap>
+    <el-form
+      class="-mb-15px"
+      :model="queryParams"
+      ref="queryFormRef"
+      :inline="true"
+      label-width="68px"
+    >
+      <el-form-item label="名称" prop="name">
+        <el-input
+          v-model="queryParams.name"
+          placeholder="请输入名称"
+          clearable
+          @keyup.enter="handleQuery"
+          class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item label="创建时间" prop="createTime">
+        <el-date-picker
+          v-model="queryParams.createTime"
+          value-format="YYYY-MM-DD HH:mm:ss"
+          type="daterange"
+          start-placeholder="开始日期"
+          end-placeholder="结束日期"
+          :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
+          class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item>
+        <el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
+        <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
+        <el-button
+          plain
+          type="primary"
+          @click="openForm('create')"
+          v-hasPermi="['product:property:create']"
+        >
+          <Icon icon="ep:plus" class="mr-5px" /> 新增
+        </el-button>
+      </el-form-item>
+    </el-form>
+  </ContentWrap>
+
+  <!-- 列表 -->
+  <ContentWrap>
+    <el-table v-loading="loading" :data="list">
+      <el-table-column label="编号" align="center" prop="id" />
+      <el-table-column label="名称" align="center" />
+      <el-table-column label="备注" align="center" prop="remark" :show-overflow-tooltip="true" />
+      <el-table-column
+        label="创建时间"
+        align="center"
+        prop="createTime"
+        width="180"
+        :formatter="dateFormatter"
+      />
+      <el-table-column label="操作" align="center">
+        <template #default="scope">
+          <el-button
+            link
+            type="primary"
+            @click="openForm('update', scope.row.id)"
+            v-hasPermi="['product:property:update']"
+          >
+            编辑
+          </el-button>
+          <el-button link type="primary">
+            <router-link :to="'/property/value/' + scope.row.id">属性值</router-link>
+          </el-button>
+          <el-button
+            link
+            type="danger"
+            @click="handleDelete(scope.row.id)"
+            v-hasPermi="['product:property:delete']"
+          >
+            删除
+          </el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+    <!-- 分页 -->
+    <Pagination
+      :total="total"
+      v-model:page="queryParams.pageNo"
+      v-model:limit="queryParams.pageSize"
+      @pagination="getList"
+    />
+  </ContentWrap>
+
+  <!-- 表单弹窗:添加/修改 -->
+  <PropertyForm ref="formRef" @success="getList" />
+</template>
+<script setup lang="ts" name="Config">
+import { dateFormatter } from '@/utils/formatTime'
+import * as PropertyApi from '@/api/mall/product/property'
+import PropertyForm from './PropertyForm.vue'
+const message = useMessage() // 消息弹窗
+const { t } = useI18n() // 国际化
+
+const loading = ref(true) // 列表的加载中
+const total = ref(0) // 列表的总页数
+const list = ref([]) // 列表的数据
+const queryParams = reactive({
+  pageNo: 1,
+  pageSize: 10,
+  name: undefined,
+  createTime: []
+})
+const queryFormRef = ref() // 搜索的表单
+
+/** 查询列表 */
+const getList = async () => {
+  loading.value = true
+  try {
+    const data = await PropertyApi.getPropertyPage(queryParams)
+    list.value = data.list
+    total.value = data.total
+  } finally {
+    loading.value = false
+  }
+}
+
+/** 搜索按钮操作 */
+const handleQuery = () => {
+  queryParams.pageNo = 1
+  getList()
+}
+
+/** 重置按钮操作 */
+const resetQuery = () => {
+  queryFormRef.value.resetFields()
+  handleQuery()
+}
+
+/** 添加/修改操作 */
+const formRef = ref()
+const openForm = (type: string, id?: number) => {
+  formRef.value.open(type, id)
+}
+
+/** 删除按钮操作 */
+const handleDelete = async (id: number) => {
+  try {
+    // 删除的二次确认
+    await message.delConfirm()
+    // 发起删除
+    await PropertyApi.deleteProperty(id)
+    message.success(t('common.delSuccess'))
+    // 刷新列表
+    await getList()
+  } catch {}
+}
+
+/** 初始化 **/
+onMounted(() => {
+  getList()
+})
+</script>
diff --git a/src/views/mall/product/property/value/ValueForm.vue b/src/views/mall/product/property/value/ValueForm.vue
new file mode 100644
index 00000000..3f6a5225
--- /dev/null
+++ b/src/views/mall/product/property/value/ValueForm.vue
@@ -0,0 +1,102 @@
+<template>
+  <Dialog :title="dialogTitle" v-model="dialogVisible">
+    <el-form
+      ref="formRef"
+      :model="formData"
+      :rules="formRules"
+      label-width="80px"
+      v-loading="formLoading"
+    >
+      <el-form-item label="属性编号" prop="category">
+        <el-input v-model="formData.propertyId" disabled="" />
+      </el-form-item>
+      <el-form-item label="名称" prop="name">
+        <el-input v-model="formData.name" placeholder="请输入名称" />
+      </el-form-item>
+      <el-form-item label="备注" prop="remark">
+        <el-input v-model="formData.remark" type="textarea" placeholder="请输入内容" />
+      </el-form-item>
+    </el-form>
+    <template #footer>
+      <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
+      <el-button @click="dialogVisible = false">取 消</el-button>
+    </template>
+  </Dialog>
+</template>
+<script setup lang="ts">
+import * as PropertyApi from '@/api/mall/product/property'
+const { t } = useI18n() // 国际化
+const message = useMessage() // 消息弹窗
+
+const dialogVisible = ref(false) // 弹窗的是否展示
+const dialogTitle = ref('') // 弹窗的标题
+const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
+const formType = ref('') // 表单的类型:create - 新增;update - 修改
+const formData = ref({
+  id: undefined,
+  propertyId: undefined,
+  name: '',
+  remark: ''
+})
+const formRules = reactive({
+  propertyId: [{ required: true, message: '属性不能为空', trigger: 'blur' }],
+  name: [{ required: true, message: '名称不能为空', trigger: 'blur' }]
+})
+const formRef = ref() // 表单 Ref
+
+/** 打开弹窗 */
+const open = async (type: string, propertyId: number, id?: number) => {
+  dialogVisible.value = true
+  dialogTitle.value = t('action.' + type)
+  formType.value = type
+  resetForm()
+  formData.value.propertyId = propertyId
+  // 修改时,设置数据
+  if (id) {
+    formLoading.value = true
+    try {
+      formData.value = await PropertyApi.getPropertyValue(id)
+    } finally {
+      formLoading.value = false
+    }
+  }
+}
+defineExpose({ open }) // 提供 open 方法,用于打开弹窗
+
+/** 提交表单 */
+const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
+const submitForm = async () => {
+  // 校验表单
+  if (!formRef) return
+  const valid = await formRef.value.validate()
+  if (!valid) return
+  // 提交请求
+  formLoading.value = true
+  try {
+    const data = formData.value as PropertyApi.PropertyValueVO
+    if (formType.value === 'create') {
+      await PropertyApi.createPropertyValue(data)
+      message.success(t('common.createSuccess'))
+    } else {
+      await PropertyApi.updatePropertyValue(data)
+      message.success(t('common.updateSuccess'))
+    }
+    dialogVisible.value = false
+    // 发送操作成功的事件
+    emit('success')
+  } finally {
+    formLoading.value = false
+  }
+}
+
+/** 重置表单 */
+const resetForm = () => {
+  formData.value = {
+    id: undefined,
+    propertyId: undefined,
+    name: '',
+    remark: ''
+  }
+  formRef.value?.resetFields()
+}
+</script>
diff --git a/src/views/mall/product/property/value/index.vue b/src/views/mall/product/property/value/index.vue
new file mode 100644
index 00000000..6f5ae5c8
--- /dev/null
+++ b/src/views/mall/product/property/value/index.vue
@@ -0,0 +1,160 @@
+<template>
+  <!-- 搜索工作栏 -->
+  <ContentWrap>
+    <el-form
+      class="-mb-15px"
+      :model="queryParams"
+      ref="queryFormRef"
+      :inline="true"
+      label-width="68px"
+    >
+      <el-form-item label="属性项" prop="propertyId">
+        <el-select v-model="queryParams.propertyId" class="!w-240px">
+          <el-option
+            v-for="item in propertyOptions"
+            :key="item.id"
+            :label="item.name"
+            :value="item.id"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="名称" prop="name">
+        <el-input
+          v-model="queryParams.name"
+          placeholder="请输入名称"
+          clearable
+          @keyup.enter="handleQuery"
+          class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item>
+        <el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
+        <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
+        <el-button
+          plain
+          type="primary"
+          @click="openForm('create')"
+          v-hasPermi="['product:property:create']"
+        >
+          <Icon icon="ep:plus" class="mr-5px" /> 新增
+        </el-button>
+      </el-form-item>
+    </el-form>
+  </ContentWrap>
+
+  <!-- 列表 -->
+  <ContentWrap>
+    <el-table v-loading="loading" :data="list">
+      <el-table-column label="编号" align="center" prop="id" />
+      <el-table-column label="名称" align="center" prop="name" :show-overflow-tooltip="true" />
+      <el-table-column label="备注" align="center" prop="remark" :show-overflow-tooltip="true" />
+      <el-table-column
+        label="创建时间"
+        align="center"
+        prop="createTime"
+        width="180"
+        :formatter="dateFormatter"
+      />
+      <el-table-column label="操作" align="center">
+        <template #default="scope">
+          <el-button
+            link
+            type="primary"
+            @click="openForm('update', scope.row.id)"
+            v-hasPermi="['product:property:update']"
+          >
+            编辑
+          </el-button>
+          <el-button
+            link
+            type="danger"
+            @click="handleDelete(scope.row.id)"
+            v-hasPermi="['product:property:delete']"
+          >
+            删除
+          </el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+    <!-- 分页 -->
+    <Pagination
+      :total="total"
+      v-model:page="queryParams.pageNo"
+      v-model:limit="queryParams.pageSize"
+      @pagination="getList"
+    />
+  </ContentWrap>
+
+  <!-- 表单弹窗:添加/修改 -->
+  <ValueForm ref="formRef" @success="getList" />
+</template>
+<script setup lang="ts" name="Config">
+import { dateFormatter } from '@/utils/formatTime'
+import * as PropertyApi from '@/api/mall/product/property'
+import ValueForm from './ValueForm.vue'
+const message = useMessage() // 消息弹窗
+const { t } = useI18n() // 国际化
+const { params } = useRoute() // 查询参数
+
+const loading = ref(true) // 列表的加载中
+const total = ref(0) // 列表的总页数
+const list = ref([]) // 列表的数据
+const queryParams = reactive({
+  pageNo: 1,
+  pageSize: 10,
+  propertyId: Number(params.propertyId),
+  name: undefined
+})
+const queryFormRef = ref() // 搜索的表单
+const propertyOptions = ref([]) // 属性项的列表
+
+/** 查询列表 */
+const getList = async () => {
+  loading.value = true
+  try {
+    const data = await PropertyApi.getPropertyValuePage(queryParams)
+    list.value = data.list
+    total.value = data.total
+  } finally {
+    loading.value = false
+  }
+}
+
+/** 搜索按钮操作 */
+const handleQuery = () => {
+  queryParams.pageNo = 1
+  getList()
+}
+
+/** 重置按钮操作 */
+const resetQuery = () => {
+  queryFormRef.value.resetFields()
+  handleQuery()
+}
+
+/** 添加/修改操作 */
+const formRef = ref()
+const openForm = (type: string, id?: number) => {
+  formRef.value.open(type, queryParams.propertyId, id)
+}
+
+/** 删除按钮操作 */
+const handleDelete = async (id: number) => {
+  try {
+    // 删除的二次确认
+    await message.delConfirm()
+    // 发起删除
+    await PropertyApi.deleteProperty(id)
+    message.success(t('common.delSuccess'))
+    // 刷新列表
+    await getList()
+  } catch {}
+}
+
+/** 初始化 **/
+onMounted(async () => {
+  await getList()
+  // 属性项下拉框数据
+  propertyOptions.value = await PropertyApi.getPropertyList({})
+})
+</script>
diff --git a/src/views/mp/account/AccountForm.vue b/src/views/mp/account/AccountForm.vue
index 406db8fe..a80bb48f 100644
--- a/src/views/mp/account/AccountForm.vue
+++ b/src/views/mp/account/AccountForm.vue
@@ -1,5 +1,5 @@
 <template>
-  <Dialog :title="modelTitle" v-model="modelVisible">
+  <Dialog :title="dialogTitle" v-model="dialogVisible">
     <el-form
       ref="formRef"
       :model="formData"
@@ -64,7 +64,7 @@
     </el-form>
     <template #footer>
       <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
-      <el-button @click="modelVisible = false">取 消</el-button>
+      <el-button @click="dialogVisible = false">取 消</el-button>
     </template>
   </Dialog>
 </template>
@@ -73,8 +73,8 @@ import * as AccountApi from '@/api/mp/account'
 const { t } = useI18n() // 国际化
 const message = useMessage() // 消息弹窗
 
-const modelVisible = ref(false) // 弹窗的是否展示
-const modelTitle = ref('') // 弹窗的标题
+const dialogVisible = ref(false) // 弹窗的是否展示
+const dialogTitle = ref('') // 弹窗的标题
 const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
 const formType = ref('') // 表单的类型:create - 新增;update - 修改
 const formData = ref({
@@ -98,8 +98,8 @@ const formRef = ref() // 表单 Ref
 
 /** 打开弹窗 */
 const open = async (type: string, id?: number) => {
-  modelVisible.value = true
-  modelTitle.value = t('action.' + type)
+  dialogVisible.value = true
+  dialogTitle.value = t('action.' + type)
   formType.value = type
   resetForm()
   // 修改时,设置数据
@@ -132,7 +132,7 @@ const submitForm = async () => {
       await AccountApi.updateAccount(data)
       message.success(t('common.updateSuccess'))
     }
-    modelVisible.value = false
+    dialogVisible.value = false
     // 发送操作成功的事件
     emit('success')
   } finally {
diff --git a/src/views/mp/freePublish/index.vue b/src/views/mp/freePublish/index.vue
index 05f3dec6..8a3d5285 100644
--- a/src/views/mp/freePublish/index.vue
+++ b/src/views/mp/freePublish/index.vue
@@ -19,14 +19,8 @@
         </el-select>
       </el-form-item>
       <el-form-item>
-        <el-button @click="handleQuery">
-          <Icon icon="ep:search" class="mr-5px" />
-          搜索
-        </el-button>
-        <el-button @click="resetQuery">
-          <Icon icon="ep:refresh" class="mr-5px" />
-          重置
-        </el-button>
+        <el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
+        <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
       </el-form-item>
     </el-form>
   </content-wrap>
@@ -41,7 +35,6 @@
         :key="item.articleId"
       >
         <wx-news :articles="item.content.newsItem" />
-        <!-- 操作 -->
         <el-row justify="center" class="ope-row">
           <el-button
             type="danger"
@@ -54,9 +47,8 @@
         </el-row>
       </div>
     </div>
-    <!-- 分页组件 -->
-    <pagination
-      v-show="total > 0"
+    <!-- 分页 -->
+    <Pagination
       :total="total"
       v-model:page="queryParams.pageNo"
       v-model:limit="queryParams.pageSize"
@@ -66,24 +58,18 @@
 </template>
 
 <script setup lang="ts" name="freePublish">
-import { getFreePublishPage, deleteFreePublish } from '@/api/mp/freePublish'
+import * as FreePublishApi from '@/api/mp/freePublish'
 import * as MpAccountApi from '@/api/mp/account'
 import WxNews from '@/views/mp/components/wx-news/main.vue'
-
 const message = useMessage() // 消息弹窗
+const { t } = useI18n() // 国际化
 
 const loading = ref(true) // 列表的加载中
 const total = ref(0) // 列表的总页数
 const list = ref([]) // 列表的数据
-interface QueryParams {
-  currentPage: number | undefined | string
-  pageNo: number | undefined | string
-  accountId: number | undefined | string
-}
-
-const queryParams: QueryParams = reactive({
-  currentPage: 1, // 当前页数
-  pageNo: 1, // 当前页数
+const queryParams = reactive({
+  pageNo: 1,
+  pageSize: 10,
   accountId: undefined // 当前页数
 })
 const queryFormRef = ref() // 搜索的表单
@@ -96,25 +82,14 @@ const getList = async () => {
     message.error('未选中公众号,无法查询已发表图文')
     return false
   }
-  // TODO 改成 await 形式
-  loading.value = true
-  getFreePublishPage(queryParams)
-    .then((data) => {
-      console.log(data)
-      // 将 thumbUrl 转成 picUrl,保证 wx-news 组件可以预览封面
-      data.list.forEach((item) => {
-        console.log(item)
-        const newsItem = item.content.newsItem
-        newsItem.forEach((article) => {
-          article.picUrl = article.thumbUrl
-        })
-      })
-      list.value = data.list
-      total.value = data.total
-    })
-    .finally(() => {
-      loading.value = false
-    })
+  try {
+    loading.value = true
+    const data = await FreePublishApi.getFreePublishPage(queryParams)
+    list.value = data.list
+    total.value = data.total
+  } finally {
+    loading.value = false
+  }
 }
 
 /** 搜索按钮操作 */
@@ -135,21 +110,15 @@ const resetQuery = () => {
 
 /** 删除按钮操作 */
 const handleDelete = async (item) => {
-  {
-    // TODO 改成 await 形式
-    const articleId = item.articleId
-    const accountId = queryParams.accountId
-    message
-      .confirm('删除后用户将无法访问此页面,确定删除?')
-      .then(function () {
-        return deleteFreePublish(accountId, articleId)
-      })
-      .then(() => {
-        getList()
-        message.success('删除成功')
-      })
-      .catch(() => {})
-  }
+  try {
+    // 删除的二次确认
+    await message.delConfirm('删除后用户将无法访问此页面,确定删除?')
+    // 发起删除
+    await FreePublishApi.deleteFreePublish(queryParams.accountId, item.articleId)
+    message.success(t('common.delSuccess'))
+    // 刷新列表
+    await getList()
+  } catch {}
 }
 
 onMounted(async () => {
@@ -162,15 +131,6 @@ onMounted(async () => {
 })
 </script>
 <style lang="scss" scoped>
-.pagination {
-  float: right;
-  margin-right: 25px;
-}
-
-.add_but {
-  padding: 10px;
-}
-
 .ope-row {
   margin-top: 5px;
   text-align: center;
diff --git a/src/views/mp/tag/TagForm.vue b/src/views/mp/tag/TagForm.vue
index db251cdf..e190af89 100644
--- a/src/views/mp/tag/TagForm.vue
+++ b/src/views/mp/tag/TagForm.vue
@@ -1,5 +1,5 @@
 <template>
-  <Dialog :title="modelTitle" v-model="modelVisible">
+  <Dialog :title="dialogTitle" v-model="dialogVisible">
     <el-form
       ref="formRef"
       :model="formData"
@@ -13,7 +13,7 @@
     </el-form>
     <template #footer>
       <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
-      <el-button @click="modelVisible = false">取 消</el-button>
+      <el-button @click="dialogVisible = false">取 消</el-button>
     </template>
   </Dialog>
 </template>
@@ -22,8 +22,8 @@ import * as MpTagApi from '@/api/mp/tag'
 const { t } = useI18n() // 国际化
 const message = useMessage() // 消息弹窗
 
-const modelVisible = ref(false) // 弹窗的是否展示
-const modelTitle = ref('') // 弹窗的标题
+const dialogVisible = ref(false) // 弹窗的是否展示
+const dialogTitle = ref('') // 弹窗的标题
 const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
 const formType = ref('') // 表单的类型:create - 新增;update - 修改
 const formData = ref({
@@ -37,8 +37,8 @@ const formRef = ref() // 表单 Ref
 
 /** 打开弹窗 */
 const open = async (type: string, accountId: number, id?: number) => {
-  modelVisible.value = true
-  modelTitle.value = t('action.' + type)
+  dialogVisible.value = true
+  dialogTitle.value = t('action.' + type)
   formType.value = type
   resetForm()
   formData.value.accountId = accountId
@@ -72,7 +72,7 @@ const submitForm = async () => {
       await MpTagApi.updateTag(data)
       message.success(t('common.updateSuccess'))
     }
-    modelVisible.value = false
+    dialogVisible.value = false
     // 发送操作成功的事件
     emit('success')
   } finally {
diff --git a/src/views/mp/tag/index.vue b/src/views/mp/tag/index.vue
index bedfbad8..8a4b731d 100644
--- a/src/views/mp/tag/index.vue
+++ b/src/views/mp/tag/index.vue
@@ -12,9 +12,9 @@
         <el-select v-model="queryParams.accountId" placeholder="请选择公众号" class="!w-240px">
           <el-option
             v-for="item in accountList"
-            :key="parseInt(item.id)"
+            :key="item.id"
             :label="item.name"
-            :value="parseInt(item.id)"
+            :value="item.id"
           />
         </el-select>
       </el-form-item>
@@ -28,21 +28,15 @@
         />
       </el-form-item>
       <el-form-item>
-        <el-button @click="handleQuery">
-          <Icon icon="ep:search" class="mr-5px" />
-          搜索
-        </el-button>
-        <el-button @click="resetQuery">
-          <Icon icon="ep:refresh" class="mr-5px" />
-          重置
-        </el-button>
+        <el-form-item>
+          <el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
+          <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
+        </el-form-item>
         <el-button type="primary" plain @click="openForm('create')" v-hasPermi="['mp:tag:create']">
-          <Icon icon="ep:plus" class="mr-5px" />
-          新增
+          <Icon icon="ep:plus" class="mr-5px" /> 新增
         </el-button>
         <el-button type="success" plain @click="handleSync" v-hasPermi="['mp:tag:sync']">
-          <Icon icon="ep:refresh" class="mr-5px" />
-          同步
+          <Icon icon="ep:refresh" class="mr-5px" /> 同步
         </el-button>
       </el-form-item>
     </el-form>
@@ -99,7 +93,6 @@ import { dateFormatter } from '@/utils/formatTime'
 import * as MpTagApi from '@/api/mp/tag'
 import * as MpAccountApi from '@/api/mp/account'
 import TagForm from './TagForm.vue'
-
 const message = useMessage() // 消息弹窗
 const { t } = useI18n() // 国际化
 
@@ -143,7 +136,6 @@ const resetQuery = () => {
   queryFormRef.value.resetFields()
   // 默认选中第一个
   if (accountList.value.length > 0) {
-    // @ts-ignore
     queryParams.accountId = accountList.value[0].id
   }
   handleQuery()
@@ -184,7 +176,6 @@ onMounted(async () => {
   accountList.value = await MpAccountApi.getSimpleAccountList()
   // 选中第一个
   if (accountList.value.length > 0) {
-    // @ts-ignore
     queryParams.accountId = accountList.value[0].id
   }
   await getList()
diff --git a/src/views/pay/merchant/MerchantForm.vue b/src/views/pay/merchant/MerchantForm.vue
new file mode 100644
index 00000000..34dea00a
--- /dev/null
+++ b/src/views/pay/merchant/MerchantForm.vue
@@ -0,0 +1,110 @@
+<template>
+  <Dialog :title="dialogTitle" v-model="dialogVisible">
+    <el-form ref="formRef" :model="formData" :rules="formRules" label-width="80px">
+      <el-form-item label="商户全称" prop="name">
+        <el-input v-model="formData.name" placeholder="请输入商户全称" />
+      </el-form-item>
+      <el-form-item label="商户简称" prop="shortName">
+        <el-input v-model="formData.shortName" placeholder="请输入商户简称" />
+      </el-form-item>
+      <el-form-item label="开启状态" prop="status">
+        <el-select v-model="formData.status" placeholder="请选择状态" clearable>
+          <el-option
+            v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)"
+            :key="dict.value"
+            :label="dict.label"
+            :value="dict.value"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="备注" prop="remark">
+        <el-input type="textarea" v-model="formData.remark" placeholder="请输入备注" />
+      </el-form-item>
+    </el-form>
+    <template #footer>
+      <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
+      <el-button @click="dialogVisible = false">取 消</el-button>
+    </template>
+  </Dialog>
+</template>
+<script setup lang="ts">
+import * as MerchantApi from '@/api/pay/merchant'
+import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
+import { CommonStatusEnum } from '@/utils/constants'
+const { t } = useI18n() // 国际化
+const message = useMessage() // 消息弹窗
+
+const dialogVisible = ref(false) // 弹窗的是否展示
+const dialogTitle = ref('') // 弹窗的标题
+const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
+const formType = ref('') // 表单的类型:create - 新增;update - 修改
+const formData = ref({
+  id: undefined,
+  name: '',
+  shortName: '',
+  status: CommonStatusEnum.ENABLE,
+  remark: ''
+})
+const formRules = reactive({
+  name: [{ required: true, message: '商户名称不能为空', trigger: 'blur' }],
+  shortName: [{ required: true, message: '商户简称不能为空', trigger: 'blur' }],
+  status: [{ required: true, message: '状态不能为空', trigger: 'change' }]
+})
+const formRef = ref() // 表单 Ref
+
+/** 打开弹窗 */
+const open = async (type: string, id?: number) => {
+  dialogVisible.value = true
+  dialogTitle.value = t('action.' + type)
+  formType.value = type
+  resetForm()
+  // 修改时,设置数据
+  if (id) {
+    formLoading.value = true
+    try {
+      formData.value = await MerchantApi.getMerchant(id)
+    } finally {
+      formLoading.value = false
+    }
+  }
+}
+defineExpose({ open }) // 提供 open 方法,用于打开弹窗
+
+/** 提交表单 */
+const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
+const submitForm = async () => {
+  // 校验表单
+  if (!formRef) return
+  const valid = await formRef.value.validate()
+  if (!valid) return
+  // 提交请求
+  formLoading.value = true
+  try {
+    const data = formData.value as unknown as MerchantApi.MerchantVO
+    if (formType.value === 'create') {
+      await MerchantApi.createMerchant(data)
+      message.success(t('common.createSuccess'))
+    } else {
+      await MerchantApi.updateMerchant(data)
+      message.success(t('common.updateSuccess'))
+    }
+    dialogVisible.value = false
+    // 发送操作成功的事件
+    emit('success')
+  } finally {
+    formLoading.value = false
+  }
+}
+
+/** 重置表单 */
+const resetForm = () => {
+  formData.value = {
+    id: undefined,
+    name: '',
+    shortName: '',
+    status: CommonStatusEnum.ENABLE,
+    remark: ''
+  }
+  formRef.value?.resetFields()
+}
+</script>
diff --git a/src/views/pay/merchant/index.vue b/src/views/pay/merchant/index.vue
index 1ea460ec..d2e487c3 100644
--- a/src/views/pay/merchant/index.vue
+++ b/src/views/pay/merchant/index.vue
@@ -1,153 +1,242 @@
 <template>
-  <ContentWrap>
-    <!-- 列表 -->
-    <XTable @register="registerTable">
-      <template #toolbar_buttons>
-        <!-- 操作:新增 -->
-        <XButton
+  <content-wrap>
+    <!-- 搜索工作栏 -->
+    <el-form
+      class="-mb-15px"
+      :model="queryParams"
+      ref="queryFormRef"
+      :inline="true"
+      label-width="68px"
+    >
+      <el-form-item label="商户号" prop="no">
+        <el-input v-model="queryParams.no" placeholder="请输入商户号" clearable class="!w-240px" />
+      </el-form-item>
+      <el-form-item label="商户全称" prop="name">
+        <el-input
+          v-model="queryParams.name"
+          placeholder="请输入商户全称"
+          clearable
+          class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item label="商户简称" prop="shortName">
+        <el-input
+          v-model="queryParams.shortName"
+          placeholder="请输入商户简称"
+          clearable
+          class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item label="开启状态" prop="status">
+        <el-select v-model="queryParams.status" placeholder="字典状态" clearable class="!w-240px">
+          <el-option
+            v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)"
+            :key="dict.value"
+            :label="dict.label"
+            :value="dict.value"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="备注" prop="remark">
+        <el-input
+          v-model="queryParams.remark"
+          placeholder="请输入备注"
+          clearable
+          class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item label="创建时间" prop="createTime">
+        <el-date-picker
+          v-model="queryParams.createTime"
+          value-format="YYYY-MM-DD HH:mm:ss"
+          type="datetimerange"
+          start-placeholder="开始日期"
+          end-placeholder="结束日期"
+          class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item>
+        <el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
+        <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
+        <el-button
+          plain
           type="primary"
-          preIcon="ep:zoom-in"
-          :title="t('action.add')"
+          @click="openForm('create')"
           v-hasPermi="['pay:merchant:create']"
-          @click="handleCreate()"
-        />
-        <!-- 操作:导出 -->
-        <XButton
-          type="warning"
-          preIcon="ep:download"
-          :title="t('action.export')"
+        >
+          <Icon icon="ep:plus" class="mr-5px" /> 新增
+        </el-button>
+        <el-button
+          type="success"
+          plain
+          @click="handleExport"
+          :loading="exportLoading"
           v-hasPermi="['pay:merchant:export']"
-          @click="exportList('商户列表.xls')"
-        />
-      </template>
-      <template #actionbtns_default="{ row }">
-        <!-- 操作:修改 -->
-        <XTextButton
-          preIcon="ep:edit"
-          :title="t('action.edit')"
-          v-hasPermi="['pay:merchant:update']"
-          @click="handleUpdate(row.id)"
-        />
-        <!-- 操作:详情 -->
-        <XTextButton
-          preIcon="ep:view"
-          :title="t('action.detail')"
-          v-hasPermi="['pay:merchant:query']"
-          @click="handleDetail(row.id)"
-        />
-        <!-- 操作:删除 -->
-        <XTextButton
-          preIcon="ep:delete"
-          :title="t('action.del')"
-          v-hasPermi="['pay:merchant:delete']"
-          @click="deleteData(row.id)"
-        />
-      </template>
-    </XTable>
-  </ContentWrap>
-  <XModal v-model="dialogVisible" :title="dialogTitle">
-    <!-- 对话框(添加 / 修改) -->
-    <Form
-      v-if="['create', 'update'].includes(actionType)"
-      :schema="allSchemas.formSchema"
-      :rules="rules"
-      ref="formRef"
-    />
-    <!-- 对话框(详情) -->
-    <Descriptions
-      v-if="actionType === 'detail'"
-      :schema="allSchemas.detailSchema"
-      :data="detailData"
-    />
-    <!-- 操作按钮 -->
-    <template #footer>
-      <!-- 按钮:保存 -->
-      <XButton
-        v-if="['create', 'update'].includes(actionType)"
-        type="primary"
-        :title="t('action.save')"
-        :loading="actionLoading"
-        @click="submitForm()"
+        >
+          <Icon icon="ep:download" class="mr-5px" /> 导出
+        </el-button>
+      </el-form-item>
+    </el-form>
+  </content-wrap>
+
+  <!-- 列表 -->
+  <content-wrap>
+    <el-table v-loading="loading" :data="list">
+      <el-table-column label="商户编号" align="center" prop="id" />
+      <el-table-column label="商户号" align="center" prop="no" />
+      <el-table-column label="商户全称" align="center" prop="name" />
+      <el-table-column label="商户简称" align="center" prop="shortName" />
+      <el-table-column 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)"
+          />
+        </template>
+      </el-table-column>
+      <el-table-column label="备注" align="center" prop="remark" />
+      <el-table-column
+        label="创建时间"
+        align="center"
+        prop="createTime"
+        :formatter="dateFormatter"
+        width="180"
       />
-      <!-- 按钮:关闭 -->
-      <XButton :loading="actionLoading" :title="t('dialog.close')" @click="dialogVisible = false" />
-    </template>
-  </XModal>
+      <el-table-column label="操作" align="center">
+        <template #default="scope">
+          <el-button
+            link
+            type="primary"
+            @click="openForm('update', scope.row.id)"
+            v-hasPermi="['pay:merchant:update']"
+          >
+            修改
+          </el-button>
+          <el-button
+            link
+            type="danger"
+            @click="handleDelete(scope.row.id)"
+            v-hasPermi="['pay:merchant:delete']"
+          >
+            删除
+          </el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+    <!-- 分页 -->
+    <Pagination
+      :total="total"
+      v-model:page="queryParams.pageNo"
+      v-model:limit="queryParams.pageSize"
+      @pagination="getList"
+    />
+  </content-wrap>
+
+  <!-- 表单弹窗:添加/修改 -->
+  <MerchantForm ref="formRef" @success="getList" />
 </template>
 <script setup lang="ts" name="Merchant">
-import type { FormExpose } from '@/components/Form'
-import { rules, allSchemas } from './merchant.data'
+import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
+import { CommonStatusEnum } from '@/utils/constants'
+import { dateFormatter } from '@/utils/formatTime'
+import download from '@/utils/download'
 import * as MerchantApi from '@/api/pay/merchant'
-
-const { t } = useI18n() // 国际化
+import MerchantForm from './MerchantForm.vue'
 const message = useMessage() // 消息弹窗
-// 列表相关的变量
-const [registerTable, { reload, deleteData, exportList }] = useXTable({
-  allSchemas: allSchemas,
-  getListApi: MerchantApi.getMerchantPageApi,
-  deleteApi: MerchantApi.deleteMerchantApi,
-  exportListApi: MerchantApi.exportMerchantApi
+const { t } = useI18n() // 国际化
+
+const loading = ref(true) // 列表的加载中
+const total = ref(0) // 列表的总页数
+const list = ref([]) // 列表的数据
+const queryParams = reactive({
+  pageNo: 1,
+  pageSize: 10,
+  name: '',
+  shortName: '',
+  status: undefined
 })
+const queryFormRef = ref() // 搜索的表单
+const exportLoading = ref(false) // 导出的加载中
 
-// ========== CRUD 相关 ==========
-const actionLoading = ref(false) // 遮罩层
-const actionType = ref('') // 操作按钮的类型
-const dialogVisible = ref(false) // 是否显示弹出层
-const dialogTitle = ref('edit') // 弹出层标题
-const formRef = ref<FormExpose>() // 表单 Ref
-const detailData = ref() // 详情 Ref
-
-// 设置标题
-const setDialogTile = (type: string) => {
-  dialogTitle.value = t('action.' + type)
-  actionType.value = type
-  dialogVisible.value = true
+/** 查询列表 */
+const getList = async () => {
+  loading.value = true
+  try {
+    const data = await MerchantApi.getMerchantPage(queryParams)
+    list.value = data.list
+    total.value = data.total
+  } finally {
+    loading.value = false
+  }
 }
 
-// 新增操作
-const handleCreate = () => {
-  setDialogTile('create')
+/** 搜索按钮操作 */
+const handleQuery = () => {
+  queryParams.pageNo = 1
+  getList()
 }
 
-// 修改操作
-const handleUpdate = async (rowId: number) => {
-  setDialogTile('update')
-  // 设置数据
-  const res = await MerchantApi.getMerchantApi(rowId)
-  unref(formRef)?.setValues(res)
+/** 重置按钮操作 */
+const resetQuery = () => {
+  queryFormRef.value.resetFields()
+  handleQuery()
 }
 
-// 详情操作
-const handleDetail = async (rowId: number) => {
-  setDialogTile('detail')
-  const res = await MerchantApi.getMerchantApi(rowId)
-  detailData.value = res
+/** 添加/修改操作 */
+const formRef = ref()
+const openForm = (type: string, id?: number) => {
+  formRef.value.open(type, id)
 }
 
-// 提交按钮
-const submitForm = async () => {
-  const elForm = unref(formRef)?.getElFormRef()
-  if (!elForm) return
-  elForm.validate(async (valid) => {
-    if (valid) {
-      actionLoading.value = true
-      // 提交请求
-      try {
-        const data = unref(formRef)?.formModel as MerchantApi.MerchantVO
-        if (actionType.value === 'create') {
-          await MerchantApi.createMerchantApi(data)
-          message.success(t('common.createSuccess'))
-        } else {
-          await MerchantApi.updateMerchantApi(data)
-          message.success(t('common.updateSuccess'))
-        }
-        dialogVisible.value = false
-      } finally {
-        actionLoading.value = false
-        // 刷新列表
-        await reload()
-      }
-    }
-  })
+/** 删除按钮操作 */
+const handleDelete = async (id: number) => {
+  try {
+    // 删除的二次确认
+    await message.delConfirm()
+    // 发起删除
+    await MerchantApi.deleteMerchant(id)
+    message.success(t('common.delSuccess'))
+    // 刷新列表
+    await getList()
+  } catch {}
 }
+
+/** 修改状态操作 */
+const handleStatusChange = async (row: MerchantApi.MerchantVO) => {
+  try {
+    // 修改状态的二次确认
+    const text = row.status === CommonStatusEnum.ENABLE ? '启用' : '停用'
+    await message.confirm('确认要"' + text + '""' + row.name + '"商户吗?', t('common.reminder'))
+    // 发起修改状态
+    await MerchantApi.updateMerchantStatus(row.id, row.status)
+    // 刷新列表
+    await getList()
+  } catch {
+    // 取消后,进行恢复按钮
+    row.status =
+      row.status === CommonStatusEnum.ENABLE ? CommonStatusEnum.DISABLE : CommonStatusEnum.ENABLE
+  }
+}
+
+/** 导出按钮操作 */
+const handleExport = async () => {
+  try {
+    // 导出的二次确认
+    await message.exportConfirm()
+    // 发起导出
+    exportLoading.value = true
+    const data = await MerchantApi.exportMerchant(queryParams)
+    download.excel(data, '商户信息.xls')
+  } catch {
+  } finally {
+    exportLoading.value = false
+  }
+}
+
+/** 初始化 **/
+onMounted(() => {
+  getList()
+})
 </script>
diff --git a/src/views/pay/merchant/merchant.data.ts b/src/views/pay/merchant/merchant.data.ts
deleted file mode 100644
index e0e0727d..00000000
--- a/src/views/pay/merchant/merchant.data.ts
+++ /dev/null
@@ -1,70 +0,0 @@
-import type { VxeCrudSchema } from '@/hooks/web/useVxeCrudSchemas'
-const { t } = useI18n() // 国际化
-
-// 表单校验
-export const rules = reactive({
-  no: [required],
-  name: [required],
-  shortName: [required],
-  status: [required]
-})
-
-// CrudSchema
-const crudSchemas = reactive<VxeCrudSchema>({
-  primaryKey: 'id',
-  primaryType: 'seq',
-  primaryTitle: '商户编号',
-  action: true,
-  columns: [
-    {
-      title: '商户号',
-      field: 'no',
-      isSearch: true
-    },
-    {
-      title: '商户全称',
-      field: 'code',
-      isSearch: true
-    },
-    {
-      title: '商户简称',
-      field: 'shortName',
-      isSearch: true
-    },
-    {
-      title: t('common.status'),
-      field: 'status',
-      dictType: DICT_TYPE.COMMON_STATUS,
-      dictClass: 'number',
-      isSearch: true
-    },
-    {
-      title: t('form.remark'),
-      field: 'remark',
-      isTable: false,
-      form: {
-        component: 'Input',
-        componentProps: {
-          type: 'textarea',
-          rows: 4
-        },
-        colProps: {
-          span: 24
-        }
-      }
-    },
-    {
-      title: t('common.createTime'),
-      field: 'createTime',
-      formatter: 'formatDate',
-      isForm: false,
-      search: {
-        show: true,
-        itemRender: {
-          name: 'XDataTimePicker'
-        }
-      }
-    }
-  ]
-})
-export const { allSchemas } = useVxeCrudSchemas(crudSchemas)
diff --git a/src/views/system/area/form.vue b/src/views/system/area/form.vue
index f0cff434..8e1604e5 100644
--- a/src/views/system/area/form.vue
+++ b/src/views/system/area/form.vue
@@ -1,5 +1,5 @@
 <template>
-  <Dialog title="IP 查询" v-model="modelVisible">
+  <Dialog title="IP 查询" v-model="dialogVisible">
     <el-form
       ref="formRef"
       :model="formData"
@@ -16,7 +16,7 @@
     </el-form>
     <template #footer>
       <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
-      <el-button @click="modelVisible = false">取 消</el-button>
+      <el-button @click="dialogVisible = false">取 消</el-button>
     </template>
   </Dialog>
 </template>
@@ -24,7 +24,7 @@
 import * as AreaApi from '@/api/system/area'
 const message = useMessage() // 消息弹窗
 
-const modelVisible = ref(false) // 弹窗的是否展示
+const dialogVisible = ref(false) // 弹窗的是否展示
 const formLoading = ref(false) // 表单的加载中:提交的按钮禁用
 const formData = ref({
   ip: '',
@@ -37,7 +37,7 @@ const formRef = ref() // 表单 Ref
 
 /** 打开弹窗 */
 const openModal = async () => {
-  modelVisible.value = true
+  dialogVisible.value = true
   resetForm()
 }
 defineExpose({ openModal }) // 提供 openModal 方法,用于打开弹窗
diff --git a/src/views/system/area/index.vue b/src/views/system/area/index.vue
index f9d4c57d..d84c769f 100644
--- a/src/views/system/area/index.vue
+++ b/src/views/system/area/index.vue
@@ -1,7 +1,7 @@
 <template>
   <!-- 操作栏 -->
   <content-wrap>
-    <el-button type="primary" @click="openModal()">
+    <el-button type="primary" plain @click="openModal()">
       <Icon icon="ep:plus" class="mr-5px" /> IP 查询
     </el-button>
   </content-wrap>
diff --git a/src/views/system/dept/DeptForm.vue b/src/views/system/dept/DeptForm.vue
index f2c3bc02..21985416 100644
--- a/src/views/system/dept/DeptForm.vue
+++ b/src/views/system/dept/DeptForm.vue
@@ -1,5 +1,5 @@
 <template>
-  <Dialog :title="modelTitle" v-model="modelVisible">
+  <Dialog :title="dialogTitle" v-model="dialogVisible">
     <el-form
       ref="formRef"
       :model="formData"
@@ -58,7 +58,7 @@
     </el-form>
     <template #footer>
       <el-button type="primary" @click="submitForm">确 定</el-button>
-      <el-button @click="modelVisible = false">取 消</el-button>
+      <el-button @click="dialogVisible = false">取 消</el-button>
     </template>
   </Dialog>
 </template>
@@ -71,8 +71,8 @@ import { CommonStatusEnum } from '@/utils/constants'
 const { t } = useI18n() // 国际化
 const message = useMessage() // 消息弹窗
 
-const modelVisible = ref(false) // 弹窗的是否展示
-const modelTitle = ref('') // 弹窗的标题
+const dialogVisible = ref(false) // 弹窗的是否展示
+const dialogTitle = ref('') // 弹窗的标题
 const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
 const formType = ref('') // 表单的类型:create - 新增;update - 修改
 const formData = ref({
@@ -101,8 +101,8 @@ const userList = ref<UserApi.UserVO[]>([]) // 用户列表
 
 /** 打开弹窗 */
 const open = async (type: string, id?: number) => {
-  modelVisible.value = true
-  modelTitle.value = t('action.' + type)
+  dialogVisible.value = true
+  dialogTitle.value = t('action.' + type)
   formType.value = type
   resetForm()
   // 修改时,设置数据
@@ -139,7 +139,7 @@ const submitForm = async () => {
       await DeptApi.updateDeptApi(data)
       message.success(t('common.updateSuccess'))
     }
-    modelVisible.value = false
+    dialogVisible.value = false
     // 发送操作成功的事件
     emit('success')
   } finally {
diff --git a/src/views/system/dept/index.vue b/src/views/system/dept/index.vue
index ead319ce..7a1db4b4 100644
--- a/src/views/system/dept/index.vue
+++ b/src/views/system/dept/index.vue
@@ -51,13 +51,7 @@
 
   <!-- 列表 -->
   <ContentWrap>
-    <el-table
-      v-loading="loading"
-      :data="list"
-      row-key="id"
-      v-if="refreshTable"
-      :default-expand-all="isExpandAll"
-    >
+    <el-table v-loading="loading" :data="list" row-key="id" default-expand-all v-if="refreshTable">
       <el-table-column prop="name" label="部门名称" width="260" />
       <el-table-column prop="leader" label="负责人" width="120">
         <template #default="scope">
diff --git a/src/views/system/dict/data.form.vue b/src/views/system/dict/data.form.vue
index 9271e8a9..4eefc4db 100644
--- a/src/views/system/dict/data.form.vue
+++ b/src/views/system/dict/data.form.vue
@@ -1,5 +1,5 @@
 <template>
-  <Dialog :title="modelTitle" v-model="modelVisible">
+  <Dialog :title="dialogTitle" v-model="dialogVisible">
     <el-form
       ref="formRef"
       :model="formData"
@@ -52,7 +52,7 @@
     </el-form>
     <template #footer>
       <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
-      <el-button @click="modelVisible = false">取 消</el-button>
+      <el-button @click="dialogVisible = false">取 消</el-button>
     </template>
   </Dialog>
 </template>
@@ -63,8 +63,8 @@ import { CommonStatusEnum } from '@/utils/constants'
 const { t } = useI18n() // 国际化
 const message = useMessage() // 消息弹窗
 
-const modelVisible = ref(false) // 弹窗的是否展示
-const modelTitle = ref('') // 弹窗的标题
+const dialogVisible = ref(false) // 弹窗的是否展示
+const dialogTitle = ref('') // 弹窗的标题
 const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
 const formType = ref('') // 表单的类型:create - 新增;update - 修改
 const formData = ref({
@@ -115,8 +115,8 @@ const colorTypeOptions = readonly([
 
 /** 打开弹窗 */
 const openModal = async (type: string, id?: number) => {
-  modelVisible.value = true
-  modelTitle.value = t('action.' + type)
+  dialogVisible.value = true
+  dialogTitle.value = t('action.' + type)
   formType.value = type
   resetForm()
   // 修改时,设置数据
@@ -149,7 +149,7 @@ const submitForm = async () => {
       await DictDataApi.updateDictData(data)
       message.success(t('common.updateSuccess'))
     }
-    modelVisible.value = false
+    dialogVisible.value = false
     // 发送操作成功的事件
     emit('success')
   } finally {
diff --git a/src/views/system/dict/data.vue b/src/views/system/dict/data.vue
index 41bcbaa8..fbb651ff 100644
--- a/src/views/system/dict/data.vue
+++ b/src/views/system/dict/data.vue
@@ -180,7 +180,7 @@ const handleExport = async () => {
     await message.exportConfirm()
     // 发起导出
     exportLoading.value = true
-    const data = await DictDataApi.exportDictDataApi(queryParams)
+    const data = await DictDataApi.exportDictData(queryParams)
     download.excel(data, '字典数据.xls')
   } catch {
   } finally {
diff --git a/src/views/system/dict/form.vue b/src/views/system/dict/form.vue
index 179656de..793186ad 100644
--- a/src/views/system/dict/form.vue
+++ b/src/views/system/dict/form.vue
@@ -1,5 +1,5 @@
 <template>
-  <Dialog :title="modelTitle" v-model="modelVisible">
+  <Dialog :title="dialogTitle" v-model="dialogVisible">
     <el-form
       ref="formRef"
       :model="formData"
@@ -34,7 +34,7 @@
     </el-form>
     <template #footer>
       <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
-      <el-button @click="modelVisible = false">取 消</el-button>
+      <el-button @click="dialogVisible = false">取 消</el-button>
     </template>
   </Dialog>
 </template>
@@ -46,8 +46,8 @@ import { CommonStatusEnum } from '@/utils/constants'
 const { t } = useI18n() // 国际化
 const message = useMessage() // 消息弹窗
 
-const modelVisible = ref(false) // 弹窗的是否展示
-const modelTitle = ref('') // 弹窗的标题
+const dialogVisible = ref(false) // 弹窗的是否展示
+const dialogTitle = ref('') // 弹窗的标题
 const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
 const formType = ref('') // 表单的类型:create - 新增;update - 修改
 const formData = ref({
@@ -65,8 +65,8 @@ const formRef = ref() // 表单 Ref
 
 /** 打开弹窗 */
 const openModal = async (type: string, id?: number) => {
-  modelVisible.value = true
-  modelTitle.value = t('action.' + type)
+  dialogVisible.value = true
+  dialogTitle.value = t('action.' + type)
   formType.value = type
   resetForm()
   // 修改时,设置数据
@@ -99,7 +99,7 @@ const submitForm = async () => {
       await DictTypeApi.updateDictType(data)
       message.success(t('common.updateSuccess'))
     }
-    modelVisible.value = false
+    dialogVisible.value = false
     // 发送操作成功的事件
     emit('success')
   } finally {
diff --git a/src/views/system/dict/index.vue b/src/views/system/dict/index.vue
index 4e304bf5..43e3a0bf 100644
--- a/src/views/system/dict/index.vue
+++ b/src/views/system/dict/index.vue
@@ -41,7 +41,6 @@
           v-model="queryParams.createTime"
           value-format="yyyy-MM-dd HH:mm:ss"
           type="daterange"
-          range-separator="-"
           start-placeholder="开始日期"
           end-placeholder="结束日期"
           :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
@@ -51,7 +50,12 @@
       <el-form-item>
         <el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
         <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
-        <el-button type="primary" @click="openModal('create')" v-hasPermi="['system:dict:create']">
+        <el-button
+          type="primary"
+          plain
+          @click="openModal('create')"
+          v-hasPermi="['system:dict:create']"
+        >
           <Icon icon="ep:plus" class="mr-5px" /> 新增
         </el-button>
         <el-button
diff --git a/src/views/system/errorCode/form.vue b/src/views/system/errorCode/form.vue
index f261ced1..3629168c 100644
--- a/src/views/system/errorCode/form.vue
+++ b/src/views/system/errorCode/form.vue
@@ -1,5 +1,5 @@
 <template>
-  <Dialog :title="modelTitle" v-model="modelVisible">
+  <Dialog :title="dialogTitle" v-model="dialogVisible">
     <el-form
       ref="formRef"
       :model="formData"
@@ -22,7 +22,7 @@
     </el-form>
     <template #footer>
       <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
-      <el-button @click="modelVisible = false">取 消</el-button>
+      <el-button @click="dialogVisible = false">取 消</el-button>
     </template>
   </Dialog>
 </template>
@@ -32,8 +32,8 @@ import * as ErrorCodeApi from '@/api/system/errorCode'
 const { t } = useI18n() // 国际化
 const message = useMessage() // 消息弹窗
 
-const modelVisible = ref(false) // 弹窗的是否展示
-const modelTitle = ref('') // 弹窗的标题
+const dialogVisible = ref(false) // 弹窗的是否展示
+const dialogTitle = ref('') // 弹窗的标题
 const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
 const formType = ref('') // 表单的类型:create - 新增;update - 修改
 // 表单参数
@@ -54,8 +54,8 @@ const formRef = ref() // 表单 Ref
 
 /** 打开弹窗 */
 const openModal = async (type: string, id?: number) => {
-  modelVisible.value = true
-  modelTitle.value = t('action.' + type)
+  dialogVisible.value = true
+  dialogTitle.value = t('action.' + type)
   formType.value = type
   resetForm()
   // 修改时,设置数据
@@ -88,7 +88,7 @@ const submitForm = async () => {
       await ErrorCodeApi.updateErrorCodeApi(data)
       message.success(t('common.updateSuccess'))
     }
-    modelVisible.value = false
+    dialogVisible.value = false
     // 发送操作成功的事件
     emit('success')
   } finally {
diff --git a/src/views/system/errorCode/index.vue b/src/views/system/errorCode/index.vue
index c95d652c..f3105d3a 100644
--- a/src/views/system/errorCode/index.vue
+++ b/src/views/system/errorCode/index.vue
@@ -61,6 +61,7 @@
         <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
         <el-button
           type="primary"
+          plain
           @click="openModal('create')"
           v-hasPermi="['system:error-code:create']"
         >
@@ -121,8 +122,7 @@
       </el-table-column>
     </el-table>
     <!-- 分页组件 -->
-    <pagination
-      v-show="total > 0"
+    <Pagination
       :total="total"
       v-model:page="queryParams.pageNo"
       v-model:limit="queryParams.pageSize"
diff --git a/src/views/system/loginlog/LoginLogDetail.vue b/src/views/system/loginlog/LoginLogDetail.vue
index f0890eca..3a8157ce 100644
--- a/src/views/system/loginlog/LoginLogDetail.vue
+++ b/src/views/system/loginlog/LoginLogDetail.vue
@@ -1,5 +1,5 @@
 <template>
-  <Dialog title="详情" v-model="modelVisible" width="800">
+  <Dialog title="详情" v-model="dialogVisible" width="800">
     <el-descriptions border :column="1">
       <el-descriptions-item label="日志编号" min-width="120">
         {{ detailData.id }}
@@ -30,13 +30,13 @@ import { DICT_TYPE } from '@/utils/dict'
 import { formatDate } from '@/utils/formatTime'
 import * as LoginLogApi from '@/api/system/loginLog'
 
-const modelVisible = ref(false) // 弹窗的是否展示
+const dialogVisible = ref(false) // 弹窗的是否展示
 const detailLoading = ref(false) // 表单的加载中
 const detailData = ref() // 详情数据
 
 /** 打开弹窗 */
 const open = async (data: LoginLogApi.LoginLogVO) => {
-  modelVisible.value = true
+  dialogVisible.value = true
   // 设置数据
   detailLoading.value = true
   try {
diff --git a/src/views/system/mail/account/form.vue b/src/views/system/mail/account/form.vue
index 78d7cf0d..3747d17f 100644
--- a/src/views/system/mail/account/form.vue
+++ b/src/views/system/mail/account/form.vue
@@ -1,9 +1,9 @@
 <template>
-  <Dialog :title="modelTitle" v-model="modelVisible">
+  <Dialog :title="dialogTitle" v-model="dialogVisible">
     <Form ref="formRef" :schema="allSchemas.formSchema" :rules="rules" v-loading="formLoading" />
     <template #footer>
       <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
-      <el-button @click="modelVisible = false">取 消</el-button>
+      <el-button @click="dialogVisible = false">取 消</el-button>
     </template>
   </Dialog>
 </template>
@@ -14,16 +14,16 @@ import { rules, allSchemas } from './account.data'
 const { t } = useI18n() // 国际化
 const message = useMessage() // 消息弹窗
 
-const modelVisible = ref(false) // 弹窗的是否展示
-const modelTitle = ref('') // 弹窗的标题
+const dialogVisible = ref(false) // 弹窗的是否展示
+const dialogTitle = ref('') // 弹窗的标题
 const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
 const formType = ref('') // 表单的类型:create - 新增;update - 修改
 const formRef = ref() // 表单 Ref
 
 /** 打开弹窗 */
 const openModal = async (type: string, id?: number) => {
-  modelVisible.value = true
-  modelTitle.value = t('action.' + type)
+  dialogVisible.value = true
+  dialogTitle.value = t('action.' + type)
   formType.value = type
   // 修改时,设置数据
   if (id) {
@@ -56,7 +56,7 @@ const submitForm = async () => {
       await MailAccountApi.updateMailAccount(data)
       message.success(t('common.updateSuccess'))
     }
-    modelVisible.value = false
+    dialogVisible.value = false
     // 发送操作成功的事件
     emit('success')
   } finally {
diff --git a/src/views/system/mail/account/index.vue b/src/views/system/mail/account/index.vue
index 1f80684f..24d06c5f 100644
--- a/src/views/system/mail/account/index.vue
+++ b/src/views/system/mail/account/index.vue
@@ -6,6 +6,7 @@
       <template #actionMore>
         <el-button
           type="primary"
+          plain
           @click="openModal('create')"
           v-hasPermi="['system:mail-account:create']"
         >
diff --git a/src/views/system/mail/log/detail.vue b/src/views/system/mail/log/detail.vue
index 1795f751..eaf8cf84 100644
--- a/src/views/system/mail/log/detail.vue
+++ b/src/views/system/mail/log/detail.vue
@@ -1,5 +1,5 @@
 <template>
-  <Dialog title="详情" v-model="modelVisible" :scroll="true" :max-height="500">
+  <Dialog title="详情" v-model="dialogVisible" :scroll="true" :max-height="500">
     <Descriptions :schema="allSchemas.detailSchema" :data="detailData">
       <!-- 展示 HTML 内容 -->
       <template #templateContent="{ row }">
@@ -12,13 +12,13 @@
 import * as MailLogApi from '@/api/system/mail/log'
 import { allSchemas } from './log.data'
 
-const modelVisible = ref(false) // 弹窗的是否展示
+const dialogVisible = ref(false) // 弹窗的是否展示
 const detailLoading = ref(false) // 表单的加载中
 const detailData = ref() // 详情数据
 
 /** 打开弹窗 */
 const openModal = async (id: number) => {
-  modelVisible.value = true
+  dialogVisible.value = true
   // 设置数据
   detailLoading.value = true
   try {
diff --git a/src/views/system/mail/template/form.vue b/src/views/system/mail/template/form.vue
index 92f3c5c1..f1b8f9a2 100644
--- a/src/views/system/mail/template/form.vue
+++ b/src/views/system/mail/template/form.vue
@@ -1,9 +1,9 @@
 <template>
-  <Dialog :title="modelTitle" v-model="modelVisible" :scroll="true" :width="800" :max-height="500">
+  <Dialog :title="dialogTitle" v-model="dialogVisible" :scroll="true" :width="800" :max-height="500">
     <Form ref="formRef" :schema="allSchemas.formSchema" :rules="rules" v-loading="formLoading" />
     <template #footer>
       <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
-      <el-button @click="modelVisible = false">取 消</el-button>
+      <el-button @click="dialogVisible = false">取 消</el-button>
     </template>
   </Dialog>
 </template>
@@ -14,16 +14,16 @@ import { rules, allSchemas } from './template.data'
 const { t } = useI18n() // 国际化
 const message = useMessage() // 消息弹窗
 
-const modelVisible = ref(false) // 弹窗的是否展示
-const modelTitle = ref('') // 弹窗的标题
+const dialogVisible = ref(false) // 弹窗的是否展示
+const dialogTitle = ref('') // 弹窗的标题
 const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
 const formType = ref('') // 表单的类型:create - 新增;update - 修改
 const formRef = ref() // 表单 Ref
 
 /** 打开弹窗 */
 const openModal = async (type: string, id?: number) => {
-  modelVisible.value = true
-  modelTitle.value = t('action.' + type)
+  dialogVisible.value = true
+  dialogTitle.value = t('action.' + type)
   formType.value = type
   // 修改时,设置数据
   if (id) {
@@ -56,7 +56,7 @@ const submitForm = async () => {
       await MailTemplateApi.updateMailTemplate(data)
       message.success(t('common.updateSuccess'))
     }
-    modelVisible.value = false
+    dialogVisible.value = false
     // 发送操作成功的事件
     emit('success')
   } finally {
diff --git a/src/views/system/mail/template/index.vue b/src/views/system/mail/template/index.vue
index b9a5040b..51531c62 100644
--- a/src/views/system/mail/template/index.vue
+++ b/src/views/system/mail/template/index.vue
@@ -6,6 +6,7 @@
       <template #actionMore>
         <el-button
           type="primary"
+          plain
           @click="openModal('create')"
           v-hasPermi="['system:mail-account:create']"
         >
diff --git a/src/views/system/mail/template/send.vue b/src/views/system/mail/template/send.vue
index b4b411b9..19a1c23d 100644
--- a/src/views/system/mail/template/send.vue
+++ b/src/views/system/mail/template/send.vue
@@ -1,5 +1,5 @@
 <template>
-  <Dialog title="测试" v-model="modelVisible">
+  <Dialog title="测试" v-model="dialogVisible">
     <el-form
       ref="formRef"
       :model="formData"
@@ -27,7 +27,7 @@
     </el-form>
     <template #footer>
       <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
-      <el-button @click="modelVisible = false">取 消</el-button>
+      <el-button @click="dialogVisible = false">取 消</el-button>
     </template>
   </Dialog>
 </template>
@@ -36,7 +36,7 @@ import * as MailTemplateApi from '@/api/system/mail/template'
 
 const message = useMessage() // 消息弹窗
 
-const modelVisible = ref(false) // 弹窗的是否展示
+const dialogVisible = ref(false) // 弹窗的是否展示
 const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
 const formData = ref({
   content: '',
@@ -54,7 +54,7 @@ const formRef = ref() // 表单 Ref
 
 /** 打开弹窗 */
 const openModal = async (id: number) => {
-  modelVisible.value = true
+  dialogVisible.value = true
   resetForm()
   // 设置数据
   formLoading.value = true
@@ -92,7 +92,7 @@ const submitForm = async () => {
     if (logId) {
       message.success('提交发送成功!发送结果,见发送日志编号:' + logId)
     }
-    modelVisible.value = false
+    dialogVisible.value = false
   } finally {
     formLoading.value = false
   }
diff --git a/src/views/system/menu/MenuForm.vue b/src/views/system/menu/MenuForm.vue
index 45bcedfb..1c6f2caf 100644
--- a/src/views/system/menu/MenuForm.vue
+++ b/src/views/system/menu/MenuForm.vue
@@ -1,5 +1,5 @@
 <template>
-  <Dialog :title="modelTitle" v-model="modelVisible">
+  <Dialog :title="dialogTitle" v-model="dialogVisible">
     <el-form
       ref="formRef"
       :model="formData"
@@ -108,7 +108,7 @@
     </el-form>
     <template #footer>
       <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
-      <el-button @click="modelVisible = false">取 消</el-button>
+      <el-button @click="dialogVisible = false">取 消</el-button>
     </template>
   </Dialog>
 </template>
@@ -122,8 +122,8 @@ const { wsCache } = useCache()
 const { t } = useI18n() // 国际化
 const message = useMessage() // 消息弹窗
 
-const modelVisible = ref(false) // 弹窗的是否展示
-const modelTitle = ref('') // 弹窗的标题
+const dialogVisible = ref(false) // 弹窗的是否展示
+const dialogTitle = ref('') // 弹窗的标题
 const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
 const formType = ref('') // 表单的类型:create - 新增;update - 修改
 const formData = ref({
@@ -152,8 +152,8 @@ const formRef = ref() // 表单 Ref
 
 /** 打开弹窗 */
 const open = async (type: string, id?: number, parentId?: number) => {
-  modelVisible.value = true
-  modelTitle.value = t('action.' + type)
+  dialogVisible.value = true
+  dialogTitle.value = t('action.' + type)
   formType.value = type
   resetForm()
   if (parentId) {
@@ -205,7 +205,7 @@ const submitForm = async () => {
       await MenuApi.updateMenu(data)
       message.success(t('common.updateSuccess'))
     }
-    modelVisible.value = false
+    dialogVisible.value = false
     // 发送操作成功的事件
     emit('success')
   } finally {
diff --git a/src/views/system/notice/form.vue b/src/views/system/notice/form.vue
index 87e75623..92f99dc9 100644
--- a/src/views/system/notice/form.vue
+++ b/src/views/system/notice/form.vue
@@ -1,5 +1,5 @@
 <template>
-  <Dialog :title="modelTitle" v-model="modelVisible" width="800">
+  <Dialog :title="dialogTitle" v-model="dialogVisible" width="800">
     <el-form
       ref="formRef"
       :model="formData"
@@ -39,7 +39,7 @@
     </el-form>
     <template #footer>
       <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
-      <el-button @click="modelVisible = false">取 消</el-button>
+      <el-button @click="dialogVisible = false">取 消</el-button>
     </template>
   </Dialog>
 </template>
@@ -49,8 +49,8 @@ import * as NoticeApi from '@/api/system/notice'
 const { t } = useI18n() // 国际化
 const message = useMessage() // 消息弹窗
 
-const modelVisible = ref(false) // 弹窗的是否展示
-const modelTitle = ref('') // 弹窗的标题
+const dialogVisible = ref(false) // 弹窗的是否展示
+const dialogTitle = ref('') // 弹窗的标题
 const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
 const formType = ref('') // 表单的类型:create - 新增;update - 修改
 const formData = ref({
@@ -71,8 +71,8 @@ const formRef = ref() // 表单 Ref
 
 /** 打开弹窗 */
 const openModal = async (type: string, id?: number) => {
-  modelVisible.value = true
-  modelTitle.value = t('action.' + type)
+  dialogVisible.value = true
+  dialogTitle.value = t('action.' + type)
   formType.value = type
   resetForm()
   // 修改时,设置数据
@@ -105,7 +105,7 @@ const submitForm = async () => {
       await NoticeApi.updateNotice(data)
       message.success(t('common.updateSuccess'))
     }
-    modelVisible.value = false
+    dialogVisible.value = false
     // 发送操作成功的事件
     emit('success')
   } finally {
diff --git a/src/views/system/notice/index.vue b/src/views/system/notice/index.vue
index 65076f9f..d76bd520 100644
--- a/src/views/system/notice/index.vue
+++ b/src/views/system/notice/index.vue
@@ -37,6 +37,7 @@
         <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
         <el-button
           type="primary"
+          plain
           @click="openModal('create')"
           v-hasPermi="['system:notice:create']"
         >
@@ -114,11 +115,11 @@ const loading = ref(true) // 列表的加载中
 const total = ref(0) // 列表的总页数
 const list = ref([]) // 列表的数据
 const queryParams = reactive({
+  pageNo: 1,
+  pageSize: 10,
   title: '',
   type: undefined,
-  status: undefined,
-  pageNo: 1,
-  pageSize: 100
+  status: undefined
 })
 const queryFormRef = ref() // 搜索的表单
 
@@ -127,7 +128,6 @@ const getList = async () => {
   loading.value = true
   try {
     const data = await NoticeApi.getNoticePage(queryParams)
-
     list.value = data.list
     total.value = data.total
   } finally {
diff --git a/src/views/system/notify/message/NotifyMessageDetail.vue b/src/views/system/notify/message/NotifyMessageDetail.vue
index 283575bb..0a29ebb1 100644
--- a/src/views/system/notify/message/NotifyMessageDetail.vue
+++ b/src/views/system/notify/message/NotifyMessageDetail.vue
@@ -1,5 +1,5 @@
 <template>
-  <Dialog title="详情" v-model="modelVisible" :scroll="true" :max-height="500">
+  <Dialog title="详情" v-model="dialogVisible" :scroll="true" :max-height="500">
     <el-descriptions border :column="1">
       <el-descriptions-item label="编号" min-width="120">
         {{ detailData.id }}
@@ -45,13 +45,13 @@ import { DICT_TYPE } from '@/utils/dict'
 import { formatDate } from '@/utils/formatTime'
 import * as NotifyMessageApi from '@/api/system/notify/message'
 
-const modelVisible = ref(false) // 弹窗的是否展示
+const dialogVisible = ref(false) // 弹窗的是否展示
 const detailLoading = ref(false) // 表单的加载中
 const detailData = ref() // 详情数据
 
 /** 打开弹窗 */
 const open = async (data: NotifyMessageApi.NotifyMessageVO) => {
-  modelVisible.value = true
+  dialogVisible.value = true
   // 设置数据
   detailLoading.value = true
   try {
diff --git a/src/views/system/notify/my/MyNotifyMessageDetail.vue b/src/views/system/notify/my/MyNotifyMessageDetail.vue
index 45af259d..bcad4711 100644
--- a/src/views/system/notify/my/MyNotifyMessageDetail.vue
+++ b/src/views/system/notify/my/MyNotifyMessageDetail.vue
@@ -1,5 +1,5 @@
 <template>
-  <Dialog title="消息详情" v-model="modelVisible" :scroll="true" :max-height="500">
+  <Dialog title="消息详情" v-model="dialogVisible" :scroll="true" :max-height="500">
     <el-descriptions border :column="1">
       <el-descriptions-item label="发送人">
         {{ detailData.templateNickname }}
@@ -27,13 +27,13 @@ import { DICT_TYPE } from '@/utils/dict'
 import { formatDate } from '@/utils/formatTime'
 import * as NotifyMessageApi from '@/api/system/notify/message'
 
-const modelVisible = ref(false) // 弹窗的是否展示
+const dialogVisible = ref(false) // 弹窗的是否展示
 const detailLoading = ref(false) // 表单的加载中
 const detailData = ref() // 详情数据
 
 /** 打开弹窗 */
 const open = async (data: NotifyMessageApi.NotifyMessageVO) => {
-  modelVisible.value = true
+  dialogVisible.value = true
   // 设置数据
   detailLoading.value = true
   try {
diff --git a/src/views/system/notify/template/index.vue b/src/views/system/notify/template/index.vue
index c4113924..de14d5ca 100644
--- a/src/views/system/notify/template/index.vue
+++ b/src/views/system/notify/template/index.vue
@@ -46,7 +46,7 @@
   </ContentWrap>
 
   <!-- 添加/修改的弹窗 -->
-  <XModal id="templateModel" :loading="modelLoading" v-model="modelVisible" :title="modelTitle">
+  <XModal id="templateModel" :loading="modelLoading" v-model="dialogVisible" :title="dialogTitle">
     <!-- 表单:添加/修改 -->
     <Form
       ref="formRef"
@@ -70,7 +70,7 @@
         @click="submitForm()"
       />
       <!-- 按钮:关闭 -->
-      <XButton :loading="actionLoading" :title="t('dialog.close')" @click="modelVisible = false" />
+      <XButton :loading="actionLoading" :title="t('dialog.close')" @click="dialogVisible = false" />
     </template>
   </XModal>
 
@@ -132,8 +132,8 @@ const [registerTable, { reload, deleteData }] = useXTable({
 })
 
 // 弹窗相关的变量
-const modelVisible = ref(false) // 是否显示弹出层
-const modelTitle = ref('edit') // 弹出层标题
+const dialogVisible = ref(false) // 是否显示弹出层
+const dialogTitle = ref('edit') // 弹出层标题
 const modelLoading = ref(false) // 弹出层loading
 const actionType = ref('') // 操作按钮的类型
 const actionLoading = ref(false) // 按钮 Loading
@@ -143,9 +143,9 @@ const detailData = ref() // 详情 Ref
 // 设置标题
 const setDialogTile = (type: string) => {
   modelLoading.value = true
-  modelTitle.value = t('action.' + type)
+  dialogTitle.value = t('action.' + type)
   actionType.value = type
-  modelVisible.value = true
+  dialogVisible.value = true
 }
 
 // 新增操作
@@ -188,7 +188,7 @@ const submitForm = async () => {
           await NotifyTemplateApi.updateNotifyTemplateApi(data)
           message.success(t('common.updateSuccess'))
         }
-        modelVisible.value = false
+        dialogVisible.value = false
       } finally {
         actionLoading.value = false
         // 刷新列表
diff --git a/src/views/system/oauth2/client/form.vue b/src/views/system/oauth2/client/ClientForm.vue
similarity index 86%
rename from src/views/system/oauth2/client/form.vue
rename to src/views/system/oauth2/client/ClientForm.vue
index 0822e59f..b5936c37 100644
--- a/src/views/system/oauth2/client/form.vue
+++ b/src/views/system/oauth2/client/ClientForm.vue
@@ -1,10 +1,10 @@
 <template>
-  <Dialog :title="modelTitle" v-model="modelVisible" width="800">
+  <Dialog :title="dialogTitle" v-model="dialogVisible" scroll max-height="500px">
     <el-form
       ref="formRef"
       :model="formData"
       :rules="formRules"
-      label-width="120px"
+      label-width="160px"
       v-loading="formLoading"
     >
       <el-form-item label="客户端编号" prop="secret">
@@ -25,11 +25,12 @@
       <el-form-item label="状态" prop="status">
         <el-radio-group v-model="formData.status">
           <el-radio
-            v-for="dict in getDictOptions(DICT_TYPE.COMMON_STATUS)"
+            v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)"
             :key="dict.value"
-            :label="parseInt(dict.value)"
-            >{{ dict.label }}</el-radio
+            :label="dict.value"
           >
+            {{ dict.label }}
+          </el-radio>
         </el-radio-group>
       </el-form-item>
       <el-form-item label="访问令牌的有效期" prop="accessTokenValiditySeconds">
@@ -47,7 +48,7 @@
           style="width: 500px"
         >
           <el-option
-            v-for="dict in getDictOptions(DICT_TYPE.SYSTEM_OAUTH2_GRANT_TYPE)"
+            v-for="dict in getIntDictOptions(DICT_TYPE.SYSTEM_OAUTH2_GRANT_TYPE)"
             :key="dict.value"
             :label="dict.label"
             :value="dict.value"
@@ -137,22 +138,20 @@
       </el-form-item>
     </el-form>
     <template #footer>
-      <div class="dialog-footer">
-        <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
-        <el-button @click="modelVisible = false">取 消</el-button>
-      </div>
+      <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
+      <el-button @click="dialogVisible = false">取 消</el-button>
     </template>
   </Dialog>
 </template>
 <script setup lang="ts">
-import { DICT_TYPE, getDictOptions } from '@/utils/dict'
+import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
+import { CommonStatusEnum } from '@/utils/constants'
 import * as ClientApi from '@/api/system/oauth2/client'
-import UploadImg from '@/components/UploadFile'
 const { t } = useI18n() // 国际化
 const message = useMessage() // 消息弹窗
 
-const modelVisible = ref(false) // 弹窗的是否展示
-const modelTitle = ref('') // 弹窗的标题
+const dialogVisible = ref(false) // 弹窗的是否展示
+const dialogTitle = ref('') // 弹窗的标题
 const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
 const formType = ref('') // 表单的类型:create - 新增;update - 修改
 const formData = ref({
@@ -162,7 +161,7 @@ const formData = ref({
   name: undefined,
   logo: undefined,
   description: undefined,
-  status: DICT_TYPE.COMMON_STATUS,
+  status: CommonStatusEnum.ENABLE,
   accessTokenValiditySeconds: 30 * 60,
   refreshTokenValiditySeconds: 30 * 24 * 60,
   redirectUris: [],
@@ -191,22 +190,22 @@ const formRules = reactive({
 const formRef = ref() // 表单 Ref
 
 /** 打开弹窗 */
-const openModal = async (type: string, id?: number) => {
-  modelVisible.value = true
-  modelTitle.value = t('action.' + type)
+const open = async (type: string, id?: number) => {
+  dialogVisible.value = true
+  dialogTitle.value = t('action.' + type)
   formType.value = type
   resetForm()
   // 修改时,设置数据
   if (id) {
     formLoading.value = true
     try {
-      formData.value = await ClientApi.getOAuth2ClientApi(id)
+      formData.value = await ClientApi.getOAuth2Client(id)
     } finally {
       formLoading.value = false
     }
   }
 }
-defineExpose({ openModal }) // 提供 openModal 方法,用于打开弹窗
+defineExpose({ open }) // 提供 open 方法,用于打开弹窗
 
 /** 提交表单 */
 const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
@@ -220,13 +219,13 @@ const submitForm = async () => {
   try {
     const data = formData.value as unknown as ClientApi.OAuth2ClientVO
     if (formType.value === 'create') {
-      await ClientApi.createOAuth2ClientApi(data)
+      await ClientApi.createOAuth2Client(data)
       message.success(t('common.createSuccess'))
     } else {
-      await ClientApi.updateOAuth2ClientApi(data)
+      await ClientApi.updateOAuth2Client(data)
       message.success(t('common.updateSuccess'))
     }
-    modelVisible.value = false
+    dialogVisible.value = false
     // 发送操作成功的事件
     emit('success')
   } finally {
@@ -243,7 +242,7 @@ const resetForm = () => {
     name: undefined,
     logo: undefined,
     description: undefined,
-    status: DICT_TYPE.COMMON_STATUS,
+    status: CommonStatusEnum.ENABLE,
     accessTokenValiditySeconds: 30 * 60,
     refreshTokenValiditySeconds: 30 * 24 * 60,
     redirectUris: [],
diff --git a/src/views/system/oauth2/client/index.vue b/src/views/system/oauth2/client/index.vue
index c88af726..eab58726 100644
--- a/src/views/system/oauth2/client/index.vue
+++ b/src/views/system/oauth2/client/index.vue
@@ -1,206 +1,185 @@
 <template>
-  <ContentWrap>
-    <!-- 列表 -->
-    <XTable @register="registerTable">
-      <template #toolbar_buttons>
-        <!-- 操作:新增 -->
-        <XButton
-          type="primary"
-          preIcon="ep:zoom-in"
-          :title="t('action.add')"
-          v-hasPermi="['system:oauth2-client:create']"
-          @click="handleCreate()"
-        />
-      </template>
-      <template #accessTokenValiditySeconds_default="{ row }">
-        {{ row.accessTokenValiditySeconds + '秒' }}
-      </template>
-      <template #refreshTokenValiditySeconds_default="{ row }">
-        {{ row.refreshTokenValiditySeconds + '秒' }}
-      </template>
-      <template #authorizedGrantTypes_default="{ row }">
-        <el-tag
-          :disable-transitions="true"
-          :key="index"
-          v-for="(authorizedGrantType, index) in row.authorizedGrantTypes"
-          :index="index"
-        >
-          {{ authorizedGrantType }}
-        </el-tag>
-      </template>
-      <template #actionbtns_default="{ row }">
-        <!-- 操作:修改 -->
-        <XTextButton
-          preIcon="ep:edit"
-          :title="t('action.edit')"
-          v-hasPermi="['system:oauth2-client:update']"
-          @click="handleUpdate(row.id)"
-        />
-        <!-- 操作:详情 -->
-        <XTextButton
-          preIcon="ep:view"
-          :title="t('action.detail')"
-          v-hasPermi="['system:oauth2-client:query']"
-          @click="handleDetail(row.id)"
-        />
-        <!-- 操作:删除 -->
-        <XTextButton
-          preIcon="ep:delete"
-          :title="t('action.del')"
-          v-hasPermi="['system:oauth2-client:delete']"
-          @click="deleteData(row.id)"
-        />
-      </template>
-    </XTable>
-  </ContentWrap>
-  <!-- 弹窗 -->
-  <XModal id="postModel" v-model="dialogVisible" :title="dialogTitle">
-    <!-- 表单:添加/修改 -->
-    <Form
-      ref="formRef"
-      v-if="['create', 'update'].includes(actionType)"
-      :schema="allSchemas.formSchema"
-      :rules="rules"
-    />
-    <!-- 表单:详情 -->
-    <Descriptions
-      v-if="actionType === 'detail'"
-      :schema="allSchemas.detailSchema"
-      :data="detailData"
+  <!-- 搜索 -->
+  <content-wrap>
+    <el-form
+      class="-mb-15px"
+      :model="queryParams"
+      ref="queryFormRef"
+      :inline="true"
+      label-width="68px"
     >
-      <template #accessTokenValiditySeconds="{ row }">
-        {{ row.accessTokenValiditySeconds + '秒' }}
-      </template>
-      <template #refreshTokenValiditySeconds="{ row }">
-        {{ row.refreshTokenValiditySeconds + '秒' }}
-      </template>
-      <template #authorizedGrantTypes="{ row }">
-        <el-tag
-          :disable-transitions="true"
-          :key="index"
-          v-for="(authorizedGrantType, index) in row.authorizedGrantTypes"
-          :index="index"
+      <el-form-item label="应用名" prop="name">
+        <el-input
+          v-model="queryParams.name"
+          placeholder="请输入应用名"
+          clearable
+          @keyup.enter="handleQuery"
+          class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item label="状态" prop="status">
+        <el-select v-model="queryParams.status" placeholder="请选择状态" clearable class="!w-240px">
+          <el-option
+            v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)"
+            :key="dict.value"
+            :label="dict.label"
+            :value="dict.value"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item>
+        <el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
+        <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
+        <el-button
+          plain
+          type="primary"
+          @click="openForm('create')"
+          v-hasPermi="['system:oauth2-client:create']"
         >
-          {{ authorizedGrantType }}
-        </el-tag>
-      </template>
-      <template #scopes="{ row }">
-        <el-tag
-          :disable-transitions="true"
-          :key="index"
-          v-for="(scopes, index) in row.scopes"
-          :index="index"
-        >
-          {{ scopes }}
-        </el-tag>
-      </template>
-      <template #autoApproveScopes="{ row }">
-        <el-tag
-          :disable-transitions="true"
-          :key="index"
-          v-for="(autoApproveScopes, index) in row.autoApproveScopes"
-          :index="index"
-        >
-          {{ autoApproveScopes }}
-        </el-tag>
-      </template>
-      <template #redirectUris="{ row }">
-        <el-tag
-          :disable-transitions="true"
-          :key="index"
-          v-for="(redirectUris, index) in row.redirectUris"
-          :index="index"
-        >
-          {{ redirectUris }}
-        </el-tag>
-      </template>
-    </Descriptions>
-    <template #footer>
-      <!-- 按钮:保存 -->
-      <XButton
-        v-if="['create', 'update'].includes(actionType)"
-        type="primary"
-        :title="t('action.save')"
-        :loading="actionLoading"
-        @click="submitForm()"
+          <Icon icon="ep:plus" class="mr-5px" /> 新增
+        </el-button>
+      </el-form-item>
+    </el-form>
+  </content-wrap>
+
+  <!-- 列表 -->
+  <content-wrap>
+    <el-table v-loading="loading" :data="list">
+      <el-table-column label="客户端编号" align="center" prop="clientId" />
+      <el-table-column label="客户端密钥" align="center" prop="secret" />
+      <el-table-column label="应用名" align="center" prop="name" />
+      <el-table-column label="应用图标" align="center" prop="logo">
+        <template #default="scope">
+          <img width="40px" height="40px" :src="scope.row.logo" />
+        </template>
+      </el-table-column>
+      <el-table-column label="状态" align="center" prop="status">
+        <template #default="scope">
+          <dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status" />
+        </template>
+      </el-table-column>
+      <el-table-column label="访问令牌的有效期" align="center" prop="accessTokenValiditySeconds">
+        <template #default="scope">{{ scope.row.accessTokenValiditySeconds }} 秒</template>
+      </el-table-column>
+      <el-table-column label="刷新令牌的有效期" align="center" prop="refreshTokenValiditySeconds">
+        <template #default="scope">{{ scope.row.refreshTokenValiditySeconds }} 秒</template>
+      </el-table-column>
+      <el-table-column label="授权类型" align="center" prop="authorizedGrantTypes">
+        <template #default="scope">
+          <el-tag
+            :disable-transitions="true"
+            :key="index"
+            v-for="(authorizedGrantType, index) in scope.row.authorizedGrantTypes"
+            :index="index"
+          >
+            {{ authorizedGrantType }}
+          </el-tag>
+        </template>
+      </el-table-column>
+      <el-table-column
+        label="创建时间"
+        align="center"
+        prop="createTime"
+        width="180"
+        :formatter="dateFormatter"
       />
-      <!-- 按钮:关闭 -->
-      <XButton :loading="actionLoading" :title="t('dialog.close')" @click="dialogVisible = false" />
-    </template>
-  </XModal>
+      <el-table-column label="操作" align="center">
+        <template #default="scope">
+          <el-button
+            link
+            type="primary"
+            @click="openForm('update', scope.row.id)"
+            v-hasPermi="['system:oauth2-client:update']"
+          >
+            编辑
+          </el-button>
+          <el-button
+            link
+            type="danger"
+            @click="handleDelete(scope.row.id)"
+            v-hasPermi="['system:oauth2-client:delete']"
+          >
+            删除
+          </el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+    <!-- 分页 -->
+    <Pagination
+      :total="total"
+      v-model:page="queryParams.pageNo"
+      v-model:limit="queryParams.pageSize"
+      @pagination="getList"
+    />
+  </content-wrap>
+
+  <!-- 表单弹窗:添加/修改 -->
+  <ClientForm ref="formRef" @success="getList" />
 </template>
-<script setup lang="ts" name="Client">
-import type { FormExpose } from '@/components/Form'
-// 业务相关的 import
+<script setup lang="ts">
+import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
+import { dateFormatter } from '@/utils/formatTime'
 import * as ClientApi from '@/api/system/oauth2/client'
-
-const { t } = useI18n() // 国际化
+import ClientForm from './ClientForm.vue'
 const message = useMessage() // 消息弹窗
+const { t } = useI18n() // 国际化
 
-// 列表相关的变量
-const [registerTable, { reload, deleteData }] = useXTable({
-  allSchemas: allSchemas,
-  getListApi: ClientApi.getOAuth2ClientPageApi,
-  deleteApi: ClientApi.deleteOAuth2ClientApi
+const loading = ref(true) // 列表的加载中
+const total = ref(0) // 列表的总页数
+const list = ref([]) // 列表的数据
+const queryParams = reactive({
+  pageNo: 1,
+  pageSize: 10,
+  name: null,
+  status: null
 })
-// 弹窗相关的变量
-const dialogVisible = ref(false) // 是否显示弹出层
-const dialogTitle = ref('edit') // 弹出层标题
-const actionType = ref('') // 操作按钮的类型
-const actionLoading = ref(false) // 按钮 Loading
-const formRef = ref<FormExpose>() // 表单 Ref
-const detailData = ref() // 详情 Ref
-// 设置标题
-const setDialogTile = (type: string) => {
-  dialogTitle.value = t('action.' + type)
-  actionType.value = type
-  dialogVisible.value = true
+const queryFormRef = ref() // 搜索的表单
+
+/** 查询列表 */
+const getList = async () => {
+  loading.value = true
+  try {
+    const data = await ClientApi.getOAuth2ClientPage(queryParams)
+    list.value = data.list
+    total.value = data.total
+  } finally {
+    loading.value = false
+  }
 }
 
-// 新增操作
-const handleCreate = () => {
-  setDialogTile('create')
+/** 搜索按钮操作 */
+const handleQuery = () => {
+  queryParams.pageNo = 1
+  getList()
 }
 
-// 修改操作
-const handleUpdate = async (rowId: number) => {
-  setDialogTile('update')
-  // 设置数据
-  const res = await ClientApi.getOAuth2ClientApi(rowId)
-  unref(formRef)?.setValues(res)
+/** 重置按钮操作 */
+const resetQuery = () => {
+  queryFormRef.value.resetFields()
+  handleQuery()
 }
 
-// 详情操作
-const handleDetail = async (rowId: number) => {
-  setDialogTile('detail')
-  const res = await ClientApi.getOAuth2ClientApi(rowId)
-  detailData.value = res
+/** 添加/修改操作 */
+const formRef = ref()
+const openForm = (type: string, id?: number) => {
+  formRef.value.open(type, id)
 }
 
-// 提交新增/修改的表单
-const submitForm = async () => {
-  const elForm = unref(formRef)?.getElFormRef()
-  if (!elForm) return
-  elForm.validate(async (valid) => {
-    if (valid) {
-      actionLoading.value = true
-      // 提交请求
-      try {
-        const data = unref(formRef)?.formModel as ClientApi.OAuth2ClientVO
-        if (actionType.value === 'create') {
-          await ClientApi.createOAuth2ClientApi(data)
-          message.success(t('common.createSuccess'))
-        } else {
-          await ClientApi.updateOAuth2ClientApi(data)
-          message.success(t('common.updateSuccess'))
-        }
-        dialogVisible.value = false
-      } finally {
-        actionLoading.value = false
-        // 刷新列表
-        await reload()
-      }
-    }
-  })
+/** 删除按钮操作 */
+const handleDelete = async (id: number) => {
+  try {
+    // 删除的二次确认
+    await message.delConfirm()
+    // 发起删除
+    await ClientApi.deleteOAuth2Client(id)
+    message.success(t('common.delSuccess'))
+    // 刷新列表
+    await getList()
+  } catch {}
 }
+
+/** 初始化 **/
+onMounted(() => {
+  getList()
+})
 </script>
diff --git a/src/views/system/operatelog/detail.vue b/src/views/system/operatelog/detail.vue
index b3603e2e..cbf22dea 100644
--- a/src/views/system/operatelog/detail.vue
+++ b/src/views/system/operatelog/detail.vue
@@ -1,5 +1,5 @@
 <template>
-  <Dialog title="详情" v-model="modelVisible" :scroll="true" :max-height="500" width="800">
+  <Dialog title="详情" v-model="dialogVisible" :scroll="true" :max-height="500" width="800">
     <el-descriptions border :column="1">
       <el-descriptions-item label="日志主键" min-width="120">
         {{ detailData.id }}
@@ -61,13 +61,13 @@
 import { formatDate } from '@/utils/formatTime'
 import * as OperateLogApi from '@/api/system/operatelog'
 
-const modelVisible = ref(false) // 弹窗的是否展示
+const dialogVisible = ref(false) // 弹窗的是否展示
 const detailLoading = ref(false) // 表单的加载中
 const detailData = ref() // 详情数据
 
 /** 打开弹窗 */
 const openModal = async (data: OperateLogApi.OperateLogVO) => {
-  modelVisible.value = true
+  dialogVisible.value = true
   // 设置数据
   detailLoading.value = true
   try {
diff --git a/src/views/system/post/PostForm.vue b/src/views/system/post/PostForm.vue
index a9dec8b0..70103906 100644
--- a/src/views/system/post/PostForm.vue
+++ b/src/views/system/post/PostForm.vue
@@ -1,5 +1,5 @@
 <template>
-  <Dialog :title="modelTitle" v-model="modelVisible" width="800">
+  <Dialog :title="dialogTitle" v-model="dialogVisible" width="800">
     <el-form
       ref="formRef"
       :model="formData"
@@ -29,7 +29,7 @@
     </el-form>
     <template #footer>
       <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
-      <el-button @click="modelVisible = false">取 消</el-button>
+      <el-button @click="dialogVisible = false">取 消</el-button>
     </template>
   </Dialog>
 </template>
@@ -41,8 +41,8 @@ import * as PostApi from '@/api/system/post'
 const { t } = useI18n() // 国际化
 const message = useMessage() // 消息弹窗
 
-const modelVisible = ref(false) // 弹窗的是否展示
-const modelTitle = ref('') // 弹窗的标题
+const dialogVisible = ref(false) // 弹窗的是否展示
+const dialogTitle = ref('') // 弹窗的标题
 const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
 const formType = ref('') // 表单的类型:create - 新增;update - 修改
 const formData = ref({
@@ -63,8 +63,8 @@ const formRef = ref() // 表单 Ref
 
 /** 打开弹窗 */
 const openModal = async (type: string, id?: number) => {
-  modelVisible.value = true
-  modelTitle.value = t('action.' + type)
+  dialogVisible.value = true
+  dialogTitle.value = t('action.' + type)
   formType.value = type
   resetForm()
   // 修改时,设置数据
@@ -97,7 +97,7 @@ const submitForm = async () => {
       await PostApi.updatePost(data)
       message.success(t('common.updateSuccess'))
     }
-    modelVisible.value = false
+    dialogVisible.value = false
     // 发送操作成功的事件
     emit('success')
   } finally {
diff --git a/src/views/system/post/index.vue b/src/views/system/post/index.vue
index 03e491d0..4d1d306c 100644
--- a/src/views/system/post/index.vue
+++ b/src/views/system/post/index.vue
@@ -39,6 +39,7 @@
         <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
         <el-button
           type="primary"
+          plain
           @click="openModal('create')"
           v-hasPermi="['system:notice:create']"
         >
diff --git a/src/views/system/role/MenuPermissionForm.vue b/src/views/system/role/MenuPermissionForm.vue
deleted file mode 100644
index 70971781..00000000
--- a/src/views/system/role/MenuPermissionForm.vue
+++ /dev/null
@@ -1,202 +0,0 @@
-<template>
-  <Dialog :title="dialogScopeTitle" v-model="dialogScopeVisible" width="800">
-    <el-form
-      ref="menuPermissionFormRef"
-      :model="dataScopeForm"
-      :inline="true"
-      label-width="80px"
-      v-loading="formLoading"
-    >
-      <el-form-item label="角色名称">
-        <el-tag>{{ dataScopeForm.name }}</el-tag>
-      </el-form-item>
-      <el-form-item label="角色标识">
-        <el-tag>{{ dataScopeForm.code }}</el-tag>
-      </el-form-item>
-      <!-- 分配角色的数据权限对话框 -->
-      <el-form-item label="权限范围" v-if="actionScopeType === 'data'">
-        <el-select v-model="dataScopeForm.dataScope">
-          <el-option
-            v-for="item in dataScopeDictDatas"
-            :key="item.value"
-            :label="item.label"
-            :value="item.value"
-          />
-        </el-select>
-      </el-form-item>
-      <!-- 分配角色的菜单权限对话框 -->
-      <el-row>
-        <el-col :span="24">
-          <el-form-item
-            label="权限范围"
-            v-if="
-              actionScopeType === 'menu' ||
-              dataScopeForm.dataScope === SystemDataScopeEnum.DEPT_CUSTOM
-            "
-            style="display: flex"
-          >
-            <el-card class="card" shadow="never">
-              <template #header>
-                父子联动(选中父节点,自动选择子节点):
-                <el-switch
-                  v-model="checkStrictly"
-                  inline-prompt
-                  active-text="是"
-                  inactive-text="否"
-                />
-                全选/全不选:
-                <el-switch
-                  v-model="treeNodeAll"
-                  inline-prompt
-                  active-text="是"
-                  inactive-text="否"
-                  @change="handleCheckedTreeNodeAll()"
-                />
-              </template>
-              <el-tree
-                ref="treeRef"
-                node-key="id"
-                show-checkbox
-                :check-strictly="!checkStrictly"
-                :props="defaultProps"
-                :data="treeOptions"
-                empty-text="加载中,请稍后"
-              />
-            </el-card>
-          </el-form-item> </el-col
-      ></el-row>
-    </el-form>
-    <!-- 操作按钮 -->
-    <template #footer>
-      <div class="dialog-footer">
-        <el-button
-          :title="t('action.save')"
-          :loading="actionLoading"
-          @click="submitScope()"
-          type="primary"
-          :disabled="formLoading"
-        >
-          保存
-        </el-button>
-        <el-button
-          :loading="actionLoading"
-          :title="t('dialog.close')"
-          @click="dialogScopeVisible = false"
-          >取 消</el-button
-        >
-      </div>
-    </template>
-  </Dialog>
-</template>
-
-<script setup lang="ts">
-import * as RoleApi from '@/api/system/role'
-import type { ElTree } from 'element-plus'
-import type { FormExpose } from '@/components/Form'
-import { handleTree, defaultProps } from '@/utils/tree'
-import { SystemDataScopeEnum } from '@/utils/constants'
-import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
-import * as MenuApi from '@/api/system/menu'
-import * as DeptApi from '@/api/system/dept'
-import * as PermissionApi from '@/api/system/permission'
-// ========== CRUD 相关 ==========
-const actionLoading = ref(false) // 遮罩层
-const menuPermissionFormRef = ref<FormExpose>() // 表单 Ref
-const { t } = useI18n() // 国际化
-const dialogScopeTitle = ref('菜单权限')
-const dataScopeDictDatas = ref()
-const message = useMessage() // 消息弹窗
-const actionScopeType = ref('')
-// 选项
-const checkStrictly = ref(true)
-const treeNodeAll = ref(false)
-const dialogScopeVisible = ref(false) // 弹窗的是否展示
-const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
-const treeOptions = ref<any[]>([]) // 菜单树形结构
-const treeRef = ref<InstanceType<typeof ElTree>>()
-// ========== 数据权限 ==========
-const dataScopeForm = reactive({
-  id: 0,
-  name: '',
-  code: '',
-  dataScope: 0,
-  checkList: []
-})
-
-/** 打开弹窗 */
-const openModal = async (type: string, row: RoleApi.RoleVO) => {
-  dataScopeForm.id = row.id
-  dataScopeForm.name = row.name
-  dataScopeForm.code = row.code
-  actionScopeType.value = type
-  dialogScopeVisible.value = true
-  if (type === 'menu') {
-    const menuRes = await MenuApi.getSimpleMenusList()
-    treeOptions.value = handleTree(menuRes)
-    const role = await PermissionApi.listRoleMenusApi(row.id)
-    if (role) {
-      role?.forEach((item: any) => {
-        unref(treeRef)?.setChecked(item, true, false)
-      })
-    }
-  } else if (type === 'data') {
-    const deptRes = await DeptApi.getSimpleDeptList()
-    treeOptions.value = handleTree(deptRes)
-    const role = await RoleApi.getRole(row.id)
-    dataScopeForm.dataScope = role.dataScope
-    if (role.dataScopeDeptIds) {
-      role.dataScopeDeptIds?.forEach((item: any) => {
-        unref(treeRef)?.setChecked(item, true, false)
-      })
-    }
-  }
-}
-
-// 保存权限
-const submitScope = async () => {
-  if ('data' === actionScopeType.value) {
-    const data = ref<PermissionApi.PermissionAssignRoleDataScopeReqVO>({
-      roleId: dataScopeForm.id,
-      dataScope: dataScopeForm.dataScope,
-      dataScopeDeptIds:
-        dataScopeForm.dataScope !== SystemDataScopeEnum.DEPT_CUSTOM
-          ? []
-          : (treeRef.value!.getCheckedKeys(false) as unknown as Array<number>)
-    })
-    await PermissionApi.assignRoleDataScopeApi(data.value)
-  } else if ('menu' === actionScopeType.value) {
-    const data = ref<PermissionApi.PermissionAssignRoleMenuReqVO>({
-      roleId: dataScopeForm.id,
-      menuIds: [
-        ...(treeRef.value!.getCheckedKeys(false) as unknown as Array<number>),
-        ...(treeRef.value!.getHalfCheckedKeys() as unknown as Array<number>)
-      ]
-    })
-    await PermissionApi.assignRoleMenuApi(data.value)
-  }
-  message.success(t('common.updateSuccess'))
-  dialogScopeVisible.value = false
-}
-
-// 全选/全不选
-const handleCheckedTreeNodeAll = () => {
-  treeRef.value!.setCheckedNodes(treeNodeAll.value ? treeOptions.value : [])
-}
-
-const init = () => {
-  dataScopeDictDatas.value = getIntDictOptions(DICT_TYPE.SYSTEM_DATA_SCOPE)
-}
-
-defineExpose({ openModal }) // 提供 openModal 方法,用于打开弹窗
-// ========== 初始化 ==========
-onMounted(() => {
-  init()
-})
-</script>
-<style scoped>
-.card {
-  width: 100%;
-  max-height: 400px;
-  overflow-y: scroll;
-}
-</style>
diff --git a/src/views/system/role/RoleAssignMenuForm.vue b/src/views/system/role/RoleAssignMenuForm.vue
new file mode 100644
index 00000000..cc8e2708
--- /dev/null
+++ b/src/views/system/role/RoleAssignMenuForm.vue
@@ -0,0 +1,154 @@
+<template>
+  <Dialog title="菜单权限" v-model="dialogVisible">
+    <el-form ref="formRef" :model="formData" label-width="80px" v-loading="formLoading">
+      <el-form-item label="角色名称">
+        <el-tag>{{ formData.name }}</el-tag>
+      </el-form-item>
+      <el-form-item label="角色标识">
+        <el-tag>{{ formData.code }}</el-tag>
+      </el-form-item>
+      <el-form-item label="菜单权限">
+        <el-card class="cardHeight">
+          <template #header>
+            全选/全不选:
+            <el-switch
+              v-model="treeNodeAll"
+              inline-prompt
+              active-text="是"
+              inactive-text="否"
+              @change="handleCheckedTreeNodeAll"
+            />
+            全部展开/折叠:
+            <el-switch
+              v-model="menuExpand"
+              inline-prompt
+              active-text="展开"
+              inactive-text="折叠"
+              @change="handleCheckedTreeExpand"
+            />
+          </template>
+          <el-tree
+            ref="treeRef"
+            node-key="id"
+            show-checkbox
+            :props="defaultProps"
+            :data="menuOptions"
+            empty-text="加载中,请稍候"
+          />
+        </el-card>
+      </el-form-item>
+    </el-form>
+    <template #footer>
+      <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
+      <el-button @click="dialogVisible = false">取 消</el-button>
+    </template>
+  </Dialog>
+</template>
+<script setup lang="ts">
+import { handleTree, defaultProps } from '@/utils/tree'
+import * as RoleApi from '@/api/system/role'
+import * as MenuApi from '@/api/system/menu'
+import * as PermissionApi from '@/api/system/permission'
+const { t } = useI18n() // 国际化
+const message = useMessage() // 消息弹窗
+
+const dialogVisible = ref(false) // 弹窗的是否展示
+const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
+const formData = reactive({
+  id: 0,
+  name: '',
+  code: '',
+  menuIds: []
+})
+const formRef = ref() // 表单 Ref
+const menuOptions = ref<any[]>([]) // 菜单树形结构
+const menuExpand = ref(false) // 展开/折叠
+const treeRef = ref() // 菜单树组件 Ref
+const treeNodeAll = ref(false) // 全选/全不选
+
+/** 打开弹窗 */
+const open = async (row: RoleApi.RoleVO) => {
+  dialogVisible.value = true
+  resetForm()
+  // 加载 Menu 列表。注意,必须放在前面,不然下面 setChecked 没数据节点
+  menuOptions.value = handleTree(await MenuApi.getSimpleMenusList())
+  // 设置数据
+  formData.id = row.id
+  formData.name = row.name
+  formData.code = row.code
+  formLoading.value = true
+  try {
+    formData.value.menuIds = await PermissionApi.getRoleMenuList(row.id)
+    // 设置选中
+    formData.value.menuIds.forEach((menuId: number) => {
+      treeRef.value.setChecked(menuId, true, false)
+    })
+  } finally {
+    formLoading.value = false
+  }
+}
+defineExpose({ open }) // 提供 open 方法,用于打开弹窗
+
+/** 提交表单 */
+const submitForm = async () => {
+  // 校验表单
+  if (!formRef) return
+  const valid = await formRef.value.validate()
+  if (!valid) return
+  // 提交请求
+  formLoading.value = true
+  try {
+    const data = {
+      roleId: formData.id,
+      menuIds: [
+        ...(treeRef.value.getCheckedKeys(false) as unknown as Array<number>), // 获得当前选中节点
+        ...(treeRef.value.getHalfCheckedKeys() as unknown as Array<number>) // 获得半选中的父节点
+      ]
+    }
+    await PermissionApi.assignRoleMenu(data)
+    message.success(t('common.updateSuccess'))
+    dialogVisible.value = false
+  } finally {
+    formLoading.value = false
+  }
+}
+
+/** 重置表单 */
+const resetForm = () => {
+  // 重置选项
+  treeNodeAll.value = false
+  menuExpand.value = false
+  // 重置表单
+  formData.value = {
+    id: 0,
+    name: '',
+    code: '',
+    menuIds: []
+  }
+  treeRef.value?.setCheckedNodes([])
+  formRef.value?.resetFields()
+}
+
+/** 全选/全不选 */
+const handleCheckedTreeNodeAll = () => {
+  treeRef.value.setCheckedNodes(treeNodeAll.value ? menuOptions.value : [])
+}
+
+/** 展开/折叠全部 */
+const handleCheckedTreeExpand = () => {
+  const nodes = treeRef.value?.store.nodesMap
+  for (let node in nodes) {
+    if (nodes[node].expanded === menuExpand.value) {
+      continue
+    }
+    nodes[node].expanded = menuExpand.value
+  }
+}
+</script>
+<style lang="scss" scoped>
+.cardHeight {
+  width: 100%;
+  max-height: 400px;
+  overflow-y: scroll;
+}
+</style>
diff --git a/src/views/system/role/RoleDataPermissionForm.vue b/src/views/system/role/RoleDataPermissionForm.vue
new file mode 100644
index 00000000..6b017278
--- /dev/null
+++ b/src/views/system/role/RoleDataPermissionForm.vue
@@ -0,0 +1,161 @@
+<template>
+  <Dialog title="菜单权限" v-model="dialogVisible" width="800">
+    <el-form ref="formRef" :model="formData" label-width="80px" v-loading="formLoading">
+      <el-form-item label="角色名称">
+        <el-tag>{{ formData.name }}</el-tag>
+      </el-form-item>
+      <el-form-item label="角色标识">
+        <el-tag>{{ formData.code }}</el-tag>
+      </el-form-item>
+      <el-form-item label="权限范围">
+        <el-select v-model="formData.dataScope">
+          <el-option
+            v-for="item in getIntDictOptions(DICT_TYPE.SYSTEM_DATA_SCOPE)"
+            :key="item.value"
+            :label="item.label"
+            :value="item.value"
+          />
+        </el-select>
+      </el-form-item>
+    </el-form>
+    <el-form-item
+      label="权限范围"
+      v-if="formData.dataScope === SystemDataScopeEnum.DEPT_CUSTOM"
+      style="display: flex"
+    >
+      <el-card class="card" shadow="never">
+        <template #header>
+          全选/全不选:
+          <el-switch
+            v-model="treeNodeAll"
+            inline-prompt
+            active-text="是"
+            inactive-text="否"
+            @change="handleCheckedTreeNodeAll()"
+          />
+          全部展开/折叠:
+          <el-switch
+            v-model="deptExpand"
+            inline-prompt
+            active-text="展开"
+            inactive-text="折叠"
+            @change="handleCheckedTreeExpand"
+          />
+          父子联动(选中父节点,自动选择子节点):
+          <el-switch v-model="checkStrictly" inline-prompt active-text="是" inactive-text="否" />
+        </template>
+        <el-tree
+          ref="treeRef"
+          node-key="id"
+          show-checkbox
+          :check-strictly="!checkStrictly"
+          :props="defaultProps"
+          :data="deptOptions"
+          empty-text="加载中,请稍后"
+          default-expand-all
+        />
+      </el-card>
+    </el-form-item>
+    <template #footer>
+      <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
+      <el-button @click="dialogVisible = false">取 消</el-button>
+    </template>
+  </Dialog>
+</template>
+<script setup lang="ts">
+import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
+import { handleTree, defaultProps } from '@/utils/tree'
+import { SystemDataScopeEnum } from '@/utils/constants'
+import * as RoleApi from '@/api/system/role'
+import * as DeptApi from '@/api/system/dept'
+import * as PermissionApi from '@/api/system/permission'
+const { t } = useI18n() // 国际化
+const message = useMessage() // 消息弹窗
+
+const dialogVisible = ref(false) // 弹窗的是否展示
+const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
+const formData = reactive({
+  id: 0,
+  name: '',
+  code: '',
+  dataScope: undefined,
+  dataScopeDeptIds: []
+})
+const formRef = ref() // 表单 Ref
+const deptOptions = ref<any[]>([]) // 部门树形结构
+const deptExpand = ref(false) // 展开/折叠
+const treeRef = ref() // 菜单树组件 Ref
+const treeNodeAll = ref(false) // 全选/全不选
+const checkStrictly = ref(true) // 是否严格模式,即父子不关联
+
+/** 打开弹窗 */
+const open = async (row: RoleApi.RoleVO) => {
+  dialogVisible.value = true
+  resetForm()
+  // 加载 Dept 列表。注意,必须放在前面,不然下面 setChecked 没数据节点
+  deptOptions.value = handleTree(await DeptApi.getSimpleDeptList())
+  // 设置数据
+  formData.id = row.id
+  formData.name = row.name
+  formData.code = row.code
+  formData.dataScope = row.dataScope
+  row.dataScopeDeptIds?.forEach((deptId: number) => {
+    treeRef.value.setChecked(deptId, true, false)
+  })
+}
+defineExpose({ open }) // 提供 open 方法,用于打开弹窗
+
+/** 提交表单 */
+const submitForm = async () => {
+  formLoading.value = true
+  try {
+    const data = {
+      roleId: formData.id,
+      dataScope: formData.dataScope,
+      dataScopeDeptIds:
+        formData.dataScope !== SystemDataScopeEnum.DEPT_CUSTOM
+          ? []
+          : treeRef.value.getCheckedKeys(false)
+    }
+    await PermissionApi.assignRoleDataScope(data)
+    message.success(t('common.updateSuccess'))
+    dialogVisible.value = false
+  } finally {
+    formLoading.value = false
+  }
+}
+
+/** 重置表单 */
+const resetForm = () => {
+  // 重置选项
+  treeNodeAll.value = false
+  deptExpand.value = false
+  checkStrictly.value = true
+  // 重置表单
+  formData.value = {
+    id: 0,
+    name: '',
+    code: '',
+    dataScope: undefined,
+    dataScopeDeptIds: []
+  }
+  treeRef.value?.setCheckedNodes([])
+  formRef.value?.resetFields()
+}
+
+/** 全选/全不选 */
+const handleCheckedTreeNodeAll = () => {
+  treeRef.value.setCheckedNodes(treeNodeAll.value ? deptOptions.value : [])
+}
+
+/** 展开/折叠全部 */
+const handleCheckedTreeExpand = () => {
+  const nodes = treeRef.value?.store.nodesMap
+  for (let node in nodes) {
+    if (nodes[node].expanded === deptExpand.value) {
+      continue
+    }
+    nodes[node].expanded = deptExpand.value
+  }
+}
+</script>
diff --git a/src/views/system/role/RoleForm.vue b/src/views/system/role/RoleForm.vue
index e6444a03..daae020e 100644
--- a/src/views/system/role/RoleForm.vue
+++ b/src/views/system/role/RoleForm.vue
@@ -1,5 +1,5 @@
 <template>
-  <Dialog :title="modelTitle" v-model="modelVisible">
+  <Dialog :title="dialogTitle" v-model="dialogVisible">
     <el-form
       ref="formRef"
       :model="formData"
@@ -32,7 +32,7 @@
     </el-form>
     <template #footer>
       <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
-      <el-button @click="modelVisible = false">取 消</el-button>
+      <el-button @click="dialogVisible = false">取 消</el-button>
     </template>
   </Dialog>
 </template>
@@ -43,8 +43,8 @@ import * as RoleApi from '@/api/system/role'
 const { t } = useI18n() // 国际化
 const message = useMessage() // 消息弹窗
 
-const modelVisible = ref(false) // 弹窗的是否展示
-const modelTitle = ref('') // 弹窗的标题
+const dialogVisible = ref(false) // 弹窗的是否展示
+const dialogTitle = ref('') // 弹窗的标题
 const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
 const formType = ref('') // 表单的类型:create - 新增;update - 修改
 const formData = ref({
@@ -66,8 +66,8 @@ const formRef = ref() // 表单 Ref
 
 /** 打开弹窗 */
 const open = async (type: string, id?: number) => {
-  modelVisible.value = true
-  modelTitle.value = t('action.' + type)
+  dialogVisible.value = true
+  dialogTitle.value = t('action.' + type)
   formType.value = type
   resetForm()
   // 修改时,设置数据
@@ -113,7 +113,7 @@ const submitForm = async () => {
       await RoleApi.updateRole(data)
       message.success(t('common.updateSuccess'))
     }
-    modelVisible.value = false
+    dialogVisible.value = false
     // 发送操作成功的事件
     emit('success')
   } finally {
diff --git a/src/views/system/role/index.vue b/src/views/system/role/index.vue
index af8e0d3a..71f0c415 100644
--- a/src/views/system/role/index.vue
+++ b/src/views/system/role/index.vue
@@ -108,7 +108,7 @@
             preIcon="ep:basketball"
             title="菜单权限"
             v-hasPermi="['system:permission:assign-role-menu']"
-            @click="handleScope('menu', scope.row)"
+            @click="openAssignMenuForm(scope.row)"
           >
             菜单权限
           </el-button>
@@ -118,7 +118,7 @@
             preIcon="ep:coin"
             title="数据权限"
             v-hasPermi="['system:permission:assign-role-data-scope']"
-            @click="handleScope('data', scope.row)"
+            @click="openDataPermissionForm(scope.row)"
           >
             数据权限
           </el-button>
@@ -145,15 +145,18 @@
   <!-- 表单弹窗:添加/修改 -->
   <RoleForm ref="formRef" @success="getList" />
   <!-- 表单弹窗:菜单权限 -->
-  <MenuPermissionForm ref="menuPermissionFormRef" @success="getList" />
+  <RoleAssignMenuForm ref="assignMenuFormRef" />
+  <!-- 表单弹窗:数据权限 -->
+  <RoleDataPermissionForm ref="dataPermissionFormRef" />
 </template>
 <script setup lang="tsx">
-import * as RoleApi from '@/api/system/role'
-import RoleForm from './RoleForm.vue'
-import MenuPermissionForm from './MenuPermissionForm.vue'
 import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
 import { dateFormatter } from '@/utils/formatTime'
 import download from '@/utils/download'
+import * as RoleApi from '@/api/system/role'
+import RoleForm from './RoleForm.vue'
+import RoleAssignMenuForm from './RoleAssignMenuForm.vue'
+import RoleDataPermissionForm from './RoleDataPermissionForm.vue'
 const message = useMessage() // 消息弹窗
 const { t } = useI18n() // 国际化
 
@@ -202,9 +205,15 @@ const openForm = (type: string, id?: number) => {
 }
 
 /** 数据权限操作 */
-const menuPermissionFormRef = ref()
-const handleScope = async (type: string, row: RoleApi.RoleVO) => {
-  menuPermissionFormRef.value.openModal(type, row)
+const dataPermissionFormRef = ref()
+const openDataPermissionForm = async (row: RoleApi.RoleVO) => {
+  dataPermissionFormRef.value.open(row)
+}
+
+/** 菜单权限操作 */
+const assignMenuFormRef = ref()
+const openAssignMenuForm = async (row: RoleApi.RoleVO) => {
+  assignMenuFormRef.value.open(row)
 }
 
 /** 删除按钮操作 */
diff --git a/src/views/system/sensitiveWord/SensitiveWordForm.vue b/src/views/system/sensitiveWord/SensitiveWordForm.vue
index c069756b..aebaf6de 100644
--- a/src/views/system/sensitiveWord/SensitiveWordForm.vue
+++ b/src/views/system/sensitiveWord/SensitiveWordForm.vue
@@ -1,5 +1,5 @@
 <template>
-  <Dialog :title="modelTitle" v-model="modelVisible">
+  <Dialog :title="dialogTitle" v-model="dialogVisible">
     <el-form
       ref="formRef"
       :model="formData"
@@ -39,7 +39,7 @@
     </el-form>
     <template #footer>
       <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
-      <el-button @click="modelVisible = false">取 消</el-button>
+      <el-button @click="dialogVisible = false">取 消</el-button>
     </template>
   </Dialog>
 </template>
@@ -50,8 +50,8 @@ import { CommonStatusEnum } from '@/utils/constants'
 const { t } = useI18n() // 国际化
 const message = useMessage() // 消息弹窗
 
-const modelVisible = ref(false) // 弹窗的是否展示
-const modelTitle = ref('') // 弹窗的标题
+const dialogVisible = ref(false) // 弹窗的是否展示
+const dialogTitle = ref('') // 弹窗的标题
 const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
 const formType = ref('') // 表单的类型:create - 新增;update - 修改
 const formData = ref({
@@ -70,8 +70,8 @@ const tagList = ref([]) // 标签数组
 
 /** 打开弹窗 */
 const open = async (type: string, id?: number) => {
-  modelVisible.value = true
-  modelTitle.value = t('action.' + type)
+  dialogVisible.value = true
+  dialogTitle.value = t('action.' + type)
   formType.value = type
   resetForm()
   // 修改时,设置数据
@@ -106,7 +106,7 @@ const submitForm = async () => {
       await SensitiveWordApi.updateSensitiveWord(data)
       message.success(t('common.updateSuccess'))
     }
-    modelVisible.value = false
+    dialogVisible.value = false
     // 发送操作成功的事件
     emit('success')
   } finally {
diff --git a/src/views/system/sensitiveWord/SensitiveWordTestForm.vue b/src/views/system/sensitiveWord/SensitiveWordTestForm.vue
index 881309c8..80308033 100644
--- a/src/views/system/sensitiveWord/SensitiveWordTestForm.vue
+++ b/src/views/system/sensitiveWord/SensitiveWordTestForm.vue
@@ -1,5 +1,5 @@
 <template>
-  <Dialog title="检测敏感词" v-model="modelVisible">
+  <Dialog title="检测敏感词" v-model="dialogVisible">
     <el-form
       ref="formRef"
       :model="formData"
@@ -24,10 +24,8 @@
       </el-form-item>
     </el-form>
     <template #footer>
-      <div class="dialog-footer">
-        <el-button @click="submitForm" type="primary" :disabled="formLoading">检 测</el-button>
-        <el-button @click="modelVisible = false">取 消</el-button>
-      </div>
+      <el-button @click="submitForm" type="primary" :disabled="formLoading">检 测</el-button>
+      <el-button @click="dialogVisible = false">取 消</el-button>
     </template>
   </Dialog>
 </template>
@@ -35,7 +33,7 @@
 import * as SensitiveWordApi from '@/api/system/sensitiveWord'
 const message = useMessage() // 消息弹窗
 
-const modelVisible = ref(false) // 弹窗的是否展示
+const dialogVisible = ref(false) // 弹窗的是否展示
 const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
 const formData = ref({
   text: '',
@@ -50,7 +48,7 @@ const tagList = ref([]) // 标签数组
 
 /** 打开弹窗 */
 const open = async () => {
-  modelVisible.value = true
+  dialogVisible.value = true
   resetForm()
   // 获得 Tag 标签列表
   tagList.value = await SensitiveWordApi.getSensitiveWordTagList()
@@ -73,7 +71,7 @@ const submitForm = async () => {
       return
     }
     message.warning('包含敏感词:' + data.join(', '))
-    modelVisible.value = false
+    dialogVisible.value = false
   } finally {
     formLoading.value = false
   }
diff --git a/src/views/system/sms/channel/SmsChannelForm.vue b/src/views/system/sms/channel/SmsChannelForm.vue
index 3145af91..cd491112 100644
--- a/src/views/system/sms/channel/SmsChannelForm.vue
+++ b/src/views/system/sms/channel/SmsChannelForm.vue
@@ -1,5 +1,5 @@
 <template>
-  <Dialog :title="modelTitle" v-model="modelVisible">
+  <Dialog :title="dialogTitle" v-model="dialogVisible">
     <el-form
       ref="formRef"
       :model="formData"
@@ -46,7 +46,7 @@
     </el-form>
     <template #footer>
       <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
-      <el-button @click="modelVisible = false">取 消</el-button>
+      <el-button @click="dialogVisible = false">取 消</el-button>
     </template>
   </Dialog>
 </template>
@@ -57,8 +57,8 @@ import { CommonStatusEnum } from '@/utils/constants'
 const { t } = useI18n() // 国际化
 const message = useMessage() // 消息弹窗
 
-const modelVisible = ref(false) // 弹窗的是否展示
-const modelTitle = ref('') // 弹窗的标题
+const dialogVisible = ref(false) // 弹窗的是否展示
+const dialogTitle = ref('') // 弹窗的标题
 const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
 const formType = ref('') // 表单的类型:create - 新增;update - 修改
 const formData = ref({
@@ -81,8 +81,8 @@ const formRef = ref() // 表单 Ref
 
 /** 打开弹窗 */
 const open = async (type: string, id?: number) => {
-  modelVisible.value = true
-  modelTitle.value = t('action.' + type)
+  dialogVisible.value = true
+  dialogTitle.value = t('action.' + type)
   formType.value = type
   resetForm()
   // 修改时,设置数据
@@ -116,7 +116,7 @@ const submitForm = async () => {
       await SmsChannelApi.updateSmsChannel(data)
       message.success(t('common.updateSuccess'))
     }
-    modelVisible.value = false
+    dialogVisible.value = false
     // 发送操作成功的事件
     emit('success')
   } finally {
diff --git a/src/views/system/sms/channel/index.vue b/src/views/system/sms/channel/index.vue
index 62cd7cc2..2eb48f02 100644
--- a/src/views/system/sms/channel/index.vue
+++ b/src/views/system/sms/channel/index.vue
@@ -40,6 +40,7 @@
         <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
         <el-button
           type="primary"
+          plain
           @click="openForm('create')"
           v-hasPermi="['system:sms-channel:create']"
         >
diff --git a/src/views/system/sms/log/SmsLogDetail.vue b/src/views/system/sms/log/SmsLogDetail.vue
index 736d0b8e..8a368b3e 100644
--- a/src/views/system/sms/log/SmsLogDetail.vue
+++ b/src/views/system/sms/log/SmsLogDetail.vue
@@ -1,5 +1,5 @@
 <template>
-  <Dialog title="详情" v-model="modelVisible" :scroll="true" :max-height="500" width="800">
+  <Dialog title="详情" v-model="dialogVisible" :scroll="true" :max-height="500" width="800">
     <el-descriptions border :column="1">
       <el-descriptions-item label="日志主键" min-width="120">
         {{ detailData.id }}
@@ -65,14 +65,14 @@ import { formatDate } from '@/utils/formatTime'
 import * as SmsLogApi from '@/api/system/sms/smsLog'
 import * as SmsChannelApi from '@/api/system/sms/smsChannel'
 
-const modelVisible = ref(false) // 弹窗的是否展示
+const dialogVisible = ref(false) // 弹窗的是否展示
 const detailLoading = ref(false) // 表单的加载中
 const detailData = ref() // 详情数据
 const channelList = ref([]) // 短信渠道列表
 
 /** 打开弹窗 */
 const open = async (data: SmsLogApi.SmsLogVO) => {
-  modelVisible.value = true
+  dialogVisible.value = true
   // 设置数据
   detailLoading.value = true
   try {
diff --git a/src/views/system/sms/template/SmsTemplateForm.vue b/src/views/system/sms/template/SmsTemplateForm.vue
index 03684215..22de060a 100644
--- a/src/views/system/sms/template/SmsTemplateForm.vue
+++ b/src/views/system/sms/template/SmsTemplateForm.vue
@@ -1,5 +1,5 @@
 <template>
-  <Dialog :title="modelTitle" v-model="modelVisible">
+  <Dialog :title="dialogTitle" v-model="dialogVisible">
     <el-form
       ref="formRef"
       :model="formData"
@@ -59,7 +59,7 @@
     </el-form>
     <template #footer>
       <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
-      <el-button @click="modelVisible = false">取 消</el-button>
+      <el-button @click="dialogVisible = false">取 消</el-button>
     </template>
   </Dialog>
 </template>
@@ -71,8 +71,8 @@ import { CommonStatusEnum } from '@/utils/constants'
 const { t } = useI18n() // 国际化
 const message = useMessage() // 消息弹窗
 
-const modelVisible = ref(false) // 弹窗的是否展示
-const modelTitle = ref('') // 弹窗的标题
+const dialogVisible = ref(false) // 弹窗的是否展示
+const dialogTitle = ref('') // 弹窗的标题
 const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
 const formType = ref('') // 表单的类型
 const formData = ref<SmsTemplateApi.SmsTemplateVO>({
@@ -99,8 +99,8 @@ const formRef = ref() // 表单 Ref
 const channelList = ref<SmsChannelApi.SmsChannelVO[]>([]) // 短信渠道列表
 
 const open = async (type: string, id?: number) => {
-  modelVisible.value = true
-  modelTitle.value = t('action.' + type)
+  dialogVisible.value = true
+  dialogTitle.value = t('action.' + type)
   formType.value = type
   resetForm()
   // 修改时,设置数据
@@ -134,7 +134,7 @@ const submitForm = async () => {
       await SmsTemplateApi.updateSmsTemplate(data)
       message.success(t('common.updateSuccess'))
     }
-    modelVisible.value = false
+    dialogVisible.value = false
     // 发送操作成功的事件
     emit('success')
   } finally {
diff --git a/src/views/system/sms/template/SmsTemplateSendForm.vue b/src/views/system/sms/template/SmsTemplateSendForm.vue
index f2ecbe9f..2da0e3f6 100644
--- a/src/views/system/sms/template/SmsTemplateSendForm.vue
+++ b/src/views/system/sms/template/SmsTemplateSendForm.vue
@@ -1,5 +1,5 @@
 <template>
-  <Dialog title="测试" v-model="modelVisible">
+  <Dialog title="测试" v-model="dialogVisible">
     <el-form
       ref="formRef"
       :model="formData"
@@ -32,7 +32,7 @@
     </el-form>
     <template #footer>
       <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
-      <el-button @click="modelVisible = false">取 消</el-button>
+      <el-button @click="dialogVisible = false">取 消</el-button>
     </template>
   </Dialog>
 </template>
@@ -40,7 +40,7 @@
 import * as SmsTemplateApi from '@/api/system/sms/smsTemplate'
 const message = useMessage() // 消息弹窗
 
-const modelVisible = ref(false) // 弹窗的是否展示
+const dialogVisible = ref(false) // 弹窗的是否展示
 const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
 
 // 发送短信表单相关
@@ -59,7 +59,7 @@ const formRules = reactive({
 const formRef = ref() // 表单 Ref
 
 const open = async (id: number) => {
-  modelVisible.value = true
+  dialogVisible.value = true
   resetForm()
   // 设置数据
   formLoading.value = true
@@ -97,7 +97,7 @@ const submitForm = async () => {
     if (logId) {
       message.success('提交发送成功!发送结果,见发送日志编号:' + logId)
     }
-    modelVisible.value = false
+    dialogVisible.value = false
   } finally {
     formLoading.value = false
   }
diff --git a/src/views/system/tenant/form.vue b/src/views/system/tenant/form.vue
index 4a6eaae4..ec19b487 100644
--- a/src/views/system/tenant/form.vue
+++ b/src/views/system/tenant/form.vue
@@ -1,5 +1,5 @@
 <template>
-  <Dialog :title="modelTitle" v-model="modelVisible" width="50%">
+  <Dialog :title="dialogTitle" v-model="dialogVisible" width="50%">
     <el-form
       ref="formRef"
       :model="formData"
@@ -71,7 +71,7 @@
     </el-form>
     <template #footer>
       <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
-      <el-button @click="modelVisible = false">取 消</el-button>
+      <el-button @click="dialogVisible = false">取 消</el-button>
     </template>
   </Dialog>
 </template>
@@ -83,8 +83,8 @@ import * as TenantPackageApi from '@/api/system/tenantPackage'
 
 const { t } = useI18n() // 国际化
 const message = useMessage() // 消息弹窗
-const modelVisible = ref(false) // 弹窗的是否展示
-const modelTitle = ref('') // 弹窗的标题
+const dialogVisible = ref(false) // 弹窗的是否展示
+const dialogTitle = ref('') // 弹窗的标题
 const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
 const formType = ref('') // 表单的类型:create - 新增;update - 修改
 const formData = ref({
@@ -112,8 +112,8 @@ const packageList = ref([]) // 租户套餐
 
 /** 打开弹窗 */
 const open = async (type: string, id?: number) => {
-  modelVisible.value = true
-  modelTitle.value = t('action.' + type)
+  dialogVisible.value = true
+  dialogTitle.value = t('action.' + type)
   formType.value = type
   resetForm()
   // 修改时,设置数据
@@ -148,7 +148,7 @@ const submitForm = async () => {
       await TenantApi.updateTenant(data)
       message.success(t('common.updateSuccess'))
     }
-    modelVisible.value = false
+    dialogVisible.value = false
     // 发送操作成功的事件
     emit('success')
   } finally {
diff --git a/src/views/system/tenant/index.vue b/src/views/system/tenant/index.vue
index 1991fbea..ff65436b 100644
--- a/src/views/system/tenant/index.vue
+++ b/src/views/system/tenant/index.vue
@@ -71,7 +71,12 @@
           <Icon icon="ep:refresh" class="mr-5px" />
           重置
         </el-button>
-        <el-button type="primary" @click="openForm('create')" v-hasPermi="['system:tenant:create']">
+        <el-button
+          type="primary"
+          plain
+          @click="openForm('create')"
+          v-hasPermi="['system:tenant:create']"
+        >
           <Icon icon="ep:plus" class="mr-5px" />
           新增
         </el-button>
diff --git a/src/views/system/tenantPackage/TenantPackageForm.vue b/src/views/system/tenantPackage/TenantPackageForm.vue
index 82fc351f..becbcaab 100644
--- a/src/views/system/tenantPackage/TenantPackageForm.vue
+++ b/src/views/system/tenantPackage/TenantPackageForm.vue
@@ -1,5 +1,5 @@
 <template>
-  <Dialog :title="modelTitle" v-model="modelVisible">
+  <Dialog :title="dialogTitle" v-model="dialogVisible">
     <el-form
       ref="formRef"
       :model="formData"
@@ -57,24 +57,22 @@
     </el-form>
     <template #footer>
       <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
-      <el-button @click="modelVisible = false">取 消</el-button>
+      <el-button @click="dialogVisible = false">取 消</el-button>
     </template>
   </Dialog>
 </template>
 <script setup lang="ts" name="TenantPackageForm">
 import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
 import { CommonStatusEnum } from '@/utils/constants'
-import { defaultProps } from '@/utils/tree'
+import { defaultProps, handleTree } from '@/utils/tree'
 import * as TenantPackageApi from '@/api/system/tenantPackage'
 import * as MenuApi from '@/api/system/menu'
 import { ElTree } from 'element-plus'
-import { handleTree } from '@/utils/tree'
-
 const { t } = useI18n() // 国际化
 const message = useMessage() // 消息弹窗
 
-const modelVisible = ref(false) // 弹窗的是否展示
-const modelTitle = ref('') // 弹窗的标题
+const dialogVisible = ref(false) // 弹窗的是否展示
+const dialogTitle = ref('') // 弹窗的标题
 const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
 const formType = ref('') // 表单的类型:create - 新增;update - 修改
 const formData = ref({
@@ -92,13 +90,13 @@ const formRules = reactive({
 const formRef = ref() // 表单 Ref
 const menuOptions = ref<any[]>([]) // 树形结构数据
 const menuExpand = ref(false) // 展开/折叠
-const treeRef = ref<InstanceType<typeof ElTree>>() // 树组件Ref
+const treeRef = ref<InstanceType<typeof ElTree>>() // 树组件 Ref
 const treeNodeAll = ref(false) // 全选/全不选
 
 /** 打开弹窗 */
 const open = async (type: string, id?: number) => {
-  modelVisible.value = true
-  modelTitle.value = t('action.' + type)
+  dialogVisible.value = true
+  dialogTitle.value = t('action.' + type)
   formType.value = type
   resetForm()
   // 加载 Menu 列表。注意,必须放在前面,不然下面 setChecked 没数据节点
@@ -133,8 +131,8 @@ const submitForm = async () => {
   try {
     const data = formData.value as unknown as TenantPackageApi.TenantPackageVO
     data.menuIds = [
-      ...(treeRef.value!.getCheckedKeys(false) as unknown as Array<number>), // 获得当前选中节点
-      ...(treeRef.value!.getHalfCheckedKeys() as unknown as Array<number>) // 获得半选中的父节点
+      ...(treeRef.value.getCheckedKeys(false) as unknown as Array<number>), // 获得当前选中节点
+      ...(treeRef.value.getHalfCheckedKeys() as unknown as Array<number>) // 获得半选中的父节点
     ]
     if (formType.value === 'create') {
       await TenantPackageApi.createTenantPackage(data)
@@ -143,7 +141,7 @@ const submitForm = async () => {
       await TenantPackageApi.updateTenantPackage(data)
       message.success(t('common.updateSuccess'))
     }
-    modelVisible.value = false
+    dialogVisible.value = false
     // 发送操作成功的事件
     emit('success')
   } finally {
@@ -168,17 +166,19 @@ const resetForm = () => {
   formRef.value?.resetFields()
 }
 
-// 全选/全不选
+/** 全选/全不选 */
 const handleCheckedTreeNodeAll = () => {
-  treeRef.value!.setCheckedNodes(treeNodeAll.value ? menuOptions.value : [])
+  treeRef.value.setCheckedNodes(treeNodeAll.value ? menuOptions.value : [])
 }
 
-// 全部(展开/折叠)TODO:for循环全部展开和折叠树组件数据
+/** 展开/折叠全部 */
 const handleCheckedTreeExpand = () => {
   const nodes = treeRef.value?.store.nodesMap
   for (let node in nodes) {
-    if (nodes[node].expanded === menuExpand.value) continue
-    nodes[node].expanded = !nodes[node].expanded
+    if (nodes[node].expanded === menuExpand.value) {
+      continue
+    }
+    nodes[node].expanded = menuExpand.value
   }
 }
 </script>
diff --git a/src/views/system/tenantPackage/index.vue b/src/views/system/tenantPackage/index.vue
index ac24ea94..b20c432e 100644
--- a/src/views/system/tenantPackage/index.vue
+++ b/src/views/system/tenantPackage/index.vue
@@ -42,6 +42,7 @@
         <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
         <el-button
           type="primary"
+          plain
           @click="openForm('create')"
           v-hasPermi="['system:tenant-package:create']"
         >
@@ -63,11 +64,13 @@
         </template>
       </el-table-column>
       <el-table-column label="备注" align="center" prop="remark" />
-      <el-table-column label="创建时间" align="center" prop="createTime" width="180">
-        <template #default="scope">
-          <span>{{ formatDate(scope.row.createTime) }}</span>
-        </template>
-      </el-table-column>
+      <el-table-column
+        label="创建时间"
+        align="center"
+        prop="createTime"
+        width="180"
+        :formatter="dateFormatter"
+      />
       <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
         <template #default="scope">
           <el-button
@@ -103,7 +106,7 @@
 </template>
 <script setup lang="ts" name="TenantPackage">
 import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
-import { formatDate } from '@/utils/formatTime'
+import { dateFormatter } from '@/utils/formatTime'
 import * as TenantPackageApi from '@/api/system/tenantPackage'
 import TenantPackageForm from './TenantPackageForm.vue'
 const message = useMessage() // 消息弹窗
@@ -112,7 +115,7 @@ const { t } = useI18n() // 国际化
 const loading = ref(true) // 列表的加载中
 const total = ref(0) // 列表的总页数
 const list = ref([]) // 列表的数据
-const queryParams: Record<string, any> = ref<Record<string, any>>({
+const queryParams = reactive({
   pageNo: 1,
   pageSize: 10,
   name: null,
diff --git a/src/views/system/user/components/UserDeptTree.vue b/src/views/system/user/DeptTree.vue
similarity index 66%
rename from src/views/system/user/components/UserDeptTree.vue
rename to src/views/system/user/DeptTree.vue
index 59004a92..87ffaf9a 100644
--- a/src/views/system/user/components/UserDeptTree.vue
+++ b/src/views/system/user/DeptTree.vue
@@ -1,6 +1,6 @@
 <template>
   <div class="head-container">
-    <el-input v-model="deptName" placeholder="请输入部门名称" clearable style="margin-bottom: 20px">
+    <el-input v-model="deptName" placeholder="请输入部门名称" clearable class="mb-20px">
       <template #prefix>
         <Icon icon="ep:search" />
       </template>
@@ -8,15 +8,15 @@
   </div>
   <div class="head-container">
     <el-tree
-      :data="deptOptions"
+      :data="deptList"
       :props="defaultProps"
+      node-key="id"
       :expand-on-click-node="false"
       :filter-node-method="filterNode"
       ref="treeRef"
-      node-key="id"
       default-expand-all
       highlight-current
-      @node-click="handleDeptNodeClick"
+      @node-click="handleNodeClick"
     />
   </div>
 </template>
@@ -26,25 +26,30 @@ import { ElTree } from 'element-plus'
 import * as DeptApi from '@/api/system/dept'
 import { defaultProps, handleTree } from '@/utils/tree'
 
-const emits = defineEmits(['node-click'])
 const deptName = ref('')
-const deptOptions = ref<Tree[]>([]) // 树形结构
+const deptList = ref<Tree[]>([]) // 树形结构
 const treeRef = ref<InstanceType<typeof ElTree>>()
+
+/** 获得部门树 */
 const getTree = async () => {
   const res = await DeptApi.getSimpleDeptList()
-  deptOptions.value = []
-  deptOptions.value.push(...handleTree(res))
+  deptList.value = []
+  deptList.value.push(...handleTree(res))
 }
 
-const filterNode = (value: string, data: Tree) => {
-  if (!value) return true
-  return data.name.includes(value)
+/** 基于名字过滤 */
+const filterNode = (name: string, data: Tree) => {
+  if (!name) return true
+  return data.name.includes(name)
 }
 
-const handleDeptNodeClick = async (row: { [key: string]: any }) => {
+/** 处理部门被点击 */
+const handleNodeClick = async (row: { [key: string]: any }) => {
   emits('node-click', row)
 }
+const emits = defineEmits(['node-click'])
 
+/** 初始化 */
 onMounted(async () => {
   await getTree()
 })
diff --git a/src/views/system/user/UserAssignRoleForm.vue b/src/views/system/user/UserAssignRoleForm.vue
new file mode 100644
index 00000000..e0259b7d
--- /dev/null
+++ b/src/views/system/user/UserAssignRoleForm.vue
@@ -0,0 +1,93 @@
+<template>
+  <Dialog title="分配角色" v-model="dialogVisible">
+    <el-form ref="formRef" :model="formData" label-width="80px" v-loading="formLoading">
+      <el-form-item label="用户名称">
+        <el-input v-model="formData.username" :disabled="true" />
+      </el-form-item>
+      <el-form-item label="用户昵称">
+        <el-input v-model="formData.nickname" :disabled="true" />
+      </el-form-item>
+      <el-form-item label="角色">
+        <el-select v-model="formData.roleIds" multiple placeholder="请选择角色">
+          <el-option v-for="item in roleList" :key="item.id" :label="item.name" :value="item.id" />
+        </el-select>
+      </el-form-item>
+    </el-form>
+    <template #footer>
+      <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
+      <el-button @click="dialogVisible = false">取 消</el-button>
+    </template>
+  </Dialog>
+</template>
+<script setup lang="ts">
+import * as PermissionApi from '@/api/system/permission'
+import * as UserApi from '@/api/system/user'
+import * as RoleApi from '@/api/system/role'
+const { t } = useI18n() // 国际化
+const message = useMessage() // 消息弹窗
+
+const dialogVisible = ref(false) // 弹窗的是否展示
+const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
+const formData = ref({
+  id: undefined,
+  nickname: '',
+  username: '',
+  roleIds: []
+})
+const formRef = ref() // 表单 Ref
+const roleList = ref([]) // 角色的列表
+
+/** 打开弹窗 */
+const open = async (row: UserApi.UserVO) => {
+  dialogVisible.value = true
+  resetForm()
+  // 设置数据
+  formData.value.id = row.id
+  formData.value.username = row.username
+  formData.value.nickname = row.nickname
+  // 获得角色拥有的菜单集合
+  formLoading.value = true
+  try {
+    formData.value.roleIds = await PermissionApi.getUserRoleList(row.id)
+  } finally {
+    formLoading.value = false
+  }
+  // 获得角色列表
+  roleList.value = await RoleApi.getSimpleRoleList()
+}
+defineExpose({ open }) // 提供 open 方法,用于打开弹窗
+
+/** 提交表单 */
+const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
+const submitForm = async () => {
+  // 校验表单
+  if (!formRef) return
+  const valid = await formRef.value.validate()
+  if (!valid) return
+  // 提交请求
+  formLoading.value = true
+  try {
+    await PermissionApi.assignUserRole({
+      userId: formData.value.id,
+      roleIds: formData.value.roleIds
+    })
+    message.success(t('common.updateSuccess'))
+    dialogVisible.value = false
+    // 发送操作成功的事件
+    emit('success', true)
+  } finally {
+    formLoading.value = false
+  }
+}
+
+/** 重置表单 */
+const resetForm = () => {
+  formData.value = {
+    id: undefined,
+    nickname: '',
+    username: '',
+    roleIds: []
+  }
+  formRef.value?.resetFields()
+}
+</script>
diff --git a/src/views/system/user/components/UserForm.vue b/src/views/system/user/UserForm.vue
similarity index 57%
rename from src/views/system/user/components/UserForm.vue
rename to src/views/system/user/UserForm.vue
index 4ea21607..3afcbd1f 100644
--- a/src/views/system/user/components/UserForm.vue
+++ b/src/views/system/user/UserForm.vue
@@ -1,7 +1,12 @@
 <template>
-  <!-- 添加或修改参数配置对话框 -->
-  <Dialog :title="title" :modelValue="showDialog" width="600px" append-to-body @close="closeDialog">
-    <el-form ref="formRef" :model="formData" :rules="rules" label-width="80px">
+  <Dialog :title="dialogTitle" v-model="dialogVisible">
+    <el-form
+      ref="formRef"
+      :model="formData"
+      :rules="formRules"
+      label-width="80px"
+      v-loading="formLoading"
+    >
       <el-row>
         <el-col :span="12">
           <el-form-item label="用户昵称" prop="nickname">
@@ -13,7 +18,7 @@
             <el-tree-select
               node-key="id"
               v-model="formData.deptId"
-              :data="deptOptions"
+              :data="deptList"
               :props="defaultProps"
               check-strictly
               placeholder="请选择归属部门"
@@ -56,7 +61,7 @@
             <el-select v-model="formData.sex" placeholder="请选择">
               <el-option
                 v-for="dict in getIntDictOptions(DICT_TYPE.SYSTEM_USER_SEX)"
-                :key="dict.value as number"
+                :key="dict.value"
                 :label="dict.label"
                 :value="dict.value"
               />
@@ -67,10 +72,10 @@
           <el-form-item label="岗位">
             <el-select v-model="formData.postIds" multiple placeholder="请选择">
               <el-option
-                v-for="item in postOptions"
+                v-for="item in postList"
                 :key="item.id"
                 :label="item.name"
-                :value="item.id as number"
+                :value="item.id"
               />
             </el-select>
           </el-form-item>
@@ -85,53 +90,26 @@
       </el-row>
     </el-form>
     <template #footer>
-      <div class="dialog-footer">
-        <el-button type="primary" @click="submitForm">确 定</el-button>
-        <el-button @click="cancel">取 消</el-button>
-      </div>
+      <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
+      <el-button @click="dialogVisible = false">取 消</el-button>
     </template>
   </Dialog>
 </template>
 <script lang="ts" setup>
-import { PostVO } from '@/api/system/post'
-import * as PostApi from '@/api/system/post'
-import { createUserApi, getUserApi, updateUserApi } from '@/api/system/user'
-import * as DeptApi from '@/api/system/dept'
-
 import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
+import { CommonStatusEnum } from '@/utils/constants'
 import { defaultProps, handleTree } from '@/utils/tree'
-import { ElForm, FormItemRule } from 'element-plus'
-import { Arrayable } from 'element-plus/es/utils'
-import { UserVO } from '@/api/login/types'
-
-type Form = InstanceType<typeof ElForm>
-
-const emits = defineEmits(['success'])
-
+import * as PostApi from '@/api/system/post'
+import * as DeptApi from '@/api/system/dept'
+import * as UserApi from '@/api/system/user'
 const { t } = useI18n() // 国际化
 const message = useMessage() // 消息弹窗
 
-const showDialog = ref(false)
-// 弹出层标题
-const title = computed(() => {
-  return formData.value?.id ? '修改用户' : '添加用户'
-})
-
-const deptOptions = ref<Tree[]>([]) // 树形结构
-const getTree = async () => {
-  const res = await DeptApi.getSimpleDeptList()
-  deptOptions.value = []
-  deptOptions.value.push(...handleTree(res))
-}
-// 获取岗位列表
-const postOptions = ref<PostVO[]>([]) //岗位列表
-const getPostOptions = async () => {
-  const res = (await PostApi.getSimplePostList()) as PostVO[]
-  postOptions.value.push(...res)
-}
-
-// 表单初始化参数
-const initParams = {
+const dialogVisible = ref(false) // 弹窗的是否展示
+const dialogTitle = ref('') // 弹窗的标题
+const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
+const formType = ref('') // 表单的类型:create - 新增;update - 修改
+const formData = ref({
   nickname: '',
   deptId: '',
   mobile: '',
@@ -139,15 +117,13 @@ const initParams = {
   id: undefined,
   username: '',
   password: '',
-  sex: 1,
+  sex: undefined,
   postIds: [],
   remark: '',
-  status: '0',
+  status: CommonStatusEnum.ENABLE,
   roleIds: []
-}
-
-// 校验规则
-const rules = {
+})
+const formRules = reactive({
   username: [{ required: true, message: '用户名称不能为空', trigger: 'blur' }],
   nickname: [{ required: true, message: '用户昵称不能为空', trigger: 'blur' }],
   password: [{ required: true, message: '用户密码不能为空', trigger: 'blur' }],
@@ -165,73 +141,75 @@ const rules = {
       trigger: 'blur'
     }
   ]
-} as Partial<Record<string, Arrayable<FormItemRule>>>
-const formRef = ref<Form | null>()
-const formData = ref<Recordable>({ ...initParams })
+})
+const formRef = ref() // 表单 Ref
+const deptList = ref<Tree[]>([]) // 树形结构
+const postList = ref([]) // 岗位列表
 
-const resetForm = () => {
-  let form = formRef?.value
-  if (!form) return
-  formData.value = { ...initParams }
-  form && (form as Form).resetFields()
-}
-const closeDialog = () => {
-  showDialog.value = false
-}
-// 操作成功
-const operateOk = () => {
-  emits('success', true)
-  closeDialog()
-}
-const submitForm = () => {
-  let form = formRef.value as Form
-  form.validate(async (valid) => {
-    let data = formData.value
-    if (valid) {
-      try {
-        if (data?.id !== undefined) {
-          await updateUserApi(data)
-          message.success(t('common.updateSuccess'))
-          operateOk()
-        } else {
-          await createUserApi(data)
-          message.success(t('common.createSuccess'))
-          operateOk()
-        }
-      } catch (err) {
-        console.error(err)
-      }
-    }
-  })
-}
-/* 取消 */
-const cancel = () => {
-  closeDialog()
-}
-
-/* 打开弹框 */
-const openForm = (row: undefined | UserVO) => {
+/** 打开弹窗 */
+const open = async (type: string, id?: number) => {
+  dialogVisible.value = true
+  dialogTitle.value = t('action.' + type)
+  formType.value = type
   resetForm()
-  getTree() // 部门树
-  if (row && row.id) {
-    const id = row.id
-    getUserApi(id).then((response) => {
-      formData.value = response
-    })
-  } else {
-    formData.value = { ...initParams }
+  // 修改时,设置数据
+  if (id) {
+    formLoading.value = true
+    try {
+      formData.value = await UserApi.getUser(id)
+    } finally {
+      formLoading.value = false
+    }
   }
+  // 加载部门树
+  deptList.value = handleTree(await DeptApi.getSimpleDeptList())
+  // 加载岗位列表
+  postList.value = await PostApi.getSimplePostList()
+}
+defineExpose({ open }) // 提供 open 方法,用于打开弹窗
 
-  showDialog.value = true
+/** 提交表单 */
+const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
+const submitForm = async () => {
+  // 校验表单
+  if (!formRef) return
+  const valid = await formRef.value.validate()
+  if (!valid) return
+  // 提交请求
+  formLoading.value = true
+  try {
+    const data = formData.value as unknown as UserApi.UserVO
+    if (formType.value === 'create') {
+      await UserApi.createUser(data)
+      message.success(t('common.createSuccess'))
+    } else {
+      await UserApi.updateUser(data)
+      message.success(t('common.updateSuccess'))
+    }
+    dialogVisible.value = false
+    // 发送操作成功的事件
+    emit('success')
+  } finally {
+    formLoading.value = false
+  }
 }
 
-// ========== 初始化 ==========
-onMounted(async () => {
-  await getPostOptions()
-})
-
-defineExpose({
-  resetForm,
-  openForm
-})
+/** 重置表单 */
+const resetForm = () => {
+  formData.value = {
+    nickname: '',
+    deptId: '',
+    mobile: '',
+    email: '',
+    id: undefined,
+    username: '',
+    password: '',
+    sex: undefined,
+    postIds: [],
+    remark: '',
+    status: CommonStatusEnum.ENABLE,
+    roleIds: []
+  }
+  formRef.value?.resetFields()
+}
 </script>
diff --git a/src/views/system/user/UserImportForm.vue b/src/views/system/user/UserImportForm.vue
new file mode 100644
index 00000000..f03345e9
--- /dev/null
+++ b/src/views/system/user/UserImportForm.vue
@@ -0,0 +1,129 @@
+<template>
+  <Dialog title="用户导入" v-model="dialogVisible" width="400">
+    <el-upload
+      ref="uploadRef"
+      :action="importUrl + '?updateSupport=' + updateSupport"
+      :headers="uploadHeaders"
+      v-model:file-list="fileList"
+      drag
+      accept=".xlsx, .xls"
+      :limit="1"
+      :on-success="submitFormSuccess"
+      :on-exceed="handleExceed"
+      :on-error="submitFormError"
+      :auto-upload="false"
+      :disabled="formLoading"
+    >
+      <Icon icon="ep:upload" />
+      <div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
+      <template #tip>
+        <div class="el-upload__tip text-center">
+          <div class="el-upload__tip">
+            <el-checkbox v-model="updateSupport" /> 是否更新已经存在的用户数据
+          </div>
+          <span>仅允许导入 xls、xlsx 格式文件。</span>
+          <el-link
+            type="primary"
+            :underline="false"
+            style="font-size: 12px; vertical-align: baseline"
+            @click="importTemplate"
+          >
+            下载模板
+          </el-link>
+        </div>
+      </template>
+    </el-upload>
+    <template #footer>
+      <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
+      <el-button @click="dialogVisible = false">取 消</el-button>
+    </template>
+  </Dialog>
+</template>
+<script lang="ts" setup>
+import * as UserApi from '@/api/system/user'
+import { getAccessToken, getTenantId } from '@/utils/auth'
+import download from '@/utils/download'
+const message = useMessage() // 消息弹窗
+
+const dialogVisible = ref(false) // 弹窗的是否展示
+const formLoading = ref(false) // 表单的加载中
+const uploadRef = ref()
+const importUrl =
+  import.meta.env.VITE_BASE_URL + import.meta.env.VITE_API_URL + '/system/user/import'
+const uploadHeaders = ref() // 上传 Header 头
+const fileList = ref([]) // 文件列表
+const updateSupport = ref(0) // 是否更新已经存在的用户数据
+
+/** 打开弹窗 */
+const open = () => {
+  dialogVisible.value = true
+  resetForm()
+}
+defineExpose({ open }) // 提供 open 方法,用于打开弹窗
+
+/** 提交表单 */
+const submitForm = async () => {
+  if (fileList.value.length == 0) {
+    message.error('请上传文件')
+    return
+  }
+  // 提交请求
+  uploadHeaders.value = {
+    Authorization: 'Bearer ' + getAccessToken(),
+    'tenant-id': getTenantId()
+  }
+  formLoading.value = true
+  uploadRef.value!.submit()
+}
+
+/** 文件上传成功 */
+const emits = defineEmits(['success'])
+const submitFormSuccess = (response: any) => {
+  if (response.code !== 0) {
+    message.error(response.msg)
+    formLoading.value = false
+    return
+  }
+  // 拼接提示语
+  const data = response.data
+  let text = '上传成功数量:' + data.createUsernames.length + ';'
+  for (let username of data.createUsernames) {
+    text += '< ' + username + ' >'
+  }
+  text += '更新成功数量:' + data.updateUsernames.length + ';'
+  for (const username of data.updateUsernames) {
+    text += '< ' + username + ' >'
+  }
+  text += '更新失败数量:' + Object.keys(data.failureUsernames).length + ';'
+  for (const username in data.failureUsernames) {
+    text += '< ' + username + ': ' + data.failureUsernames[username] + ' >'
+  }
+  message.alert(text)
+  // 发送操作成功的事件
+  emits('success')
+}
+
+/** 上传错误提示 */
+const submitFormError = (): void => {
+  message.error('上传失败,请您重新上传!')
+  formLoading.value = false
+}
+
+/** 重置表单 */
+const resetForm = () => {
+  // 重置上传状态和文件
+  formLoading.value = false
+  uploadRef.value?.clearFiles()
+}
+
+/** 文件数超出提示 */
+const handleExceed = (): void => {
+  message.error('最多只能上传一个文件!')
+}
+
+/** 下载模板操作 */
+const importTemplate = async () => {
+  const res = await UserApi.importUserTemplate()
+  download.excel(res, '用户导入模版.xls')
+}
+</script>
diff --git a/src/views/system/user/components/UserAssignRoleForm.vue b/src/views/system/user/components/UserAssignRoleForm.vue
deleted file mode 100644
index bbf37739..00000000
--- a/src/views/system/user/components/UserAssignRoleForm.vue
+++ /dev/null
@@ -1,108 +0,0 @@
-<template>
-  <Dialog
-    title="分配角色"
-    :modelValue="showDialog"
-    width="500px"
-    append-to-body
-    @close="closeDialog"
-  >
-    <el-form :model="formData" label-width="80px" ref="formRef">
-      <el-form-item label="用户名称">
-        <el-input v-model="formData.username" :disabled="true" />
-      </el-form-item>
-      <el-form-item label="用户昵称">
-        <el-input v-model="formData.nickname" :disabled="true" />
-      </el-form-item>
-      <el-form-item label="角色">
-        <el-select v-model="formData.roleIds" multiple placeholder="请选择角色">
-          <el-option
-            v-for="item in roleOptions"
-            :key="item.id"
-            :label="item.name"
-            :value="item.id"
-          />
-        </el-select>
-      </el-form-item>
-    </el-form>
-    <template #footer>
-      <div class="dialog-footer">
-        <el-button type="primary" @click="submit">确 定</el-button>
-        <el-button @click="cancel">取 消</el-button>
-      </div>
-    </template>
-  </Dialog>
-</template>
-
-<script setup lang="ts">
-import {
-  assignUserRoleApi,
-  listUserRolesApi,
-  PermissionAssignUserRoleReqVO
-} from '@/api/system/permission'
-import { UserVO } from '@/api/system/user'
-import * as RoleApi from '@/api/system/role'
-
-const emits = defineEmits(['success'])
-
-const { t } = useI18n() // 国际化
-const message = useMessage() // 消息弹窗
-
-// 表单初始化参数
-const initParams = {
-  nickname: '',
-  id: 0,
-  username: '',
-  roleIds: [] as number[]
-}
-const formData = ref<Recordable>({ ...initParams })
-
-/* 弹框按钮操作 */
-// 点击取消
-const cancel = () => {
-  closeDialog()
-}
-// 关闭弹窗
-const closeDialog = () => {
-  showDialog.value = false
-}
-// 提交
-const submit = async () => {
-  const data = ref<PermissionAssignUserRoleReqVO>({
-    userId: formData.value.id,
-    roleIds: formData.value.roleIds
-  })
-  try {
-    await assignUserRoleApi(data.value)
-    message.success(t('common.updateSuccess'))
-    emits('success', true)
-    closeDialog()
-  } catch (error) {
-    console.error(error)
-  }
-}
-
-const roleOptions = ref()
-const userRole = reactive(initParams)
-const showDialog = ref(false)
-const formRef = ref()
-const openForm = async (row: UserVO) => {
-  formRef.value?.resetFields()
-  userRole.id = row.id
-  userRole.username = row.username
-  userRole.nickname = row.nickname
-
-  // 获得角色列表
-  const roleOpt = await RoleApi.getSimpleRoleList()
-  roleOptions.value = [...roleOpt]
-
-  // 获得角色拥有的菜单集合
-  const roles = await listUserRolesApi(row.id)
-  userRole.roleIds = roles
-  formData.value = { ...userRole }
-
-  showDialog.value = true
-}
-defineExpose({
-  openForm
-})
-</script>
diff --git a/src/views/system/user/components/UserImportForm.vue b/src/views/system/user/components/UserImportForm.vue
deleted file mode 100644
index f63936e2..00000000
--- a/src/views/system/user/components/UserImportForm.vue
+++ /dev/null
@@ -1,154 +0,0 @@
-<template>
-  <Dialog
-    :title="upload.title"
-    :modelValue="showDialog"
-    width="400px"
-    append-to-body
-    @close="closeDialog"
-  >
-    <el-upload
-      ref="uploadRef"
-      accept=".xlsx, .xls"
-      :limit="1"
-      :headers="upload.headers"
-      :action="upload.url + '?updateSupport=' + upload.updateSupport"
-      :disabled="upload.isUploading"
-      :on-progress="handleFileUploadProgress"
-      :on-success="handleFileSuccess"
-      :on-exceed="handleExceed"
-      :on-error="excelUploadError"
-      :auto-upload="false"
-      drag
-    >
-      <Icon icon="ep:upload" />
-      <div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
-      <template #tip>
-        <div class="el-upload__tip text-center">
-          <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
-          >
-        </div>
-      </template>
-    </el-upload>
-    <template #footer>
-      <div class="dialog-footer">
-        <el-button type="primary" @click="submitFileForm">确 定</el-button>
-        <el-button @click="cancel">取 消</el-button>
-      </div>
-    </template>
-  </Dialog>
-</template>
-
-<script lang="ts" setup>
-import { importUserTemplateApi } from '@/api/system/user'
-import { getAccessToken, getTenantId } from '@/utils/auth'
-import download from '@/utils/download'
-
-const emits = defineEmits(['success'])
-
-const message = useMessage() // 消息弹窗
-
-const showDialog = ref(false)
-const uploadRef = ref()
-
-// 用户导入参数
-const upload = reactive({
-  // // 是否显示弹出层(用户导入)
-  // open: false,
-  // 弹出层标题(用户导入)
-  title: '用户导入',
-  // 是否禁用上传
-  isUploading: false,
-  // 是否更新已经存在的用户数据
-  updateSupport: 0,
-  // 设置上传的请求头部
-  headers: {
-    Authorization: 'Bearer ' + getAccessToken(),
-    'tenant-id': getTenantId()
-  },
-  // 上传的地址
-  url: import.meta.env.VITE_BASE_URL + import.meta.env.VITE_API_URL + '/system/user/import'
-})
-
-// 文件上传中处理
-const handleFileUploadProgress = () => {
-  upload.isUploading = true
-}
-// 文件上传成功处理
-const handleFileSuccess = (response: any) => {
-  if (response.code !== 0) {
-    message.error(response.msg)
-    return
-  }
-  upload.isUploading = false
-  uploadRef.value?.clearFiles()
-  // 拼接提示语
-  const data = response.data
-  let text = '上传成功数量:' + data.createUsernames.length + ';'
-  for (let username of data.createUsernames) {
-    text += '< ' + username + ' >'
-  }
-  text += '更新成功数量:' + data.updateUsernames.length + ';'
-  for (const username of data.updateUsernames) {
-    text += '< ' + username + ' >'
-  }
-  text += '更新失败数量:' + Object.keys(data.failureUsernames).length + ';'
-  for (const username in data.failureUsernames) {
-    text += '< ' + username + ': ' + data.failureUsernames[username] + ' >'
-  }
-  message.alert(text)
-  emits('success')
-  closeDialog()
-}
-
-// 文件数超出提示
-const handleExceed = (): void => {
-  message.error('最多只能上传一个文件!')
-}
-// 上传错误提示
-const excelUploadError = (e): void => {
-  console.log(e)
-  message.error('导入数据失败,请您重新上传!')
-}
-
-/** 下载模板操作 */
-const importTemplate = async () => {
-  try {
-    const res = await importUserTemplateApi()
-    download.excel(res, '用户导入模版.xls')
-  } catch (error) {
-    console.error(error)
-  }
-}
-
-/* 弹框按钮操作 */
-// 点击取消
-const cancel = () => {
-  closeDialog()
-}
-// 关闭弹窗
-const closeDialog = () => {
-  showDialog.value = false
-}
-// 提交上传文件
-const submitFileForm = () => {
-  uploadRef.value?.submit()
-}
-
-const openForm = () => {
-  uploadRef.value?.clearFiles()
-  showDialog.value = true
-}
-defineExpose({
-  openForm
-})
-</script>
diff --git a/src/views/system/user/index.vue b/src/views/system/user/index.vue
index 1c36d376..c95c9fd7 100644
--- a/src/views/system/user/index.vue
+++ b/src/views/system/user/index.vue
@@ -1,256 +1,216 @@
 <template>
-  <div class="app-container">
-    <content-wrap>
-      <!-- 搜索工作栏 -->
-      <el-row :gutter="20">
-        <!--部门数据-->
-        <el-col :span="4" :xs="24">
-          <UserDeptTree @node-click="handleDeptNodeClick" />
-        </el-col>
-        <!--用户数据-->
-        <el-col :span="20" :xs="24">
-          <el-form
-            :model="queryParams"
-            ref="queryFormRef"
-            :inline="true"
-            v-show="showSearch"
-            label-width="68px"
-          >
-            <el-form-item label="用户名称" prop="username">
-              <el-input
-                v-model="queryParams.username"
-                placeholder="请输入用户名称"
-                clearable
-                style="width: 240px"
-                @keyup.enter="handleQuery"
-              />
-            </el-form-item>
-            <el-form-item label="手机号码" prop="mobile">
-              <el-input
-                v-model="queryParams.mobile"
-                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"
-              >
-                <el-option
-                  v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)"
-                  :key="dict.value as number"
-                  :label="dict.label"
-                  :value="dict.value as number"
-                />
-              </el-select>
-            </el-form-item>
-            <el-form-item label="创建时间" prop="createTime">
-              <el-date-picker
-                v-model="queryParams.createTime"
-                style="width: 240px"
-                value-format="YYYY-MM-DD HH:mm:ss"
-                type="datetimerange"
-                range-separator="-"
-                start-placeholder="开始日期"
-                end-placeholder="结束日期"
-              />
-            </el-form-item>
-            <el-form-item>
-              <el-button type="primary" @click="handleQuery"
-                ><Icon icon="ep:search" />搜索</el-button
-              >
-              <el-button @click="resetQuery"><Icon icon="ep:refresh" />重置</el-button>
-            </el-form-item>
-          </el-form>
-
-          <el-row :gutter="10" class="mb-8px">
-            <el-col :span="1.5">
-              <el-button
-                type="primary"
-                plain
-                size="small"
-                @click="handleAdd"
-                v-hasPermi="['system:user:create']"
-                ><Icon icon="ep:plus" />新增</el-button
-              >
-            </el-col>
-            <el-col :span="1.5">
-              <el-button
-                type="info"
-                size="small"
-                @click="handleImport"
-                v-hasPermi="['system:user:import']"
-                ><Icon icon="ep:upload" />导入</el-button
-              >
-            </el-col>
-            <el-col :span="1.5">
-              <el-button
-                type="warning"
-                size="small"
-                @click="handleExport"
-                :loading="exportLoading"
-                v-hasPermi="['system:user:export']"
-                ><Icon icon="ep:download" />导出</el-button
-              >
-            </el-col>
-          </el-row>
-          <el-table v-loading="loading" :data="userList">
-            <el-table-column
-              label="用户编号"
-              align="center"
-              key="id"
-              prop="id"
-              v-if="columns[0].visible"
+  <el-row :gutter="20">
+    <!-- 左侧部门树 -->
+    <el-col :span="4" :xs="24">
+      <content-wrap class="h-1/1">
+        <DeptTree @node-click="handleDeptNodeClick" />
+      </content-wrap>
+    </el-col>
+    <el-col :span="20" :xs="24">
+      <!-- 搜索 -->
+      <content-wrap>
+        <el-form
+          class="-mb-15px"
+          :model="queryParams"
+          ref="queryFormRef"
+          :inline="true"
+          label-width="68px"
+        >
+          <el-form-item label="用户名称" prop="username">
+            <el-input
+              v-model="queryParams.username"
+              placeholder="请输入用户名称"
+              clearable
+              @keyup.enter="handleQuery"
+              class="!w-240px"
             />
-            <el-table-column
-              label="用户名称"
-              align="center"
-              key="username"
-              prop="username"
-              v-if="columns[1].visible"
-              :show-overflow-tooltip="true"
+          </el-form-item>
+          <el-form-item label="手机号码" prop="mobile">
+            <el-input
+              v-model="queryParams.mobile"
+              placeholder="请输入手机号码"
+              clearable
+              @keyup.enter="handleQuery"
+              class="!w-240px"
             />
-            <el-table-column
-              label="用户昵称"
-              align="center"
-              key="nickname"
-              prop="nickname"
-              v-if="columns[2].visible"
-              :show-overflow-tooltip="true"
-            />
-            <el-table-column
-              label="部门"
-              align="center"
-              key="deptName"
-              prop="dept.name"
-              v-if="columns[3].visible"
-              :show-overflow-tooltip="true"
-            />
-            <el-table-column
-              label="手机号码"
-              align="center"
-              key="mobile"
-              prop="mobile"
-              v-if="columns[4].visible"
-              width="120"
-            />
-            <el-table-column label="状态" key="status" v-if="columns[5].visible" align="center">
-              <template #default="scope">
-                <el-switch
-                  v-model="scope.row.status"
-                  :active-value="0"
-                  :inactive-value="1"
-                  @change="handleStatusChange(scope.row)"
-                />
-              </template>
-            </el-table-column>
-            <el-table-column
-              label="创建时间"
-              align="center"
-              prop="createTime"
-              v-if="columns[6].visible"
-              width="160"
+          </el-form-item>
+          <el-form-item label="状态" prop="status">
+            <el-select
+              v-model="queryParams.status"
+              placeholder="用户状态"
+              clearable
+              class="!w-240px"
             >
-              <template #default="scope">
-                <span>{{ parseTime(scope.row.createTime) }}</span>
-              </template>
-            </el-table-column>
-            <el-table-column
-              label="操作"
-              align="center"
-              width="160"
-              class-name="small-padding fixed-width"
+              <el-option
+                v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)"
+                :key="dict.value"
+                :label="dict.label"
+                :value="dict.value"
+              />
+            </el-select>
+          </el-form-item>
+          <el-form-item label="创建时间" prop="createTime">
+            <el-date-picker
+              v-model="queryParams.createTime"
+              value-format="YYYY-MM-DD HH:mm:ss"
+              type="datetimerange"
+              start-placeholder="开始日期"
+              end-placeholder="结束日期"
+              class="!w-240px"
+            />
+          </el-form-item>
+          <el-form-item>
+            <el-button @click="handleQuery"><Icon icon="ep:search" />搜索</el-button>
+            <el-button @click="resetQuery"><Icon icon="ep:refresh" />重置</el-button>
+            <el-button
+              type="primary"
+              plain
+              @click="openForm('create')"
+              v-hasPermi="['system:user:create']"
             >
-              <template #default="scope">
-                <div class="flex justify-center items-center">
-                  <el-button
-                    type="primary"
-                    link
-                    @click="handleUpdate(scope.row)"
-                    v-hasPermi="['system:user:update']"
-                    ><Icon icon="ep:edit" />修改</el-button
-                  >
-                  <el-dropdown
-                    @command="(command) => handleCommand(command, scope.$index, scope.row)"
-                    v-hasPermi="[
-                      'system:user:delete',
-                      'system:user:update-password',
-                      'system:permission:assign-user-role'
-                    ]"
-                  >
-                    <el-button type="primary" link><Icon icon="ep:d-arrow-right" />更多</el-button>
-                    <template #dropdown>
-                      <el-dropdown-menu>
-                        <!-- div包住避免控制台报错:Runtime directive used on component with non-element root node -->
-                        <div v-if="scope.row.id !== 1" v-hasPermi="['system:user:delete']">
-                          <el-dropdown-item command="handleDelete" type="text"
-                            ><Icon icon="ep:delete" />删除</el-dropdown-item
-                          >
-                        </div>
-                        <div v-hasPermi="['system:user:update-password']">
-                          <el-dropdown-item command="handleResetPwd" type="text"
-                            ><Icon icon="ep:key" />重置密码</el-dropdown-item
-                          ></div
-                        >
-                        <div v-hasPermi="['system:permission:assign-user-role']">
-                          <el-dropdown-item command="handleRole" type="text"
-                            ><Icon icon="ep:circle-check" />分配角色</el-dropdown-item
-                          ></div
-                        >
-                      </el-dropdown-menu>
-                    </template>
-                  </el-dropdown>
-                </div>
-              </template>
-            </el-table-column>
-          </el-table>
-          <pagination
-            v-show="total > 0"
-            :total="total"
-            v-model:page="queryParams.pageNo"
-            v-model:limit="queryParams.pageSize"
-            @pagination="getList"
+              <Icon icon="ep:plus" /> 新增
+            </el-button>
+            <el-button
+              type="warning"
+              plain
+              @click="handleImport"
+              v-hasPermi="['system:user:import']"
+            >
+              <Icon icon="ep:upload" /> 导入
+            </el-button>
+            <el-button
+              type="success"
+              plain
+              @click="handleExport"
+              :loading="exportLoading"
+              v-hasPermi="['system:user:export']"
+            >
+              <Icon icon="ep:download" />导出
+            </el-button>
+          </el-form-item>
+        </el-form>
+      </content-wrap>
+      <content-wrap>
+        <el-table v-loading="loading" :data="list">
+          <el-table-column label="用户编号" align="center" key="id" prop="id" />
+          <el-table-column
+            label="用户名称"
+            align="center"
+            prop="username"
+            :show-overflow-tooltip="true"
           />
-        </el-col>
-      </el-row>
-    </content-wrap>
-    <!-- 添加或修改用户对话框 -->
-    <UserForm ref="userFormRef" @success="getList" />
-    <!-- 用户导入对话框 -->
-    <UserImportForm ref="userImportFormRef" @success="getList" />
-    <!-- 分配角色 -->
-    <UserAssignRoleForm ref="userAssignRoleFormRef" @success="getList" />
-  </div>
+          <el-table-column
+            label="用户昵称"
+            align="center"
+            prop="nickname"
+            :show-overflow-tooltip="true"
+          />
+          <el-table-column
+            label="部门"
+            align="center"
+            key="deptName"
+            prop="dept.name"
+            :show-overflow-tooltip="true"
+          />
+          <el-table-column label="手机号码" align="center" prop="mobile" width="120" />
+          <el-table-column label="状态" key="status">
+            <template #default="scope">
+              <el-switch
+                v-model="scope.row.status"
+                :active-value="0"
+                :inactive-value="1"
+                @change="handleStatusChange(scope.row)"
+              />
+            </template>
+          </el-table-column>
+          <el-table-column
+            label="创建时间"
+            align="center"
+            prop="createTime"
+            :formatter="dateFormatter"
+            width="180"
+          />
+          <el-table-column label="操作" align="center" width="160">
+            <template #default="scope">
+              <div class="flex justify-center items-center">
+                <el-button
+                  type="primary"
+                  link
+                  @click="openForm('update', scope.row.id)"
+                  v-hasPermi="['system:user:update']"
+                >
+                  <Icon icon="ep:edit" />修改
+                </el-button>
+                <el-dropdown
+                  @command="(command) => handleCommand(command, scope.row)"
+                  v-hasPermi="[
+                    'system:user:delete',
+                    'system:user:update-password',
+                    'system:permission:assign-user-role'
+                  ]"
+                >
+                  <el-button type="primary" link><Icon icon="ep:d-arrow-right" /> 更多</el-button>
+                  <template #dropdown>
+                    <el-dropdown-menu>
+                      <el-dropdown-item
+                        command="handleDelete"
+                        v-if="checkPermi(['system:user:delete'])"
+                      >
+                        <Icon icon="ep:delete" />删除
+                      </el-dropdown-item>
+                      <el-dropdown-item
+                        command="handleResetPwd"
+                        v-if="checkPermi(['system:user:update-password'])"
+                      >
+                        <Icon icon="ep:key" />重置密码
+                      </el-dropdown-item>
+                      <el-dropdown-item
+                        command="handleRole"
+                        v-if="checkPermi(['system:permission:assign-user-role'])"
+                      >
+                        <Icon icon="ep:circle-check" />分配角色
+                      </el-dropdown-item>
+                    </el-dropdown-menu>
+                  </template>
+                </el-dropdown>
+              </div>
+            </template>
+          </el-table-column>
+        </el-table>
+        <Pagination
+          :total="total"
+          v-model:page="queryParams.pageNo"
+          v-model:limit="queryParams.pageSize"
+          @pagination="getList"
+        />
+      </content-wrap>
+    </el-col>
+  </el-row>
+
+  <!-- 添加或修改用户对话框 -->
+  <UserForm ref="formRef" @success="getList" />
+  <!-- 用户导入对话框 -->
+  <UserImportForm ref="importFormRef" @success="getList" />
+  <!-- 分配角色 -->
+  <UserAssignRoleForm ref="assignRoleFormRef" @success="getList" />
 </template>
-
 <script setup lang="ts" name="User">
-import download from '@/utils/download'
-import { parseTime } from '@/utils/formatTime'
 import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
+import { checkPermi } from '@/utils/permission'
+import { dateFormatter } from '@/utils/formatTime'
+import download from '@/utils/download'
 import { CommonStatusEnum } from '@/utils/constants'
-
-import {
-  deleteUserApi,
-  exportUserApi,
-  resetUserPwdApi,
-  updateUserStatusApi,
-  getUserPageApi,
-  UserVO
-} from '@/api/system/user'
-
-import UserForm from './components/UserForm.vue'
-import UserImportForm from './components/UserImportForm.vue'
-import UserAssignRoleForm from './components/UserAssignRoleForm.vue'
-import UserDeptTree from './components/UserDeptTree.vue'
-
+import * as UserApi from '@/api/system/user'
+import UserForm from './UserForm.vue'
+import UserImportForm from './UserImportForm.vue'
+import UserAssignRoleForm from './UserAssignRoleForm.vue'
+import DeptTree from './DeptTree.vue'
 const message = useMessage() // 消息弹窗
 const { t } = useI18n() // 国际化
 
+const loading = ref(true) // 列表的加载中
+const total = ref(0) // 列表的总页数
+const list = ref([]) // 列表的数
 const queryParams = reactive({
   pageNo: 1,
   pageSize: 10,
@@ -260,35 +220,20 @@ const queryParams = reactive({
   deptId: undefined,
   createTime: []
 })
-const showSearch = ref(true)
+const queryFormRef = ref() // 搜索的表单
 
-const handleDeptNodeClick = async (row: { [key: string]: any }) => {
-  queryParams.deptId = row.id
-  getList()
-}
-
-// 用户列表
-const userList = ref<UserVO[]>([])
-const loading = ref(false)
-const total = ref(0)
-const columns = ref([
-  { key: 0, label: `用户编号`, visible: true },
-  { key: 1, label: `用户名称`, visible: true },
-  { key: 2, label: `用户昵称`, visible: true },
-  { key: 3, label: `部门`, visible: true },
-  { key: 4, label: `手机号码`, visible: true },
-  { key: 5, label: `状态`, visible: true },
-  { key: 6, label: `创建时间`, visible: true }
-])
-/* 查询列表 */
-const getList = () => {
+/** 查询列表 */
+const getList = async () => {
   loading.value = true
-  getUserPageApi(queryParams).then((response) => {
-    userList.value = response.list
-    total.value = response.total
+  try {
+    const data = await UserApi.getUserPage(queryParams.value)
+    list.value = data.list
+    total.value = data.total
+  } finally {
     loading.value = false
-  })
+  }
 }
+
 /** 搜索按钮操作 */
 const handleQuery = () => {
   queryParams.pageNo = 1
@@ -296,54 +241,67 @@ const handleQuery = () => {
 }
 
 /** 重置按钮操作 */
-const queryFormRef = ref()
 const resetQuery = () => {
   queryFormRef.value?.resetFields()
   handleQuery()
 }
 
-// 添加或编辑
-const userFormRef = ref()
-// 添加用户
-const handleAdd = () => {
-  userFormRef.value?.openForm()
+/** 处理部门被点击 */
+const handleDeptNodeClick = async (row) => {
+  queryParams.deptId = row.id
+  await getList()
 }
 
-// 用户导入
-const userImportFormRef = ref()
+/** 添加/修改操作 */
+const formRef = ref()
+const openForm = (type: string, id?: number) => {
+  formRef.value.open(type, id)
+}
+
+/** 用户导入 */
+const importFormRef = ref()
 const handleImport = () => {
-  userImportFormRef.value?.openForm()
+  importFormRef.value.open()
 }
 
-// 用户导出
+/** 修改用户状态 */
+const handleStatusChange = async (row: UserApi.UserVO) => {
+  try {
+    // 修改状态的二次确认
+    const text = row.status === CommonStatusEnum.ENABLE ? '启用' : '停用'
+    await message.confirm('确认要"' + text + '""' + row.username + '"用户吗?')
+    // 发起修改状态
+    await UserApi.updateUserStatus(row.id, row.status)
+    // 刷新列表
+    await getList()
+  } catch {
+    // 取消后,进行恢复按钮
+    row.status =
+      row.status === CommonStatusEnum.ENABLE ? CommonStatusEnum.DISABLE : CommonStatusEnum.ENABLE
+  }
+}
+
+/** 导出按钮操作 */
 const exportLoading = ref(false)
-const handleExport = () => {
-  message
-    .confirm('是否确认导出所有用户数据项?')
-    .then(async () => {
-      // 处理查询参数
-      let params = { ...queryParams }
-      params.pageNo = 1
-      params.pageSize = 99999
-      exportLoading.value = true
-      const response = await exportUserApi(params)
-      download.excel(response, '用户数据.xls')
-    })
-    .catch(() => {})
-    .finally(() => {
-      exportLoading.value = false
-    })
+const handleExport = async () => {
+  try {
+    // 导出的二次确认
+    await message.exportConfirm()
+    // 发起导出
+    exportLoading.value = true
+    const data = await UserApi.exportUser(queryParams)
+    download.excel(data, '用户数据.xls')
+  } catch {
+  } finally {
+    exportLoading.value = false
+  }
 }
 
-// 操作分发
-const handleCommand = (command: string, index: number, row: UserVO) => {
-  console.log(index)
+/** 操作分发 */
+const handleCommand = (command: string, row: UserApi.UserVO) => {
   switch (command) {
-    case 'handleUpdate':
-      handleUpdate(row) //修改客户信息
-      break
     case 'handleDelete':
-      handleDelete(row) //红号变更
+      handleDelete(row.id)
       break
     case 'handleResetPwd':
       handleResetPwd(row)
@@ -356,67 +314,42 @@ const handleCommand = (command: string, index: number, row: UserVO) => {
   }
 }
 
-// 用户状态修改
-const handleStatusChange = (row: UserVO) => {
-  let text = row.status === CommonStatusEnum.ENABLE ? '启用' : '停用'
-  message
-    .confirm('确认要"' + text + '""' + row.username + '"用户吗?', t('common.reminder'))
-    .then(async () => {
-      row.status =
-        row.status === CommonStatusEnum.ENABLE ? CommonStatusEnum.ENABLE : CommonStatusEnum.DISABLE
-      await updateUserStatusApi(row.id, row.status)
-      message.success(text + '成功')
-      // 刷新列表
-      getList()
-    })
-    .catch(() => {
-      row.status =
-        row.status === CommonStatusEnum.ENABLE ? CommonStatusEnum.DISABLE : CommonStatusEnum.ENABLE
-    })
+/** 删除按钮操作 */
+const handleDelete = async (id: number) => {
+  try {
+    // 删除的二次确认
+    await message.delConfirm()
+    // 发起删除
+    await UserApi.deleteUser(id)
+    message.success(t('common.delSuccess'))
+    // 刷新列表
+    await getList()
+  } catch {}
 }
 
-// 具体数据单行操作
-/** 修改按钮操作 */
-const handleUpdate = (row: UserVO) => {
-  userFormRef.value?.openForm(row)
+/** 重置密码 */
+const handleResetPwd = async (row: UserApi.UserVO) => {
+  try {
+    // 重置的二次确认
+    const result = await message.prompt(
+      '请输入"' + row.username + '"的新密码',
+      t('common.reminder')
+    )
+    const password = result.value
+    // 发起重置
+    await UserApi.resetUserPwd(row.id, password)
+    message.success('修改成功,新密码是:' + password)
+  } catch {}
 }
 
-// 删除用户
-const handleDelete = (row: UserVO) => {
-  const ids = row.id
-  message
-    .confirm('是否确认删除用户编号为"' + ids + '"的数据项?')
-    .then(async () => {
-      await deleteUserApi(ids)
-      message.success('删除成功')
-      getList()
-    })
-    .catch((e) => {
-      console.error(e)
-    })
+/** 分配角色 */
+const assignRoleFormRef = ref()
+const handleRole = (row: UserApi.UserVO) => {
+  assignRoleFormRef.value.open(row)
 }
 
-// 重置密码
-const handleResetPwd = (row: UserVO) => {
-  message
-    .prompt('请输入"' + row.username + '"的新密码', t('common.reminder'))
-    .then(async ({ value }) => {
-      await resetUserPwdApi(row.id, value)
-      message.success('修改成功,新密码是:' + value)
-    })
-    .catch((e) => {
-      console.error(e)
-    })
-}
-
-// 分配角色
-const userAssignRoleFormRef = ref()
-const handleRole = (row: UserVO) => {
-  userAssignRoleFormRef.value?.openForm(row)
-}
-
-// ========== 初始化 ==========
-onMounted(async () => {
+/** 初始化 */
+onMounted(() => {
   getList()
 })
 </script>