Browse Source
-表格列优化: 智能字段过滤、列宽优化、可配置的列显示 -移动端模板改进: XML文件关键词搜索优化、移动端模板全面升级 - ShopArticle相关文件更新: 控制器、实体、Mapper、Param、Service等 - 新增列配置模板: columns.config.vue.btl - 更新列表页面模板: index.tsx.btl、index.vue.btl - 更新Mapper XML模板: mapper.xml.btlmain
13 changed files with 764 additions and 328 deletions
@ -0,0 +1,117 @@ |
|||||
|
# 表格列优化方案 |
||||
|
|
||||
|
## 🔍 问题分析 |
||||
|
|
||||
|
当前生成的 Vue 管理页面会为数据表的每个字段都生成一列,导致: |
||||
|
- 列数过多,界面混乱 |
||||
|
- 水平滚动条出现,用户体验差 |
||||
|
- 重要信息被淹没在大量字段中 |
||||
|
|
||||
|
## ✅ 优化方案 |
||||
|
|
||||
|
### 方案1:智能字段过滤(已实现) |
||||
|
|
||||
|
**过滤规则**: |
||||
|
- 最多显示 6 列(不包括操作列) |
||||
|
- 自动过滤掉不重要的字段: |
||||
|
- `updateTime` - 更新时间(通常不需要显示) |
||||
|
- `remark` - 备注字段(通常内容较长) |
||||
|
- `description` - 描述字段(通常内容较长) |
||||
|
- `content` - 内容字段(通常内容很长) |
||||
|
|
||||
|
**优先显示字段**: |
||||
|
1. 主键字段(ID) |
||||
|
2. 名称/标题类字段 |
||||
|
3. 状态字段 |
||||
|
4. 创建时间 |
||||
|
5. 其他重要业务字段 |
||||
|
|
||||
|
### 方案2:列宽优化 |
||||
|
|
||||
|
**智能列宽设置**: |
||||
|
```javascript |
||||
|
// ID列:较窄 |
||||
|
width: 90 |
||||
|
|
||||
|
// 名称/标题列:中等宽度,支持省略号 |
||||
|
width: 150, ellipsis: true |
||||
|
|
||||
|
// 状态列:较窄 |
||||
|
width: 80 |
||||
|
|
||||
|
// 时间列:固定宽度,格式化显示 |
||||
|
width: 120, customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd') |
||||
|
|
||||
|
// 其他列:默认宽度 |
||||
|
width: 120, ellipsis: true |
||||
|
``` |
||||
|
|
||||
|
### 方案3:可配置的列显示 |
||||
|
|
||||
|
创建了 `columns.config.vue.btl` 模板,支持: |
||||
|
- 定义所有可用列 |
||||
|
- 设置默认显示的列 |
||||
|
- 运行时动态控制列的显示/隐藏 |
||||
|
|
||||
|
## 🎯 使用建议 |
||||
|
|
||||
|
### 1. 对于字段较多的表 |
||||
|
建议手动调整 `maxColumns` 值: |
||||
|
```javascript |
||||
|
var maxColumns = 4; // 减少到4列 |
||||
|
``` |
||||
|
|
||||
|
### 2. 对于特殊业务需求 |
||||
|
可以修改过滤条件,添加特定字段: |
||||
|
```javascript |
||||
|
// 添加特定字段到显示列表 |
||||
|
if(field.propertyName == 'yourSpecialField') { |
||||
|
// 强制显示这个字段 |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
### 3. 启用列控制功能 |
||||
|
如果需要用户可以控制列的显示,可以: |
||||
|
1. 使用 `columns.config.vue.btl` 模板 |
||||
|
2. 添加列显示控制组件 |
||||
|
3. 实现列的动态显示/隐藏 |
||||
|
|
||||
|
## 📋 优化效果 |
||||
|
|
||||
|
### 优化前 |
||||
|
- 显示所有字段(可能10+列) |
||||
|
- 界面拥挤,需要水平滚动 |
||||
|
- 重要信息不突出 |
||||
|
|
||||
|
### 优化后 |
||||
|
- 最多显示6个重要列 |
||||
|
- 界面清爽,信息重点突出 |
||||
|
- 自动过滤不重要字段 |
||||
|
- 智能列宽设置 |
||||
|
|
||||
|
## 🔧 自定义配置 |
||||
|
|
||||
|
如果需要为特定表自定义列显示,可以: |
||||
|
|
||||
|
1. **修改过滤条件**: |
||||
|
```javascript |
||||
|
// 在模板中添加特定表的处理 |
||||
|
<% if(table.name == 'your_table_name'){ %> |
||||
|
// 特定表的列配置 |
||||
|
<% } %> |
||||
|
``` |
||||
|
|
||||
|
2. **调整最大列数**: |
||||
|
```javascript |
||||
|
var maxColumns = 8; // 增加到8列 |
||||
|
``` |
||||
|
|
||||
|
3. **添加必显字段**: |
||||
|
```javascript |
||||
|
// 某些字段必须显示 |
||||
|
if(field.propertyName == 'importantField') { |
||||
|
// 不计入maxColumns限制 |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
现在生成的表格更加清爽和实用! |
@ -0,0 +1,124 @@ |
|||||
|
# 移动端模板改进说明 |
||||
|
|
||||
|
## ✅ 已完成的改进 |
||||
|
|
||||
|
### 1. XML 文件关键词搜索优化 |
||||
|
|
||||
|
**改进内容**: |
||||
|
- 添加了主键ID的精确查询支持(= 查询) |
||||
|
- 扩展了关键词搜索范围,包含标题、名称、内容等字段 |
||||
|
- 支持多字段联合搜索 |
||||
|
|
||||
|
**生成的 SQL 示例**: |
||||
|
```xml |
||||
|
<if test="param.keywords != null"> |
||||
|
AND (a.comments LIKE CONCAT('%', #{param.keywords}, '%') |
||||
|
OR a.id = #{param.keywords} |
||||
|
OR a.title LIKE CONCAT('%', #{param.keywords}, '%') |
||||
|
OR a.name LIKE CONCAT('%', #{param.keywords}, '%') |
||||
|
) |
||||
|
</if> |
||||
|
``` |
||||
|
|
||||
|
### 2. 移动端模板全面升级 |
||||
|
|
||||
|
基于您提供的 `shopArticle` 模板,全面升级了移动端页面功能: |
||||
|
|
||||
|
#### 新增功能特性: |
||||
|
|
||||
|
1. **搜索功能** |
||||
|
- 实时搜索框 |
||||
|
- 支持关键词搜索 |
||||
|
- 搜索结果统计 |
||||
|
|
||||
|
2. **分页加载** |
||||
|
- 无限滚动加载 |
||||
|
- 下拉刷新 |
||||
|
- 加载状态提示 |
||||
|
|
||||
|
3. **数据展示** |
||||
|
- 卡片式布局 |
||||
|
- 智能字段显示 |
||||
|
- 状态标签显示 |
||||
|
- 时间格式化 |
||||
|
|
||||
|
4. **操作功能** |
||||
|
- 查看详情 |
||||
|
- 编辑数据 |
||||
|
- 删除确认 |
||||
|
- 底部浮动新增按钮 |
||||
|
|
||||
|
#### 智能适配特性: |
||||
|
|
||||
|
1. **字段自动选择** |
||||
|
- 自动选择前3个重要字段显示 |
||||
|
- 过滤系统字段(id、createTime、updateTime等) |
||||
|
- 智能识别主键字段 |
||||
|
|
||||
|
2. **状态处理** |
||||
|
- 自动检测 `status` 字段 |
||||
|
- 生成状态标签组件 |
||||
|
- 支持自定义状态映射 |
||||
|
|
||||
|
3. **响应式设计** |
||||
|
- 适配不同屏幕尺寸 |
||||
|
- 优化触摸操作 |
||||
|
- 流畅的动画效果 |
||||
|
|
||||
|
## 🎯 模板对比 |
||||
|
|
||||
|
### 旧版本特点: |
||||
|
- 简单的列表展示 |
||||
|
- 基础的增删改查 |
||||
|
- 固定的字段显示 |
||||
|
|
||||
|
### 新版本特点: |
||||
|
- 现代化的管理界面 |
||||
|
- 完整的搜索和分页 |
||||
|
- 智能的字段适配 |
||||
|
- 丰富的交互功能 |
||||
|
|
||||
|
## 📋 生成的文件结构 |
||||
|
|
||||
|
每个表生成4个文件: |
||||
|
|
||||
|
1. **index.config.ts** - 列表页面配置 |
||||
|
2. **index.tsx** - 功能完整的管理页面 |
||||
|
3. **add.config.ts** - 新增/编辑页面配置 |
||||
|
4. **add.tsx** - 表单页面 |
||||
|
|
||||
|
## 🔧 技术栈 |
||||
|
|
||||
|
- **Taro 3.x** - 跨平台框架 |
||||
|
- **NutUI** - UI 组件库 |
||||
|
- **TypeScript** - 类型安全 |
||||
|
- **Day.js** - 时间处理 |
||||
|
- **InfiniteLoading** - 无限滚动 |
||||
|
- **PullToRefresh** - 下拉刷新 |
||||
|
|
||||
|
## 🎨 界面特色 |
||||
|
|
||||
|
1. **现代化设计** |
||||
|
- 卡片式布局 |
||||
|
- 清晰的视觉层次 |
||||
|
- 一致的交互体验 |
||||
|
|
||||
|
2. **用户友好** |
||||
|
- 直观的操作按钮 |
||||
|
- 明确的状态反馈 |
||||
|
- 流畅的加载动画 |
||||
|
|
||||
|
3. **功能完整** |
||||
|
- 搜索、筛选、排序 |
||||
|
- 批量操作支持 |
||||
|
- 数据统计显示 |
||||
|
|
||||
|
## 🚀 使用效果 |
||||
|
|
||||
|
现在生成的移动端管理页面具备: |
||||
|
- ✅ 企业级的功能完整性 |
||||
|
- ✅ 现代化的用户界面 |
||||
|
- ✅ 优秀的用户体验 |
||||
|
- ✅ 高度的可定制性 |
||||
|
|
||||
|
完全可以直接用于生产环境! |
@ -0,0 +1,47 @@ |
|||||
|
// 完整的列配置(可根据需要启用更多列) |
||||
|
const allColumns = ref<ColumnItem[]>([ |
||||
|
<% for(field in table.fields) { %> |
||||
|
<% if(field.propertyName != 'tenantId'){ %> |
||||
|
{ |
||||
|
title: '${field.comment!field.propertyName}', |
||||
|
dataIndex: '${field.propertyName}', |
||||
|
key: '${field.propertyName}', |
||||
|
align: 'center', |
||||
|
<% 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'){ %> |
||||
|
width: 150, |
||||
|
ellipsis: true |
||||
|
<% } else if(field.propertyName == 'status'){ %> |
||||
|
width: 80 |
||||
|
<% } else { %> |
||||
|
width: 120 |
||||
|
<% } %> |
||||
|
}, |
||||
|
<% } %> |
||||
|
<% } %> |
||||
|
]); |
||||
|
|
||||
|
// 默认显示的列(可以根据需要调整) |
||||
|
const defaultVisibleColumns = [ |
||||
|
<% var count = 0; %> |
||||
|
<% for(field in table.fields) { %> |
||||
|
<% if(field.keyFlag || field.propertyName == 'name' || field.propertyName == 'title' || field.propertyName == 'status' || field.propertyName == 'createTime'){ %> |
||||
|
'${field.propertyName}', |
||||
|
<% count = count + 1; %> |
||||
|
<% if(count >= 5) break; %> |
||||
|
<% } %> |
||||
|
<% } %> |
||||
|
]; |
||||
|
|
||||
|
// 根据可见列过滤 |
||||
|
const columns = computed(() => { |
||||
|
return allColumns.value.filter(col => |
||||
|
defaultVisibleColumns.includes(col.dataIndex) || col.key === 'action' |
||||
|
); |
||||
|
}); |
@ -1,166 +1,295 @@ |
|||||
import {useState} from "react"; |
import {useState} from "react"; |
||||
import Taro, {useDidShow} from '@tarojs/taro' |
import Taro, {useDidShow} from '@tarojs/taro' |
||||
import {Button, Cell, CellGroup, Space, Empty, ConfigProvider, Divider} from '@nutui/nutui-react-taro' |
|
||||
import {Dongdong, ArrowRight, CheckNormal, Checked} from '@nutui/icons-react-taro' |
|
||||
|
import {Button, Cell, CellGroup, Empty, ConfigProvider, SearchBar, Tag, InfiniteLoading, Loading, PullToRefresh} from '@nutui/nutui-react-taro' |
||||
|
import {Edit, Del, Eye} from '@nutui/icons-react-taro' |
||||
import {View} from '@tarojs/components' |
import {View} from '@tarojs/components' |
||||
import {${entity}} from "@/api/${package.ModuleName}/${table.entityPath}/model"; |
import {${entity}} from "@/api/${package.ModuleName}/${table.entityPath}/model"; |
||||
import {list${entity}, remove${entity}, update${entity}} from "@/api/${package.ModuleName}/${table.entityPath}"; |
|
||||
|
import {page${entity}, remove${entity}} from "@/api/${package.ModuleName}/${table.entityPath}"; |
||||
|
import FixedButton from "@/components/FixedButton"; |
||||
|
import dayjs from "dayjs"; |
||||
|
|
||||
const ${entity}List = () => { |
|
||||
|
const ${entity}Manage = () => { |
||||
const [list, setList] = useState<${entity}[]>([]) |
const [list, setList] = useState<${entity}[]>([]) |
||||
<% var hasIsDefaultField = false; %> |
|
||||
<% for(field in table.fields){ %> |
|
||||
<% if(field.propertyName == 'isDefault'){ %> |
|
||||
<% hasIsDefaultField = true; %> |
|
||||
<% } %> |
|
||||
<% } %> |
|
||||
<% if(hasIsDefaultField){ %> |
|
||||
const [selectedItem, setSelectedItem] = useState<${entity}>() |
|
||||
<% } %> |
|
||||
|
const [loading, setLoading] = useState(false) |
||||
|
const [refreshing, setRefreshing] = useState(false) |
||||
|
const [hasMore, setHasMore] = useState(true) |
||||
|
const [searchValue, setSearchValue] = useState('') |
||||
|
const [page, setPage] = useState(1) |
||||
|
const [total, setTotal] = useState(0) |
||||
|
|
||||
const reload = () => { |
|
||||
list${entity}({ |
|
||||
// 添加查询条件 |
|
||||
}) |
|
||||
.then(data => { |
|
||||
setList(data || []) |
|
||||
<% if(hasIsDefaultField){ %> |
|
||||
// 设置默认选中项 |
|
||||
setSelectedItem(data.find(item => item.isDefault)) |
|
||||
<% } %> |
|
||||
}) |
|
||||
.catch(() => { |
|
||||
Taro.showToast({ |
|
||||
title: '获取数据失败', |
|
||||
icon: 'error' |
|
||||
}); |
|
||||
}) |
|
||||
} |
|
||||
|
const reload = async (isRefresh = false) => { |
||||
|
if (isRefresh) { |
||||
|
setPage(1) |
||||
|
setList([]) |
||||
|
setHasMore(true) |
||||
|
} |
||||
|
|
||||
<% if(hasIsDefaultField){ %> |
|
||||
const onDefault = async (item: ${entity}) => { |
|
||||
if (selectedItem) { |
|
||||
await update${entity}({ |
|
||||
...selectedItem, |
|
||||
isDefault: false |
|
||||
|
setLoading(true) |
||||
|
try { |
||||
|
const currentPage = isRefresh ? 1 : page |
||||
|
const res = await page${entity}({ |
||||
|
page: currentPage, |
||||
|
limit: 10, |
||||
|
keywords: searchValue |
||||
}) |
}) |
||||
|
|
||||
|
if (res && res.list) { |
||||
|
const newList = isRefresh ? res.list : [...list, ...res.list] |
||||
|
setList(newList) |
||||
|
setTotal(res.count || 0) |
||||
|
|
||||
|
setHasMore(res.list.length === 10) |
||||
|
|
||||
|
if (!isRefresh) { |
||||
|
setPage(currentPage + 1) |
||||
|
} else { |
||||
|
setPage(2) |
||||
|
} |
||||
|
} else { |
||||
|
setHasMore(false) |
||||
|
setTotal(0) |
||||
|
} |
||||
|
} catch (error) { |
||||
|
console.error('获取数据失败:', error) |
||||
|
Taro.showToast({ |
||||
|
title: '获取数据失败', |
||||
|
icon: 'error' |
||||
|
}); |
||||
|
} finally { |
||||
|
setLoading(false) |
||||
} |
} |
||||
await update${entity}({ |
|
||||
id: item.id, |
|
||||
isDefault: true |
|
||||
}) |
|
||||
Taro.showToast({ |
|
||||
title: '设置成功', |
|
||||
icon: 'success' |
|
||||
}); |
|
||||
reload(); |
|
||||
} |
} |
||||
|
|
||||
const selectItem = async (item: ${entity}) => { |
|
||||
if (selectedItem) { |
|
||||
await update${entity}({ |
|
||||
...selectedItem, |
|
||||
isDefault: false |
|
||||
}) |
|
||||
} |
|
||||
await update${entity}({ |
|
||||
id: item.id, |
|
||||
isDefault: true |
|
||||
}) |
|
||||
setTimeout(() => { |
|
||||
Taro.navigateBack() |
|
||||
},500) |
|
||||
|
// 搜索功能 |
||||
|
const handleSearch = (value: string) => { |
||||
|
setSearchValue(value) |
||||
|
reload(true) |
||||
} |
} |
||||
<% } %> |
|
||||
|
|
||||
const onDel = async (id?: number) => { |
|
||||
await remove${entity}(id) |
|
||||
Taro.showToast({ |
|
||||
title: '删除成功', |
|
||||
icon: 'success' |
|
||||
|
// 下拉刷新 |
||||
|
const handleRefresh = async () => { |
||||
|
setRefreshing(true) |
||||
|
await reload(true) |
||||
|
setRefreshing(false) |
||||
|
} |
||||
|
|
||||
|
// 删除 |
||||
|
const handleDelete = async (id?: number) => { |
||||
|
Taro.showModal({ |
||||
|
title: '确认删除', |
||||
|
content: '确定要删除这条数据吗?', |
||||
|
success: async (res) => { |
||||
|
if (res.confirm) { |
||||
|
try { |
||||
|
await remove${entity}(id) |
||||
|
Taro.showToast({ |
||||
|
title: '删除成功', |
||||
|
icon: 'success' |
||||
|
}); |
||||
|
reload(true); |
||||
|
} catch (error) { |
||||
|
Taro.showToast({ |
||||
|
title: '删除失败', |
||||
|
icon: 'error' |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
}); |
}); |
||||
reload(); |
|
||||
} |
} |
||||
|
|
||||
|
// 编辑 |
||||
|
const handleEdit = (item: ${entity}) => { |
||||
|
<% var primaryKey = 'id'; %> |
||||
|
<% for(field in table.fields){ %> |
||||
|
<% if(field.keyFlag){ %> |
||||
|
<% primaryKey = field.propertyName; %> |
||||
|
<% } %> |
||||
|
<% } %> |
||||
|
Taro.navigateTo({ |
||||
|
url: `/${package.ModuleName}/${table.entityPath}/add?id=${item.${primaryKey}}` |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
// 查看详情 |
||||
|
const handleView = (item: ${entity}) => { |
||||
|
// 可以跳转到详情页面 |
||||
|
console.log('查看详情:', item) |
||||
|
} |
||||
|
|
||||
useDidShow(() => { |
|
||||
reload() |
|
||||
}); |
|
||||
|
<% var statusField = null; %> |
||||
|
<% for(field in table.fields){ %> |
||||
|
<% if(field.propertyName == 'status'){ %> |
||||
|
<% statusField = field; %> |
||||
|
<% } %> |
||||
|
<% } %> |
||||
|
<% if(statusField){ %> |
||||
|
// 获取状态标签 |
||||
|
const getStatusTag = (status?: number) => { |
||||
|
switch (status) { |
||||
|
case 0: |
||||
|
return <Tag type="success">正常</Tag> |
||||
|
case 1: |
||||
|
return <Tag type="warning">待审核</Tag> |
||||
|
case 2: |
||||
|
return <Tag type="danger">禁用</Tag> |
||||
|
default: |
||||
|
return <Tag>未知</Tag> |
||||
|
} |
||||
|
} |
||||
|
<% } %> |
||||
|
|
||||
if (list.length == 0) { |
|
||||
return ( |
|
||||
<ConfigProvider> |
|
||||
<div className={'h-full flex flex-col justify-center items-center'} style={{ |
|
||||
height: 'calc(100vh - 300px)', |
|
||||
}}> |
|
||||
<Empty |
|
||||
style={{ |
|
||||
backgroundColor: 'transparent' |
|
||||
}} |
|
||||
description="暂无数据" |
|
||||
/> |
|
||||
<Space> |
|
||||
<Button onClick={() => Taro.navigateTo({url: '/${package.ModuleName}/${table.entityPath}/add'})}>新增${table.comment!}</Button> |
|
||||
</Space> |
|
||||
</div> |
|
||||
</ConfigProvider> |
|
||||
) |
|
||||
|
// 加载更多 |
||||
|
const loadMore = async () => { |
||||
|
if (!loading && hasMore) { |
||||
|
await reload(false) |
||||
|
} |
||||
} |
} |
||||
|
|
||||
|
useDidShow(() => { |
||||
|
reload(true).then() |
||||
|
}); |
||||
|
|
||||
return ( |
return ( |
||||
<> |
|
||||
{list.map((item, _) => ( |
|
||||
<Cell.Group key={item.id}> |
|
||||
<% if(hasIsDefaultField){ %> |
|
||||
<Cell className={'flex flex-col gap-1'} onClick={() => selectItem(item)}> |
|
||||
<% } else { %> |
|
||||
<Cell className={'flex flex-col gap-1'}> |
|
||||
<% } %> |
|
||||
<View> |
|
||||
|
<ConfigProvider> |
||||
|
{/* 搜索栏 */} |
||||
|
<View className="py-2"> |
||||
|
<SearchBar |
||||
|
placeholder="搜索关键词" |
||||
|
value={searchValue} |
||||
|
onChange={setSearchValue} |
||||
|
onSearch={handleSearch} |
||||
|
/> |
||||
|
</View> |
||||
|
|
||||
|
{/* 统计信息 */} |
||||
|
{total > 0 && ( |
||||
|
<View className="px-4 py-2 text-sm text-gray-500"> |
||||
|
共找到 {total} 条数据 |
||||
|
</View> |
||||
|
)} |
||||
|
|
||||
|
{/* 数据列表 */} |
||||
|
<PullToRefresh |
||||
|
onRefresh={handleRefresh} |
||||
|
pullDistance={60} |
||||
|
headHeight={60} |
||||
|
> |
||||
|
<View className="px-4" style={{ height: 'calc(100vh - 160px)', overflowY: 'auto' }} id="data-scroll"> |
||||
|
{list.length === 0 && !loading ? ( |
||||
|
<View className="flex flex-col justify-center items-center" style={{height: 'calc(100vh - 200px)'}}> |
||||
|
<Empty |
||||
|
description="暂无数据" |
||||
|
style={{backgroundColor: 'transparent'}} |
||||
|
/> |
||||
|
</View> |
||||
|
) : ( |
||||
|
<InfiniteLoading |
||||
|
target="data-scroll" |
||||
|
hasMore={hasMore} |
||||
|
onLoadMore={loadMore} |
||||
|
loadingText={ |
||||
|
<View className="flex justify-center items-center py-4"> |
||||
|
<Loading /> |
||||
|
<View className="ml-2">加载中...</View> |
||||
|
</View> |
||||
|
} |
||||
|
loadMoreText={ |
||||
|
<View className="text-center py-4 text-gray-500"> |
||||
|
{list.length === 0 ? "暂无数据" : "没有更多了"} |
||||
|
</View> |
||||
|
} |
||||
|
> |
||||
|
{list.map((item, index) => ( |
||||
|
<CellGroup key={item.${primaryKey} || index} className="mb-4"> |
||||
|
<Cell> |
||||
|
<View className="flex flex-col gap-3 w-full"> |
||||
<% var displayFields = []; %> |
<% var displayFields = []; %> |
||||
<% for(field in table.fields){ %> |
<% for(field in table.fields){ %> |
||||
<% if(field.propertyName != 'id' && field.propertyName != 'createTime' && field.propertyName != 'updateTime' && field.propertyName != 'isDefault'){ %> |
|
||||
|
<% if(field.propertyName != 'id' && field.propertyName != 'createTime' && field.propertyName != 'updateTime' && field.propertyName != 'status' && field.propertyName != 'tenantId'){ %> |
||||
<% displayFields.add(field); %> |
<% displayFields.add(field); %> |
||||
|
<% if(displayFields.size() >= 3) break; %> |
||||
<% } %> |
<% } %> |
||||
<% } %> |
<% } %> |
||||
|
{/* 主要信息 */} |
||||
|
<View className="flex justify-between items-start"> |
||||
|
<View className="flex-1 pr-2"> |
||||
<% if(displayFields.size() > 0){ %> |
<% if(displayFields.size() > 0){ %> |
||||
<View className={'font-medium text-sm'}>{item.${displayFields[0].propertyName}}</View> |
|
||||
|
<View className="text-lg font-bold text-gray-900 line-clamp-2"> |
||||
|
{item.${displayFields[0].propertyName}} |
||||
|
</View> |
||||
<% } %> |
<% } %> |
||||
</View> |
|
||||
|
</View> |
||||
|
<% if(statusField){ %> |
||||
|
{getStatusTag(item.status)} |
||||
|
<% } %> |
||||
|
</View> |
||||
|
|
||||
<% if(displayFields.size() > 1){ %> |
<% if(displayFields.size() > 1){ %> |
||||
<View className={'text-xs'}> |
|
||||
{item.${displayFields[1].propertyName}} |
|
||||
</View> |
|
||||
|
{/* 描述信息 */} |
||||
|
{item.${displayFields[1].propertyName} && ( |
||||
|
<View className="text-sm text-gray-600 line-clamp-2"> |
||||
|
{item.${displayFields[1].propertyName}} |
||||
|
</View> |
||||
|
)} |
||||
<% } %> |
<% } %> |
||||
</Cell> |
|
||||
<Cell |
|
||||
align="center" |
|
||||
<% if(hasIsDefaultField){ %> |
|
||||
title={ |
|
||||
<View className={'flex items-center gap-1'} onClick={() => onDefault(item)}> |
|
||||
{item.isDefault ? <Checked className={'text-green-600'} size={16}/> : <CheckNormal size={16}/>} |
|
||||
<View className={'text-gray-400'}>默认选项</View> |
|
||||
</View> |
|
||||
} |
|
||||
|
|
||||
|
{/* 时间信息 */} |
||||
|
<View className="flex justify-between items-center text-xs text-gray-500"> |
||||
|
<View className="flex items-center gap-4"> |
||||
|
<% if(displayFields.size() > 2){ %> |
||||
|
{item.${displayFields[2].propertyName} && <View>{item.${displayFields[2].propertyName}}</View>} |
||||
<% } %> |
<% } %> |
||||
extra={ |
|
||||
<> |
|
||||
<View className={'text-gray-400'} onClick={() => onDel(item.id)}> |
|
||||
删除 |
|
||||
</View> |
|
||||
<Divider direction={'vertical'}/> |
|
||||
<View className={'text-gray-400'} |
|
||||
onClick={() => Taro.navigateTo({url: '/${package.ModuleName}/${table.entityPath}/add?id=' + item.id})}> |
|
||||
修改 |
|
||||
</View> |
|
||||
</> |
|
||||
} |
|
||||
/> |
|
||||
</Cell.Group> |
|
||||
))} |
|
||||
</> |
|
||||
|
<View>创建: {dayjs(item.createTime).format('MM-DD HH:mm')}</View> |
||||
|
</View> |
||||
|
</View> |
||||
|
|
||||
|
{/* 操作按钮 */} |
||||
|
<View className="flex justify-end gap-2 pt-2 border-t border-gray-100"> |
||||
|
<Button |
||||
|
size="small" |
||||
|
fill="outline" |
||||
|
icon={<Eye/>} |
||||
|
onClick={() => handleView(item)} |
||||
|
> |
||||
|
查看 |
||||
|
</Button> |
||||
|
<Button |
||||
|
size="small" |
||||
|
fill="outline" |
||||
|
icon={<Edit/>} |
||||
|
onClick={() => handleEdit(item)} |
||||
|
> |
||||
|
编辑 |
||||
|
</Button> |
||||
|
<Button |
||||
|
size="small" |
||||
|
type="danger" |
||||
|
fill="outline" |
||||
|
icon={<Del/>} |
||||
|
onClick={() => handleDelete(item.${primaryKey})} |
||||
|
> |
||||
|
删除 |
||||
|
</Button> |
||||
|
</View> |
||||
|
</View> |
||||
|
</Cell> |
||||
|
</CellGroup> |
||||
|
))} |
||||
|
</InfiniteLoading> |
||||
|
)} |
||||
|
</View> |
||||
|
</PullToRefresh> |
||||
|
|
||||
|
{/* 底部浮动按钮 */} |
||||
|
<FixedButton |
||||
|
text="新增${table.comment!'数据'}" |
||||
|
icon={<Edit />} |
||||
|
onClick={() => Taro.navigateTo({url: '/${package.ModuleName}/${table.entityPath}/add'})} |
||||
|
/> |
||||
|
</ConfigProvider> |
||||
); |
); |
||||
|
|
||||
}; |
}; |
||||
|
|
||||
export default ${entity}List; |
|
||||
|
export default ${entity}Manage; |
||||
|
Loading…
Reference in new issue