优化更新

This commit is contained in:
2026-09-13 18:12:07 +08:00
parent 7f758cc6e9
commit d7a081e8b7
92 changed files with 2429 additions and 1117 deletions
@@ -146,7 +146,7 @@ class ConfigWeb(BaseModel):
| 用途 | 枚举值(下拉选项) | 系统参数(配置值) |
| 值类型 | 简单值(字符串) | 可存储较长的配置内容 |
| 典型场景 | 状态、性别、类型 | SMTP配置、站点信息 |
| 前端用法 | el-select 选项 | 配置表单 |
| 前端用法 | n-select 选项 | 配置表单 |
| 缓存策略 | Redis 缓存 | 按需查询 |
| 数据量 | 通常每个字典 < 50 项 | 每个分组 < 20 项 |
@@ -158,18 +158,16 @@ class ConfigWeb(BaseModel):
```vue
<template>
<el-form-item :label="item.name">
<n-form-item :label="item.name">
<!-- 文本输入 -->
<el-input v-if="item.type === 'text'" v-model="item.value" />
<n-input v-if="item.type === 'text'" v-model:value="item.value" />
<!-- 数字输入 -->
<el-input-number v-else-if="item.type === 'number'" v-model="item.value" />
<n-input-number v-else-if="item.type === 'number'" v-model:value="item.value" />
<!-- 下拉选择 -->
<el-select v-else-if="item.type === 'select'" v-model="item.value">
<el-option v-for="opt in parseOptions(item.options)" :key="opt.value" :label="opt.label" :value="opt.value" />
</el-select>
<n-select v-else-if="item.type === 'select'" v-model:value="item.value" :options="parseOptions(item.options)" />
<!-- 开关 -->
<el-switch v-else-if="item.type === 'switch'" v-model="item.value" />
</el-form-item>
<n-switch v-else-if="item.type === 'switch'" v-model:value="item.value" />
</n-form-item>
</template>
```
@@ -87,14 +87,7 @@ def _enrich_records(records):
```vue
<template>
<el-select v-model="form.trainingMethod" placeholder="请选择培训方式">
<el-option
v-for="item in dictOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
<n-select v-model:value="form.trainingMethod" placeholder="请选择培训方式" :options="dictOptions" />
</template>
<script setup>
@@ -116,7 +109,7 @@ onMounted(async () => {
```typescript
import { h } from 'vue';
import { ElTag } from 'element-plus';
import { NTag } from 'naive-ui';
export const columns = [
{
@@ -125,7 +118,7 @@ export const columns = [
render(record) {
const map = { 1: '线上', 2: '线下', 3: '混合' };
const typeMap = { 1: 'success', 2: 'warning', 3: 'info' };
return h(ElTag, { type: typeMap[record.row.trainingMethod] }, {
return h(NTag, { type: typeMap[record.row.trainingMethod] }, {
default: () => map[record.row.trainingMethod] || '-'
});
},
@@ -105,19 +105,12 @@ const statusOptions = dictStore.getDict('sys_status')
```vue
<template>
<!-- el-select 下拉选择 -->
<el-select v-model="form.status" placeholder="请选择状态">
<el-option
v-for="item in statusOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
<!-- n-select 下拉选择 -->
<n-select v-model:value="form.status" placeholder="请选择状态" :options="statusOptions" />
<!-- el-tag 标签展示 -->
<el-tag v-if="form.status === '1'">正常</el-tag>
<el-tag v-else type="danger">停用</el-tag>
<!-- n-tag 标签展示 -->
<n-tag v-if="form.status === '1'">正常</n-tag>
<n-tag v-else type="error">停用</n-tag>
</template>
```
@@ -174,7 +167,7 @@ export const useDictStore = defineStore('dict', {
```
1. 两级结构:字典类型(分组)+ 字典项(具体值),清晰管理
2. 前端集成:useDictStore 统一管理,el-select 直接绑定
2. 前端集成:useDictStore 统一管理,n-select 直接绑定
3. 值为字符串:字典项 value 统一为字符串类型
4. 避免硬编码:枚举值统一走字典,修改无需改代码
5. Redis 缓存:减少数据库查询,提升性能
@@ -37,16 +37,16 @@ function useLockFn(fn) {
### 按钮 loading
ElementPlus 的按钮组件支持 `loading` 属性,请求期间禁用按钮:
NaiveUI 的按钮组件支持 `loading` 属性,请求期间禁用按钮:
```vue
<el-button
<n-button
type="primary"
:loading="submitting"
@click="handleSubmit"
>
提交
</el-button>
</n-button>
<script setup>
const submitting = ref(false)
@@ -119,10 +119,10 @@ def get_user_permissions(user_id):
```html
<!-- 只有拥有 sys:user:add 权限的用户才能看到此按钮 -->
<el-button v-perm="'sys:user:add'" type="primary">新增</el-button>
<n-button v-perm="'sys:user:add'" type="primary">新增</n-button>
<!-- 多个权限,满足其一即可 -->
<el-button v-perm="['sys:user:update', 'sys:user:delete']">操作</el-button>
<n-button v-perm="['sys:user:update', 'sys:user:delete']">操作</n-button>
```
### 路由守卫