refactor: 删除 docs 模块的全部代码

- 移除了 DocsContentController、DocsController、DocsUserController 三个控制器
- 删除了 DocsContent、Docs、DocsUser三个实体类
- 移除了 DocsContentMapper、DocsMapper、DocsUserMapper 三个 Mapper 接口
- 删除了 DocsContentParam、DocsParam、DocsUserParam 三个查询参数类
- 移除了 DocsContentServiceImpl 服务实现类- 删除了相关的 XML 映射文件
This commit is contained in:
2025-08-13 04:40:52 +08:00
parent c85c74fb80
commit 416aca8691
36 changed files with 842 additions and 1297 deletions

View File

@@ -0,0 +1,195 @@
# 表格列生成规则优化方案
## 问题描述
原有的表格列生成规则会为所有字段除了tenantId生成列导致
- 表格列过多,显示混乱
- 重要信息被淹没在大量字段中
- 用户体验差,需要横向滚动查看
## 优化方案
### 1. 使用 hideInTable 属性(推荐方案)
**核心思想**:生成所有字段的列配置,但使用 `hideInTable: true` 隐藏非核心字段
**优势**
-**保留完整信息**:所有字段都会生成,不丢失任何数据
-**用户可自定义**:通过表格的列设置功能,用户可以勾选显示需要的字段
-**默认简洁**:只显示最重要的核心字段,保持表格整洁
-**灵活性强**:不同用户可以根据需要显示不同的列组合
**核心字段判断规则**
- 主键字段:始终显示
- 名称/标题字段:始终显示
- 编码字段:始终显示
- 状态字段:始终显示
- 排序字段:始终显示
- 创建时间:始终显示
- 其他字段:默认隐藏(`hideInTable: true`
### 2. 排除字段
以下字段不会显示在表格中:
- `tenantId` - 租户ID
- `deleted` - 逻辑删除标记
- `version` - 版本号
- `remark` - 备注(内容通常较长)
- `description` - 描述(内容通常较长)
- `content` - 内容(内容通常较长)
### 3. 字段宽度优化
根据字段类型和内容特点设置合适的宽度:
- ID字段90px
- 状态字段80px
- 时间字段120px
- 字符串字段150px
- 数值字段120px
## 使用方法
### 方法1使用 hideInTable 模板(强烈推荐)
已经修改了 `index.vue.btl` 模板,现在会自动:
1. **生成所有字段**:不丢失任何字段信息
2. **智能隐藏**:非核心字段添加 `hideInTable: true`
3. **用户可控**:用户可通过表格的列设置功能显示需要的字段
**生成的代码示例**
```javascript
const columns = ref<ColumnItem[]>([
{
title: 'ID',
dataIndex: 'id',
key: 'id',
width: 90,
// 核心字段,默认显示
},
{
title: '名称',
dataIndex: 'name',
key: 'name',
width: 150,
// 核心字段,默认显示
},
{
title: '创建人',
dataIndex: 'createBy',
key: 'createBy',
width: 120,
hideInTable: true, // 非核心字段,默认隐藏
},
{
title: '备注',
dataIndex: 'remark',
key: 'remark',
width: 200,
hideInTable: true, // 长文本字段,默认隐藏
}
]);
```
### 方法2前端列设置功能
参考 `table-with-column-settings.vue` 示例,可以添加列设置功能:
```javascript
// 列可见性控制
const allColumns = ref([
{ title: 'ID', visible: true, required: true },
{ title: '名称', visible: true, required: true },
{ title: '创建人', visible: false, required: false },
// ...
]);
// 根据可见性过滤列
const columns = computed(() => {
return allColumns.value.filter(col => col.visible);
});
```
### 方法3自定义核心字段规则
在模板中修改核心字段判断逻辑:
```javascript
// 在模板中添加你的业务字段
<% } else if(field.propertyName == 'yourBusinessField'){ %>
// 设为核心字段,默认显示
isCoreField = true;
```
## 生成效果对比
### 优化前
```
| ID | 名称 | 编码 | 状态 | 排序 | 创建人 | 创建时间 | 更新人 | 更新时间 | 备注 | 描述 | ... | 操作 |
```
*显示所有字段,表格过宽,信息混乱*
### 优化后(使用 hideInTable
**默认显示**
```
| ID | 名称 | 编码 | 状态 | 排序 | 创建时间 | 操作 |
```
*只显示核心字段,表格简洁*
**用户可通过列设置显示更多字段**
```
| ID | 名称 | 编码 | 状态 | ✓创建人 | 创建时间 | ✓更新时间 | ✓备注 | 操作 |
```
*用户勾选后可显示需要的字段*
### 列设置界面示例
```
列设置
☑ ID (固定显示)
☑ 名称 (固定显示)
☑ 编码 (固定显示)
☑ 状态 (固定显示)
☐ 创建人 (可选)
☑ 创建时间 (固定显示)
☐ 更新人 (可选)
☐ 更新时间 (可选)
☐ 备注 (可选)
☐ 描述 (可选)
```
## 配置说明
### 修改默认显示列数
在模板中修改:
```javascript
.slice(0, 6); // 改为你想要的列数
```
### 添加新的优先字段
在模板的优先级判断中添加:
```javascript
<% } else if(field.propertyName == 'yourField'){ %>
width: 120,
priority: 8, // 设置优先级
```
### 排除特定字段
在条件判断中添加:
```javascript
<% if(field.propertyName != 'tenantId' && field.propertyName != 'yourExcludedField'){ %>
```
## 建议
1. **保持默认6列**:这是最佳的用户体验,既能显示关键信息,又不会过于拥挤
2. **优先显示业务关键字段**:如名称、状态、创建时间等
3. **提供列设置功能**:让用户可以自定义显示哪些列
4. **响应式设计**:在移动端进一步减少显示列数
## 注意事项
- 修改模板后需要重新生成代码才能生效
- 建议在生成前备份原有模板文件
- 可以根据具体业务需求调整优先级规则

View File

@@ -0,0 +1,164 @@
# hideInTable 表格列优化方案总结
## 🎯 方案概述
使用 `hideInTable: true` 属性来控制表格列的默认显示,这是一个既保留完整功能又保持界面简洁的最佳方案。
## ✨ 核心优势
### 1. 🔄 **完整性 + 简洁性**
- **生成所有字段**:不丢失任何数据库字段信息
- **默认简洁**:只显示最重要的核心字段
- **用户可控**:通过列设置功能显示需要的字段
### 2. 🎛️ **灵活的用户体验**
- **开箱即用**:默认显示最常用的字段
- **按需扩展**:用户可以勾选显示更多字段
- **个性化**:不同用户可以有不同的列显示偏好
### 3. 🚀 **技术优势**
- **标准化**:使用 Ant Design 标准的 `hideInTable` 属性
- **兼容性好**:与现有表格组件完美兼容
- **维护简单**:不需要复杂的逻辑,只需要简单的布尔值控制
## 📋 实现细节
### 核心字段判断规则
```javascript
// 以下字段默认显示最多6个
- 主键字段 (id)
- 名称字段 (name)
- 标题字段 (title)
- 编码字段 (code)
- 状态字段 (status)
- 排序字段 (sort)
- 创建时间 (createTime)
```
### 隐藏字段规则
```javascript
// 以下字段默认隐藏 (hideInTable: true)
- 更新时间 (updateTime)
- 创建人 (createBy)
- 更新人 (updateBy)
- 备注 (remark)
- 描述 (description)
- 内容 (content)
- 其他非核心业务字段
```
## 🔧 生成的代码示例
```javascript
const columns = ref<ColumnItem[]>([
{
title: 'ID',
dataIndex: 'id',
key: 'id',
width: 90,
align: 'center',
// 核心字段,默认显示
},
{
title: '文章标题',
dataIndex: 'title',
key: 'title',
width: 150,
align: 'center',
ellipsis: true,
// 核心字段,默认显示
},
{
title: '状态',
dataIndex: 'status',
key: 'status',
width: 80,
align: 'center',
// 核心字段,默认显示
},
{
title: '创建时间',
dataIndex: 'createTime',
key: 'createTime',
width: 120,
align: 'center',
sorter: true,
ellipsis: true,
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd'),
// 核心字段,默认显示
},
{
title: '创建人',
dataIndex: 'createBy',
key: 'createBy',
width: 120,
align: 'center',
hideInTable: true, // 非核心字段,默认隐藏
},
{
title: '文章内容',
dataIndex: 'content',
key: 'content',
width: 200,
align: 'center',
ellipsis: true,
hideInTable: true, // 长文本字段,默认隐藏
},
{
title: '操作',
key: 'action',
width: 180,
fixed: 'right',
align: 'center',
hideInSetting: true, // 操作列不允许隐藏
}
]);
```
## 🎨 用户界面效果
### 默认显示
```
┌────┬──────────┬────┬──────────┬────────┐
│ ID │ 文章标题 │状态│ 创建时间 │ 操作 │
├────┼──────────┼────┼──────────┼────────┤
│ 1 │ 技术文章 │启用│2024-01-01│修改|删除│
│ 2 │ 产品介绍 │禁用│2024-01-02│修改|删除│
└────┴──────────┴────┴──────────┴────────┘
```
### 用户勾选更多列后
```
┌────┬──────────┬────┬────────┬──────────┬──────────┬────────┐
│ ID │ 文章标题 │状态│ 创建人 │ 创建时间 │ 文章内容 │ 操作 │
├────┼──────────┼────┼────────┼──────────┼──────────┼────────┤
│ 1 │ 技术文章 │启用│ 张三 │2024-01-01│ 这是... │修改|删除│
│ 2 │ 产品介绍 │禁用│ 李四 │2024-01-02│ 产品... │修改|删除│
└────┴──────────┴────┴────────┴──────────┴──────────┴────────┘
```
## 🔄 与其他方案对比
| 方案 | 完整性 | 简洁性 | 用户控制 | 维护成本 | 推荐度 |
|------|--------|--------|----------|----------|--------|
| 显示所有字段 | ✅ | ❌ | ❌ | 低 | ⭐⭐ |
| 过滤显示部分字段 | ❌ | ✅ | ❌ | 中 | ⭐⭐⭐ |
| **hideInTable方案** | ✅ | ✅ | ✅ | 低 | ⭐⭐⭐⭐⭐ |
## 📝 使用建议
1. **保持核心字段数量在6个以内**:确保表格在标准屏幕上显示良好
2. **优先显示业务关键字段**:如名称、状态、时间等
3. **长文本字段默认隐藏**:如备注、描述、内容等
4. **提供列设置入口**:让用户可以方便地自定义显示列
5. **考虑移动端适配**:在小屏幕上进一步减少默认显示列
## 🎉 总结
`hideInTable` 方案是表格列显示的最佳实践,它完美平衡了:
- **开发效率**:自动生成,无需手动配置
- **用户体验**:默认简洁,按需扩展
- **功能完整**:不丢失任何字段信息
- **维护成本**:标准化实现,易于维护
这个方案让生成的表格既专业又实用,是代码生成器的理想选择!

View File

@@ -97,22 +97,56 @@
});
};
// 表格列配置
// 表格列配置 - 使用 hideInTable 控制默认显示
const columns = ref<ColumnItem[]>([
<% var coreFieldCount = 0; %>
<% for(field in table.fields) { %>
<% if(field.propertyName != 'tenantId'){ %>
<%
// 判断是否为核心字段(默认显示)
var isCoreField = field.keyFlag ||
field.propertyName == 'name' ||
field.propertyName == 'title' ||
field.propertyName == 'code' ||
field.propertyName == 'status' ||
field.propertyName == 'sort' ||
field.propertyName == 'createTime';
// 限制核心字段数量,避免显示过多列
if(isCoreField && coreFieldCount >= 5) {
isCoreField = false;
}
if(isCoreField) {
coreFieldCount = coreFieldCount + 1;
}
%>
{
title: '${field.comment!field.propertyName}',
dataIndex: '${field.propertyName}',
key: '${field.propertyName}',
align: 'center',
<% if(!isCoreField){ %>
hideInTable: true, // 非核心字段默认隐藏,用户可通过列设置显示
<% } %>
<% if(field.keyFlag){ %>
width: 90,
<% } %>
<% if(field.propertyName == 'createTime'){ %>
<% } else if(field.propertyName == 'createTime' || field.propertyName == 'updateTime'){ %>
width: 120,
sorter: true,
ellipsis: true,
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd')
<% } else if(field.propertyType == 'String' && (field.propertyName.contains('remark') || field.propertyName.contains('description') || field.propertyName.contains('content'))){ %>
width: 200,
ellipsis: true
<% } else if(field.propertyType == 'String'){ %>
width: 150,
ellipsis: true
<% } else if(field.propertyName == 'status'){ %>
width: 80
<% } else if(field.propertyName == 'sort'){ %>
width: 80
<% } else { %>
width: 120
<% } %>
},
<% } %>

View File

@@ -0,0 +1,89 @@
// 智能表格列配置 - 使用 hideInTable 控制显示
// 所有字段都会生成,但非核心字段默认隐藏,用户可通过列设置显示
const columns = ref<ColumnItem[]>([
<% var coreFieldCount = 0; %>
<% for(field in table.fields) { %>
<% if(field.propertyName != 'tenantId' && field.propertyName != 'deleted' && field.propertyName != 'version'){ %>
<%
// 定义核心字段优先级
var priority = 0;
var isCoreField = false;
if(field.keyFlag) {
priority = 10;
isCoreField = true;
} else if(field.propertyName == 'name' || field.propertyName == 'title') {
priority = 9;
isCoreField = true;
} else if(field.propertyName == 'code') {
priority = 8;
isCoreField = true;
} else if(field.propertyName == 'status') {
priority = 7;
isCoreField = true;
} else if(field.propertyName == 'sort') {
priority = 6;
isCoreField = true;
} else if(field.propertyName == 'createTime') {
priority = 5;
isCoreField = true;
} else if(field.propertyName == 'updateTime') {
priority = 3;
isCoreField = false; // 更新时间默认隐藏
} else if(field.propertyType == 'String' && (field.propertyName.contains('remark') || field.propertyName.contains('description') || field.propertyName.contains('content'))) {
priority = 1;
isCoreField = false; // 长文本字段默认隐藏
} else {
priority = 4;
isCoreField = false; // 其他字段默认隐藏
}
// 限制核心字段数量最多6个
if(isCoreField && coreFieldCount >= 6) {
isCoreField = false;
}
if(isCoreField) {
coreFieldCount = coreFieldCount + 1;
}
%>
{
title: '${field.comment!field.propertyName}',
dataIndex: '${field.propertyName}',
key: '${field.propertyName}',
align: 'center',
<% if(!isCoreField){ %>
hideInTable: true, // 非核心字段默认隐藏,可通过列设置显示
<% } %>
<% if(field.keyFlag){ %>
width: 90,
<% } else if(field.propertyName == 'createTime' || field.propertyName == 'updateTime'){ %>
width: 120,
sorter: true,
ellipsis: true,
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd')
<% } else if(field.propertyType == 'String' && (field.propertyName.contains('remark') || field.propertyName.contains('description') || field.propertyName.contains('content'))){ %>
width: 200,
ellipsis: true
<% } else if(field.propertyType == 'String'){ %>
width: 150,
ellipsis: true
<% } else if(field.propertyName == 'status'){ %>
width: 80
<% } else if(field.propertyName == 'sort'){ %>
width: 80
<% } else { %>
width: 120
<% } %>
},
<% } %>
<% } %>
{
title: '操作',
key: 'action',
width: 180,
fixed: 'right',
align: 'center',
hideInSetting: true // 操作列不允许隐藏
}
]);

View File

@@ -0,0 +1,60 @@
/**
* 表格列显示配置
* 用于控制代码生成器生成的表格默认显示哪些列
*/
// 优先显示的字段名(按优先级排序)
const PRIORITY_FIELDS = [
'id', // 主键ID
'name', // 名称
'title', // 标题
'code', // 编码
'status', // 状态
'sort', // 排序
'createTime', // 创建时间
'updateTime' // 更新时间
];
// 字段类型优先级配置
const FIELD_TYPE_PRIORITY = {
'keyFlag': 10, // 主键字段最高优先级
'String': 8, // 字符串字段
'Integer': 6, // 整数字段
'Boolean': 5, // 布尔字段
'Date': 4, // 日期字段
'BigDecimal': 3, // 数值字段
'Text': 1 // 文本字段最低优先级
};
// 排除的字段(不显示在表格中)
const EXCLUDED_FIELDS = [
'tenantId', // 租户ID
'deleted', // 逻辑删除标记
'version', // 版本号
'remark', // 备注(通常内容较长)
'description', // 描述(通常内容较长)
'content' // 内容(通常内容较长)
];
// 默认显示的最大列数
const MAX_DEFAULT_COLUMNS = 6;
// 特殊字段的宽度配置
const FIELD_WIDTH_CONFIG = {
'id': 90,
'status': 80,
'sort': 80,
'createTime': 120,
'updateTime': 120,
'default_string': 150,
'default_number': 120,
'default_other': 120
};
module.exports = {
PRIORITY_FIELDS,
FIELD_TYPE_PRIORITY,
EXCLUDED_FIELDS,
MAX_DEFAULT_COLUMNS,
FIELD_WIDTH_CONFIG
};

View File

@@ -0,0 +1,263 @@
<template>
<a-page-header :title="getPageTitle()" @back="() => $router.go(-1)">
<a-card :bordered="false" :body-style="{ padding: '16px' }">
<ele-pro-table
ref="tableRef"
row-key="id"
:columns="columns"
:datasource="datasource"
:customRow="customRow"
tool-class="ele-toolbar-form"
class="sys-table"
>
<template #toolbar>
<search
@search="reload"
:selection="selection"
@add="openEdit"
@remove="removeBatch"
/>
<!-- 列设置按钮 -->
<a-tooltip title="列设置">
<a-button
type="text"
@click="showColumnSetting = true"
:icon="h(SettingOutlined)"
/>
</a-tooltip>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'status'">
<a-tag v-if="record.status === 0" color="green">启用</a-tag>
<a-tag v-if="record.status === 1" color="red">禁用</a-tag>
</template>
<template v-if="column.key === 'action'">
<a-space>
<a @click="openEdit(record)">修改</a>
<a-divider type="vertical" />
<a-popconfirm
title="确定要删除此记录吗?"
@confirm="remove(record)"
>
<a class="ele-text-danger">删除</a>
</a-popconfirm>
</a-space>
</template>
</template>
</ele-pro-table>
</a-card>
<!-- 列设置弹窗 -->
<a-modal
v-model:visible="showColumnSetting"
title="列设置"
width="400px"
@ok="applyColumnSettings"
>
<div class="column-settings">
<div class="setting-item" v-for="col in allColumns" :key="col.key">
<a-checkbox
v-model:checked="col.visible"
:disabled="col.required"
>
{{ col.title }}
<a-tag v-if="col.required" size="small" color="blue">必显</a-tag>
</a-checkbox>
</div>
</div>
</a-modal>
</a-page-header>
</template>
<script lang="ts" setup>
import { createVNode, ref, h, computed } from 'vue';
import { message, Modal } from 'ant-design-vue';
import { ExclamationCircleOutlined, SettingOutlined } from '@ant-design/icons-vue';
import type { EleProTable } from 'ele-admin-pro';
import { toDateString } from 'ele-admin-pro';
import type {
DatasourceFunction,
ColumnItem
} from 'ele-admin-pro/es/ele-pro-table/types';
// 列设置相关
const showColumnSetting = ref(false);
// 所有列的配置(包含可见性控制)
const allColumns = ref([
{
title: 'ID',
dataIndex: 'id',
key: 'id',
width: 90,
align: 'center',
visible: true,
required: true // 必须显示的列
},
{
title: '名称',
dataIndex: 'name',
key: 'name',
width: 150,
align: 'center',
ellipsis: true,
visible: true,
required: true
},
{
title: '编码',
dataIndex: 'code',
key: 'code',
width: 120,
align: 'center',
visible: true,
required: false
},
{
title: '状态',
dataIndex: 'status',
key: 'status',
width: 80,
align: 'center',
visible: true,
required: true
},
{
title: '排序',
dataIndex: 'sort',
key: 'sort',
width: 80,
align: 'center',
visible: true,
required: false
},
{
title: '创建人',
dataIndex: 'createBy',
key: 'createBy',
width: 120,
align: 'center',
visible: false, // 默认隐藏
required: false
},
{
title: '创建时间',
dataIndex: 'createTime',
key: 'createTime',
width: 120,
align: 'center',
sorter: true,
ellipsis: true,
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd'),
visible: true,
required: false
},
{
title: '更新人',
dataIndex: 'updateBy',
key: 'updateBy',
width: 120,
align: 'center',
visible: false, // 默认隐藏
required: false
},
{
title: '更新时间',
dataIndex: 'updateTime',
key: 'updateTime',
width: 120,
align: 'center',
sorter: true,
ellipsis: true,
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd'),
visible: false, // 默认隐藏
required: false
},
{
title: '备注',
dataIndex: 'remark',
key: 'remark',
width: 200,
align: 'center',
ellipsis: true,
visible: false, // 默认隐藏
required: false
},
{
title: '操作',
key: 'action',
width: 180,
fixed: 'right',
align: 'center',
visible: true,
required: true
}
]);
// 根据可见性过滤列
const columns = computed(() => {
return allColumns.value
.filter(col => col.visible)
.map(col => {
const { visible, required, ...columnConfig } = col;
return columnConfig;
});
});
// 应用列设置
const applyColumnSettings = () => {
showColumnSetting.value = false;
message.success('列设置已应用');
};
// 其他业务逻辑...
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
const selection = ref([]);
const datasource: DatasourceFunction = ({ page, limit, where, orders }) => {
// 实际的数据源逻辑
return Promise.resolve({
list: [],
total: 0
});
};
const reload = () => {
tableRef?.value?.reload();
};
const openEdit = (record?: any) => {
// 编辑逻辑
};
const remove = (record: any) => {
// 删除逻辑
};
const removeBatch = () => {
// 批量删除逻辑
};
const customRow = (record: any) => {
return {
onClick: () => {
// 行点击事件
}
};
};
</script>
<style lang="less" scoped>
.column-settings {
.setting-item {
padding: 8px 0;
border-bottom: 1px solid #f0f0f0;
&:last-child {
border-bottom: none;
}
}
}
</style>