From 3fdea8b85b1078f04609f01e1c73693fccd5a29e Mon Sep 17 00:00:00 2001 From: augushong Date: Mon, 5 Jan 2026 22:59:12 +0800 Subject: [PATCH 1/4] =?UTF-8?q?feat:=20=E5=AE=9E=E7=8E=B0=E5=9F=BA?= =?UTF-8?q?=E6=9C=AC=E7=9A=84=E8=AF=A6=E6=83=85=E7=94=9F=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .trae/documents/添加CURD详情页面生成功能.md | 134 ++++++++++++ .trae/rules/project_rules.md | 168 +++++++++++++++ app/admin/controller/test/Goods.php | 104 +++++++++ app/admin/model/TestGoods.php | 60 ++++++ app/admin/view/test/goods/_common.js | 10 + app/admin/view/test/goods/add.html | 200 ++++++++++++++++++ app/admin/view/test/goods/add.js | 3 + app/admin/view/test/goods/edit.html | 200 ++++++++++++++++++ app/admin/view/test/goods/edit.js | 3 + app/admin/view/test/goods/index.html | 13 ++ app/admin/view/test/goods/index.js | 11 + app/admin/view/test/goods/read.html | 40 ++++ app/admin/view/test/goods/read.js | 22 ++ .../service/curd/BuildCurdServiceBase.php | 130 +++++++++++- .../admin/service/curd/templates/js/read.code | 22 ++ .../service/curd/templates/view/read.code | 40 ++++ extend/base/admin/traits/CurdTraitBase.php | 17 ++ public/static/admin/css/public.css | 124 +++++++++++ public/static/admin/css/public.scss | 123 +++++++++++ public/static/common/css/theme/index.css | 21 +- 20 files changed, 1430 insertions(+), 15 deletions(-) create mode 100644 .trae/documents/添加CURD详情页面生成功能.md create mode 100644 .trae/rules/project_rules.md create mode 100644 app/admin/controller/test/Goods.php create mode 100644 app/admin/model/TestGoods.php create mode 100644 app/admin/view/test/goods/_common.js create mode 100644 app/admin/view/test/goods/add.html create mode 100644 app/admin/view/test/goods/add.js create mode 100644 app/admin/view/test/goods/edit.html create mode 100644 app/admin/view/test/goods/edit.js create mode 100644 app/admin/view/test/goods/index.html create mode 100644 app/admin/view/test/goods/index.js create mode 100644 app/admin/view/test/goods/read.html create mode 100644 app/admin/view/test/goods/read.js create mode 100644 extend/base/admin/service/curd/templates/js/read.code create mode 100644 extend/base/admin/service/curd/templates/view/read.code diff --git a/.trae/documents/添加CURD详情页面生成功能.md b/.trae/documents/添加CURD详情页面生成功能.md new file mode 100644 index 0000000..2d1b084 --- /dev/null +++ b/.trae/documents/添加CURD详情页面生成功能.md @@ -0,0 +1,134 @@ +# CURD详情页面生成功能实现计划 + +## 1. 需求分析 + +* 当前CURD生成功能不包含详情页面 + +* 详情页面需要合理布局:顶部是标题+ID,左侧8/12是主体,右侧4/12是基础字段 + +* 详情页面需要包含编辑、删除、返回等基础按钮操作 + +* 支持后续扩展更多字段 + +* 使用Layui栅格系统 + +## 2. 实现步骤 + +### 2.1 添加详情方法到CURD Trait + +* 在 `CurdTraitBase.php` 中添加 `read` 方法 + +* 实现详情数据获取和页面渲染逻辑 + +### 2.2 创建详情页面模板 + +* 创建 `view/read.code` 主模板 + +* 设计Layui风格布局: + * 顶部区域:标题、ID和操作按钮(编辑、删除、返回) + * 内容区域:使用 `layui-row` 和 `layui-col-md-*` 实现8/4分栏 + * 左侧:主体字段(8列) + * 右侧:基础字段(4列,包含创建时间、更新时间等) + +### 2.3 修改BuildCurdServiceBase + +* 在 `renderView` 方法中添加详情页面生成逻辑 + +* 实现字段分类: + * 主体字段:除ID、创建时间、更新时间外的大部分字段 + * 基础字段:ID、创建时间、更新时间、状态等系统字段 + +* 添加详情页面到文件列表 + +### 2.4 更新JS文件生成 + +* 修改 `js/index.code` 模板 + +* 在操作列添加详情按钮 + +* 实现详情跳转逻辑 + +### 2.5 更新控制器模板 + +* 确保控制器支持详情页面路由 + +## 3. 布局设计(Layui风格) + +```html + +
+
+
+
+

{{title}}

+
ID: {{id}}
+
+
+ + + +
+
+
+ + +
+
+ +
+
+ +
+
+ + +
+
+ +
+
+
+
+
+``` + +## 4. 字段分类规则 + +* **主体字段**:所有非系统字段,如名称、描述、内容等 + +* **基础字段**: + * id + * create_time + * update_time + * status + * 其他系统相关字段 + +## 5. 实现要点 + +* 保持与Layui框架风格一致 + +* 遵循现有代码生成模式 + +* 支持后续字段扩展 + +* 确保详情页面与现有功能无缝集成 + +* 添加必要的JavaScript交互逻辑 + +## 6. 文件修改清单 + +1. `extend/base/admin/traits/CurdTraitBase.php` - 添加read方法 +2. `extend/base/admin/service/curd/templates/view/read.code` - 详情页面模板 +3. `extend/base/admin/service/curd/BuildCurdServiceBase.php` - 添加详情页面生成逻辑 +4. `extend/base/admin/service/curd/templates/js/index.code` - 添加详情按钮 +5. `extend/base/admin/service/curd/templates/js/read.code` - 详情页面JS逻辑 + +## 7. 详情页面按钮功能 + +* **返回**:返回上一页 + +* **编辑**:跳转到编辑页面 + +* **删除**:调用删除接口,删除当前数据 + +* 所有按钮使用Layui样式,保持一致的视觉效果 \ No newline at end of file diff --git a/.trae/rules/project_rules.md b/.trae/rules/project_rules.md new file mode 100644 index 0000000..b99f679 --- /dev/null +++ b/.trae/rules/project_rules.md @@ -0,0 +1,168 @@ +# Ulthon Admin 项目开发规则 + +## 1. 框架技术栈 + +- **核心框架**: ThinkPHP 8.0 +- **开发语言**: PHP 8+ +- **数据库**: MySQL 8+ +- **前端框架**: Layui 2.8.6 +- **模板引擎**: ThinkPHP 内置模板引擎 +- **代码生成器**: 自定义命令行工具 + +## 2. 项目架构设计 + +### 2.1 双层架构设计 + +Uthon Admin 采用独特的双层架构设计,将系统功能分为核心基础层和业务应用层,便于开发者进行二次开发和功能扩展: + +- **基础核心层 (`extend/base/`)**: + - 包含系统内置的所有核心功能代码 + - 提供标准化的类和方法接口 + - 不可直接修改,确保系统稳定性 + - 示例:`extend/base/controller/Base.php`、`extend/base/model/BaseModel.php` + +- **业务应用层 (`application/`)**: + - 基于基础核心层扩展开发的具体业务代码 + - 所有业务类必须继承基础核心层的对应类 + - 开发者可自由修改和扩展,不会影响核心功能 + - 示例:`application/admin/controller/User.php` 继承 `base\controller\Base` + +### 2.2 继承重写机制 + +**注意**:继承重写机制主要针对 ulthon-admin 自身的内置功能(如管理员管理、菜单、权限等),用于扩展或修改框架内置功能。 + +- 对于 ulthon-admin 内置功能,通过继承基础核心类(位于 `extend/base/`),可以获得内置功能并进行扩展 +- 需要修改内置功能时,在业务类中重写对应方法,保持方法签名一致 +- 支持调用父类方法:`parent::methodName()` + +**用户自定义代码**: +- 用户自己的业务代码不需要遵守该继承规则 +- 生成的代码直接位于 `application/` 目录下 +- 可以直接在 `application/` 目录下进行开发和修改 + +## 3. 开发流程 + +### 3.1 标准开发步骤 + +1. **设计数据库表结构** + - 按照业务需求设计合理的表结构 + - 必须为所有字段编写清晰、完整的注释 + - 遵循命名规范:表名小写,使用下划线分隔 + +2. **生成基础代码** + - 使用内置命令行工具生成代码 + - 支持生成到临时目录,避免覆盖已定制代码 + - 生成内容包括:控制器、模型、视图、验证器、菜单配置 + +3. **代码定制** + - 基于生成的代码进行业务定制 + - 仅修改 `application/` 目录下的文件 + - 使用继承重写机制扩展基础功能 + +4. **测试与验证** + - 测试所有功能是否正常工作 + - 确保数据完整性和安全性 + - 检查代码规范和性能 + +### 3.2 代码生成命令 + +CURD命令大全 + +ulthon_admin框架以内置快速生成CURD的命令, 包括控制器、视图、模型、JS文件。能够使开发者效率得到进一步提升。 + +> 备注:在进行CURD命令行之前, 请按照规范设计表结构, 请参考表结构规范模块说明。 + +**常用命令** +``` +# 生成ul_test_goods表的CURD +php think curd -t test_goods + +# 生成ul_test_goods表的CURD到临时目录 +php think curd -t test_goods -r + +# 生成ul_test_goods表的CURD, 文件冲突时强制覆盖 +php think curd -t test_goods -f + +# 删除ul_test_goods表的CURD +php think curd -t test_goods -d + +# 生成ul_test_goods表的CURD, 控制器在目录demo下的Goods.php文件 +# 原路径: `controller\text\Goods.php`, +# 此时路径:`controller\demo\Goods.php` +# 不建议指定该参数 +php think curd -t test_goods -c demo/Goods + +# 生成ul_test_goods表的CURD, 模型在目录demo下的Goods.php文件 +# 原路径: `model\MallCate.php` +# 此时路径: `model\demo\Goods.php` +# 不建议指定该参数 +php think curd -t test_goods -m demo/Goods +``` + +**参数介绍** + +| 短参 | 长参 |说明| +| ------------ | ------------ | ------| +| -t | `--table=VALUE` | 主表名 | +| -c | `--controllerFilename=VALUE` | 控制器文件名 | +|-m| `--modelFilename=VALUE` |主表模型文件名| +|-f| `--force`|强制覆盖模式 | +|-d| `--delete`|删除模式 | +|-r |`--runtime`|生成到临时目录| + +**官方命令行文档**: [https://doc.ulthon.com/read/augushong/ulthon_admin/619efc929565f/zh-cn/2.x.html](https://doc.ulthon.com/read/augushong/ulthon_admin/619efc929565f/zh-cn/2.x.html) + +**CURD 文档地址**: [https://doc.ulthon.com/read/augushong/ulthon_admin/619efc816472e/zh-cn/2.x.html](https://doc.ulthon.com/read/augushong/ulthon_admin/619efc816472e/zh-cn/2.x.html) + +### 3.3 表结构设计规范 + +**官方表结构规范文档**: [https://doc.ulthon.com/read/augushong/ulthon_admin/619efc9d7af62/zh-cn/2.x.html](https://doc.ulthon.com/read/augushong/ulthon_admin/619efc9d7af62/zh-cn/2.x.html) + +> 以官方在线文档为准,包含详细的表结构设计规范,包括表名规则、特殊字段、数据类型定义等。 + +## 4. 命名规范 + +**官方命名规范文档**: [https://doc.ulthon.com/read/augushong/ulthon_admin/64fbcf8830640/zh-cn/2.x.html](https://doc.ulthon.com/read/augushong/ulthon_admin/64fbcf8830640/zh-cn/2.x.html) + +> 以官方在线文档为准,包含详细的命名规范说明。 + +## 5. 代码规范 + +**官方代码规范文档**: [https://doc.ulthon.com/read/augushong/ulthon_admin/64360c249d66a/zh-cn/2.x.html](https://doc.ulthon.com/read/augushong/ulthon_admin/64360c249d66a/zh-cn/2.x.html) + +> 以官方在线文档为准,包含 PHP-CS-Fixer 配置和详细的代码规范说明。 + +### 5.1 前端文件组织规范 + +**视图与JS文件对应规则**:后台的所有视图,每个HTML文件都会搭配一个对应的JS文件,文件结构示例: + +``` +goods +├─ add.html +├─ add.js +├─ edit.html +├─ edit.js +├─ index.html +├─ index.js +├─ read.html +├─ read.js +└─ _common.js +``` + +- 每个功能页面的HTML和JS文件名保持一致 +- `_common.js` 用于存放该模块通用的JS代码 +- JS文件中应包含对应页面的业务逻辑、事件绑定等 +- 这种结构便于维护和扩展,确保前端代码的组织性 + +## 7. 二次开发注意事项 + +- 不要修改 `extend/base/` 目录下的任何文件 +- 所有业务逻辑都应放在 `application/` 目录下 +- 扩展功能时优先考虑继承重写机制 +- 保持代码结构清晰,便于维护 +- 定期备份代码和数据库 +- 遵循版本控制规范,提交信息清晰 + +--- + +以上规则是 Ulthon Admin 项目开发的基本规范,所有开发者必须严格遵守。遵循这些规则可以提高代码质量,减少开发成本,便于系统维护和扩展。 \ No newline at end of file diff --git a/app/admin/controller/test/Goods.php b/app/admin/controller/test/Goods.php new file mode 100644 index 0000000..3601754 --- /dev/null +++ b/app/admin/controller/test/Goods.php @@ -0,0 +1,104 @@ +model = new \app\admin\model\TestGoods(); + + $this->assign('select_list_status', $this->model::SELECT_LIST_STATUS, true); + + $this->assign('select_list_time_status', $this->model::SELECT_LIST_TIME_STATUS, true); + + $this->assign('select_list_is_recommend', $this->model::SELECT_LIST_IS_RECOMMEND, true); + + $this->assign('select_list_shop_type', $this->model::SELECT_LIST_SHOP_TYPE, true); + + } + + + /** + * @NodeAnotation(title="列表") + */ + public function index() + { + if ($this->request->isAjax()) { + if (input('selectFields')) { + return $this->selectList(); + } + list($page, $limit, $where) = $this->buildTableParames(); + $count = $this->model + ->withJoin(['mallCate'], 'LEFT') + ->where($where) + ->count(); + $list = $this->model + ->withJoin(['mallCate'], 'LEFT') + ->where($where) + ->page($page, $limit) + ->order($this->sort) + ->select(); + $data = [ + 'code' => 0, + 'msg' => '', + 'count' => $count, + 'data' => $list, + ]; + return json($data); + } + return $this->fetch(); + } + + + + /** + * @NodeAnotation(title="导出") + */ + public function export() + { + list($page, $limit, $where) = $this->buildTableParames(); + + + $this->model = $this->model->withJoin(['mallCate'], 'LEFT'); + + $fields = $this->request->param('fields', '{}', null); + $image_fields = $this->request->param('image_fields', '{}', null); + $select_fields = $this->request->param('select_fields', '{}', null); + $date_fields = $this->request->param('date_fields', '{}', null); + + $fields = json_decode($fields, true); + $image_fields = json_decode($image_fields, true); + $select_fields = json_decode($select_fields, true); + $date_fields = json_decode($date_fields, true); + + $content = \app\common\tools\ExportTools::excel($this->model, $where, $fields, $image_fields, $select_fields, $date_fields); + + $export_file_name = $this->exportFileName; + + if (empty($export_file_name)) { + $export_file_name = $this->model->getName(); + } + + return download($content, $export_file_name . date('YmdHis') . '.xlsx', true); + } +} \ No newline at end of file diff --git a/app/admin/model/TestGoods.php b/app/admin/model/TestGoods.php new file mode 100644 index 0000000..0c12663 --- /dev/null +++ b/app/admin/model/TestGoods.php @@ -0,0 +1,60 @@ +'正常','1'=>'禁用',]; + + public const SELECT_LIST_TIME_STATUS = ['0'=>'未参加','1'=>'已开始','3'=>'已结束',]; + + public const SELECT_LIST_IS_RECOMMEND = ['0'=>'不推荐','1'=>'推荐',]; + + public const SELECT_LIST_SHOP_TYPE = ['taobao'=>'淘宝','jd'=>'京东',]; + + + + public function mallCate() + { + return $this->belongsTo('\app\admin\model\MallCate', 'cate_id', 'id'); + } + + +} \ No newline at end of file diff --git a/app/admin/view/test/goods/_common.js b/app/admin/view/test/goods/_common.js new file mode 100644 index 0000000..6e85503 --- /dev/null +++ b/app/admin/view/test/goods/_common.js @@ -0,0 +1,10 @@ +var init = { + tableElem: '#currentTable', + tableRenderId: 'currentTableRenderId', + indexUrl: 'test.goods/index', + addUrl: 'test.goods/add' + location.search, + editUrl: 'test.goods/edit', + deleteUrl: 'test.goods/delete', + exportUrl: 'test.goods/export', + modifyUrl: 'test.goods/modify', +}; \ No newline at end of file diff --git a/app/admin/view/test/goods/add.html b/app/admin/view/test/goods/add.html new file mode 100644 index 0000000..c034665 --- /dev/null +++ b/app/admin/view/test/goods/add.html @@ -0,0 +1,200 @@ +
+
+ +
+ +
+
+ +
+
+
+
+ +
+ +
+
+
+ +
+ + +
+
+
+ +
+ + +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ {foreach $select_list_status as $k=>$v} + + {/foreach} +
+
+ +
+ +
+ + +
+
+
+ +
+ + +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ {foreach $select_list_is_recommend as $k=>$v} + + {/foreach} +
+
+ +
+ +
+ {foreach $select_list_shop_type as $k=>$v} + + {/foreach} +
+
+ +
+ +
+
+ +
+
+
+
+ +
+
+ +
+
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+
+
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+
+ {notempty name='$Request.param.backTagId'} +
返回
+ {/notempty} + + +
+ +
+
\ No newline at end of file diff --git a/app/admin/view/test/goods/add.js b/app/admin/view/test/goods/add.js new file mode 100644 index 0000000..4a445e0 --- /dev/null +++ b/app/admin/view/test/goods/add.js @@ -0,0 +1,3 @@ +$(function(){ + ua.listen(); +}) \ No newline at end of file diff --git a/app/admin/view/test/goods/edit.html b/app/admin/view/test/goods/edit.html new file mode 100644 index 0000000..634c128 --- /dev/null +++ b/app/admin/view/test/goods/edit.html @@ -0,0 +1,200 @@ +
+
+ +
+ +
+
+ +
+
+
+
+ +
+ +
+
+
+ +
+ + +
+
+
+ +
+ + +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ {foreach $select_list_status as $k=>$v} + + {/foreach} +
+
+ +
+ +
+ + +
+
+
+ +
+ + +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ {foreach $select_list_is_recommend as $k=>$v} + + {/foreach} +
+
+ +
+ +
+ {foreach $select_list_shop_type as $k=>$v} + + {/foreach} +
+
+ +
+ +
+
+ +
+
+
+
+ +
+
+ +
+
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+
+
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+
+ {notempty name='$Request.param.backTagId'} +
返回
+ {/notempty} + + +
+ +
+
\ No newline at end of file diff --git a/app/admin/view/test/goods/edit.js b/app/admin/view/test/goods/edit.js new file mode 100644 index 0000000..4a445e0 --- /dev/null +++ b/app/admin/view/test/goods/edit.js @@ -0,0 +1,3 @@ +$(function(){ + ua.listen(); +}) \ No newline at end of file diff --git a/app/admin/view/test/goods/index.html b/app/admin/view/test/goods/index.html new file mode 100644 index 0000000..9e71a4f --- /dev/null +++ b/app/admin/view/test/goods/index.html @@ -0,0 +1,13 @@ +
+
+ +
+
+
\ No newline at end of file diff --git a/app/admin/view/test/goods/index.js b/app/admin/view/test/goods/index.js new file mode 100644 index 0000000..8c46dfe --- /dev/null +++ b/app/admin/view/test/goods/index.js @@ -0,0 +1,11 @@ +$(function(){ + ua.table.render({ + init: init, + cols: [[ + {type: 'checkbox'}, {field: 'id', title: 'id'}, {field: 'cate_id', title: '分类ID'}, {field: 'title', title: '商品名称'}, {field: 'logo', title: '商品logo', templet: ua.table.image}, {field: 'total_stock', title: '总库存'}, {field: 'sort', title: '排序', edit: 'text'}, {field: 'status', search: 'select', selectList: ua.getDataBrage('select_list_status'), title: '状态', templet: ua.table.switch}, {field: 'cert_file', title: '合格证', templet: ua.table.url}, {field: 'remark', title: '备注说明', templet: ua.table.text}, {field: 'create_time', title: 'create_time'}, {field: 'publish_time', title: '发布日期'}, {field: 'sale_time', title: '售卖日期'}, {field: 'intro', title: '简介'}, {field: 'time_status', search: 'select', selectList: ua.getDataBrage('select_list_time_status'), title: '秒杀状态'}, {field: 'is_recommend', search: 'select', selectList: ua.getDataBrage('select_list_is_recommend'), title: '是否推荐'}, {field: 'shop_type', search: 'select', selectList: ua.getDataBrage('select_list_shop_type'), title: '商品类型'}, {field: 'from_area', title: '产地'}, {field: 'store_city', title: '仓库'}, {field: 'tag_input', title: '商品标签 (输入)'}, {field: 'uid', title: '唯一id'}, {field: 'price', title: '价格'}, {field: 'detail', title: '详情'}, {field: 'mallCate.id', title: ''}, {field: 'mallCate.title', title: '分类名'}, {field: 'mallCate.image', title: '分类图片', templet: ua.table.image}, {field: 'mallCate.sort', title: '排序', edit: 'text'}, {field: 'mallCate.status', title: '状态', templet: ua.table.switch}, {field: 'mallCate.remark', title: '备注说明', templet: ua.table.text}, {field: 'mallCate.create_time', title: '创建时间'}, {width: 250, title: '操作', templet: ua.table.tool, operat: [{class: 'layui-btn layui-btn-primary layui-btn-xs', method: 'tab', field: 'id', text: '详情', title: '查看详情', auth: 'read', url: 'read', icon: ''}, 'edit', 'delete'], fixed:'right'}, + + ]], + }); + + ua.listen(); +}) \ No newline at end of file diff --git a/app/admin/view/test/goods/read.html b/app/admin/view/test/goods/read.html new file mode 100644 index 0000000..4c29a4b --- /dev/null +++ b/app/admin/view/test/goods/read.html @@ -0,0 +1,40 @@ +
+
+
+
+
+
+

#{$row.id} {$title}

+
ID: {$row.id}
+
+
+ + + +
+
+
+
+
+ +
+
+
分类ID
{$row.cate_id|default=''}
商品名称
{$row.title|default=''}
商品logo
商品图片
{$row.images|default=''}
商品描述
{$row.describe|raw|default=''}
总库存
{$row.total_stock|default=''}
合格证
{$row.cert_file|default=''}
检测报告
{$row.verfiy_file|default=''}
备注说明
{$row.remark|raw|default=''}
发布日期
{$row.publish_time|default=''}
售卖日期
{$row.sale_time|default=''}
简介
{$row.intro|raw|default=''}
秒杀状态
{$row.time_status|default=''}
是否推荐
{eq name="row.is_recommend" value="1"}启用{else/}禁用{/eq}
商品类型
{$row.shop_type|default=''}
商品标签
{$row.tag|default=''}
商品标签(单选)
{$row.tag_backup|default=''}
产地
{$row.from_area|default=''}
仓库
{$row.store_city|default=''}
商品标签 (输入)
{$row.tag_input|default=''}
唯一id
{$row.uid|default=''}
价格
{$row.price|default=''}
详情
{$row.detail|default=''}
+
+
+ +
+

基础信息

+
+
+
ID
+
{$row.id}
+
+
排序
{$row.sort|default=''}
状态
{$row.status|default=''}
create_time
{$row.create_time|default=''}
+
+
+
+
+
+
+
\ No newline at end of file diff --git a/app/admin/view/test/goods/read.js b/app/admin/view/test/goods/read.js new file mode 100644 index 0000000..f5671a7 --- /dev/null +++ b/app/admin/view/test/goods/read.js @@ -0,0 +1,22 @@ +$(function(){ + // 删除数据 + window.deleteData = function(id) { + layer.confirm('确定要删除这条数据吗?', { + icon: 3, + title: '提示' + }, function(index) { + $.post('{{:url("delete")}}', {id: id}, function(res) { + if (res.code == 0) { + layer.msg('删除成功', {icon: 1}, function() { + location.href = '{{:url("index")}}'; + }); + } else { + layer.msg(res.msg, {icon: 2}); + } + }, 'json'); + layer.close(index); + }); + }; + + ua.listen(); +}) \ No newline at end of file diff --git a/extend/base/admin/service/curd/BuildCurdServiceBase.php b/extend/base/admin/service/curd/BuildCurdServiceBase.php index d9f4d1a..e8eab14 100644 --- a/extend/base/admin/service/curd/BuildCurdServiceBase.php +++ b/extend/base/admin/service/curd/BuildCurdServiceBase.php @@ -1454,6 +1454,129 @@ class BuildCurdServiceBase ); $this->fileList[$viewEditFile] = $viewEditValue; + // 详情页面 + $viewReadFile = "{$this->rootDir}app{$this->DS}admin{$this->DS}view{$this->DS}{$this->viewFilename}{$this->DS}read.html"; + $mainFields = ''; + $basicFields = ''; + + // 定义基础字段(右侧显示) + $basicFieldList = ['id', 'create_time', 'update_time', 'status', 'sort', 'delete_time']; + + foreach ($this->tableColumns as $field => $val) { + if (in_array($field, ['id'])) { + continue; + } + + $templateFile = "view{$this->DS}module{$this->DS}input"; + $value = '{$row.' . $field . '|default=\'\'}'; + + // 根据字段类型选择不同的模板 + if ($val['formType'] == 'image') { + $templateFile = "view{$this->DS}module{$this->DS}image"; + } elseif ($val['formType'] == 'images') { + $templateFile = "view{$this->DS}module{$this->DS}images"; + } elseif ($val['formType'] == 'file') { + $templateFile = "view{$this->DS}module{$this->DS}file"; + } elseif ($val['formType'] == 'files') { + $templateFile = "view{$this->DS}module{$this->DS}files"; + } elseif ($val['formType'] == 'editor' || in_array($field, ['remark']) || $val['formType'] == 'textarea') { + $templateFile = "view{$this->DS}module{$this->DS}textarea"; + $value = '{$row.' . $field . '|raw|default=\'\'}'; + } elseif ($val['formType'] == 'date') { + $templateFile = "view{$this->DS}module{$this->DS}date"; + if (isset($val['define']) && !empty($val['define'])) { + $define = $val['define']; + } else { + $define = 'datetime'; + } + if (!in_array($define, ['year', 'month', 'date', 'time', 'datetime'])) { + $define = 'datetime'; + } + } elseif ($val['formType'] == 'radio' || $val['formType'] == 'switch') { + $templateFile = "view{$this->DS}module{$this->DS}radio"; + if (isset($val['define']) && !empty($val['define'])) { + $define = $this->buildRadioView($field, '{in name="k" value="$row.' . $field . '"}checked=""{/in}'); + } + } elseif ($val['formType'] == 'checkbox') { + $templateFile = "view{$this->DS}module{$this->DS}checkbox"; + if (isset($val['define']) && !empty($val['define'])) { + $define = $this->buildCheckboxView($field, '{in name="k" value="$row.' . $field . '"}checked=""{/in}'); + } + } elseif ($val['formType'] == 'select') { + $templateFile = "view{$this->DS}module{$this->DS}select"; + if (isset($val['bindRelation'])) { + $define = $this->buildOptionView($val['bindRelation'], '{in name="k" value="$row.' . $field . '"}selected=""{/in}'); + } elseif (isset($val['define']) && !empty($val['define'])) { + $define = $this->buildOptionView($field, '{in name="k" value="$row.' . $field . '"}selected=""{/in}'); + } + } elseif ($val['formType'] == 'relation') { + $val['define']['type'] = 'radio'; + $val['define']['valueField'] = 'id'; + $val['define']['fieldName'] = $val['define']['relationBindSelect']; + $templateFile = "view{$this->DS}module{$this->DS}table"; + $define = $this->buildTableView($field, $val, $value); + } elseif ($val['formType'] == 'table') { + $templateFile = "view{$this->DS}module{$this->DS}table"; + $define = $this->buildTableView($field, $val, $value); + } elseif ($val['formType'] == 'city') { + $templateFile = "view{$this->DS}module{$this->DS}city"; + $define = $this->buildCityView($field, $val, $value); + } elseif ($val['formType'] == 'tag') { + $templateFile = "view{$this->DS}module{$this->DS}tag"; + } + + // 直接生成详情页面的字段展示HTML,使用简单的div结构 + $fieldContent = '
'; + $fieldContent .= '
' . $val['comment'] . '
'; + $fieldContent .= '
'; + + // 根据字段类型处理值的显示 + if ($val['formType'] == 'editor' || in_array($field, ['remark']) || $val['formType'] == 'textarea') { + $fieldContent .= '{$row.' . $field . '|raw|default=\'\'}'; + } elseif ($val['formType'] == 'image') { + $fieldContent .= ''; + } elseif ($val['formType'] == 'switch') { + $fieldContent .= '{eq name="row.' . $field . '" value="1"}启用{else/}禁用{/eq}'; + } else { + $fieldContent .= '{$row.' . $field . '|default=\'\'}'; + } + + $fieldContent .= '
'; + $fieldContent .= '
'; + + // 注释掉表单模板生成逻辑 + /* + $fieldContent = $this->replaceTemplate( + $this->getTemplate($templateFile), + [ + 'comment' => $val['comment'], + 'field' => $field, + 'required' => '', + 'required_text' => '', + 'value' => $value, + 'define' => $define, + ] + ); + */ + + // 根据字段类型分配到不同区域 + if (in_array($field, $basicFieldList)) { + $basicFields .= $fieldContent; + } else { + $mainFields .= $fieldContent; + } + } + + $viewReadValue = $this->replaceTemplate( + $this->getTemplate("view{$this->DS}read"), + [ + + 'mainFields' => $mainFields, + 'basicFields' => $basicFields, + ] + ); + $this->fileList[$viewReadFile] = $viewReadValue; + return $this; } @@ -1538,7 +1661,8 @@ class BuildCurdServiceBase } } - $indexCols .= $this->formatColsRow("{width: 250, title: '操作', templet: ua.table.tool , fixed:'right'},\r"); + $indexCols .= $this->formatColsRow("{width: 250, title: '操作', templet: ua.table.tool, operat: [{class: 'layui-btn layui-btn-primary layui-btn-xs', method: 'tab', field: 'id', text: '详情', title: '查看详情', auth: 'read', url: 'read', icon: ''}, 'edit', 'delete'], fixed:'right'}, +"); $js_index = $this->replaceTemplate( $this->getTemplate("js{$this->DS}index"), @@ -1560,12 +1684,16 @@ class BuildCurdServiceBase $js_add_file = "{$this->rootDir}app{$this->DS}admin{$this->DS}view{$this->DS}{$this->viewFilename}{$this->DS}add.js"; $js_edit_file = "{$this->rootDir}app{$this->DS}admin{$this->DS}view{$this->DS}{$this->viewFilename}{$this->DS}edit.js"; + $js_read_file = "{$this->rootDir}app{$this->DS}admin{$this->DS}view{$this->DS}{$this->viewFilename}{$this->DS}read.js"; $js_add = $this->replaceTemplate($this->getTemplate("js{$this->DS}add")); $this->fileList[$js_add_file] = $js_add; $js_edit = $this->replaceTemplate($this->getTemplate("js{$this->DS}edit")); $this->fileList[$js_edit_file] = $js_edit; + + $js_read = $this->replaceTemplate($this->getTemplate("js{$this->DS}read")); + $this->fileList[$js_read_file] = $js_read; return $this; } diff --git a/extend/base/admin/service/curd/templates/js/read.code b/extend/base/admin/service/curd/templates/js/read.code new file mode 100644 index 0000000..f5671a7 --- /dev/null +++ b/extend/base/admin/service/curd/templates/js/read.code @@ -0,0 +1,22 @@ +$(function(){ + // 删除数据 + window.deleteData = function(id) { + layer.confirm('确定要删除这条数据吗?', { + icon: 3, + title: '提示' + }, function(index) { + $.post('{{:url("delete")}}', {id: id}, function(res) { + if (res.code == 0) { + layer.msg('删除成功', {icon: 1}, function() { + location.href = '{{:url("index")}}'; + }); + } else { + layer.msg(res.msg, {icon: 2}); + } + }, 'json'); + layer.close(index); + }); + }; + + ua.listen(); +}) \ No newline at end of file diff --git a/extend/base/admin/service/curd/templates/view/read.code b/extend/base/admin/service/curd/templates/view/read.code new file mode 100644 index 0000000..1ce63aa --- /dev/null +++ b/extend/base/admin/service/curd/templates/view/read.code @@ -0,0 +1,40 @@ +
+
+
+
+
+
+

#{$row.id} {$title}

+
ID: {$row.id}
+
+
+ + + +
+
+
+
+
+ +
+
+ {{mainFields}} +
+
+ +
+

基础信息

+
+
+
ID
+
{$row.id}
+
+ {{basicFields}} +
+
+
+
+
+
+
\ No newline at end of file diff --git a/extend/base/admin/traits/CurdTraitBase.php b/extend/base/admin/traits/CurdTraitBase.php index 67562c0..e9383dc 100644 --- a/extend/base/admin/traits/CurdTraitBase.php +++ b/extend/base/admin/traits/CurdTraitBase.php @@ -130,6 +130,23 @@ trait CurdTraitBase return download($content, $export_file_name . date('YmdHis') . '.xlsx', true); } + /** + * @\app\admin\service\annotation\NodeAnotation(title="详情") + */ + public function read($id) + { + $row = $this->model->find($id); + empty($row) && $this->error('数据不存在'); + + // 获取模型的标题(表注释) + $title = $row->title; + + $this->assign('row', $row); + $this->assign('title', $title); + + return $this->fetch(); + } + /** * @\app\admin\service\annotation\NodeAnotation(title="属性修改") */ diff --git a/public/static/admin/css/public.css b/public/static/admin/css/public.css index 0bc4979..1aad26a 100644 --- a/public/static/admin/css/public.css +++ b/public/static/admin/css/public.css @@ -532,6 +532,130 @@ table样式 white-space: nowrap; } +/** +详情页面样式 + */ +/* 详情页面容器 */ +.detail-container { + background-color: #ffffff; +} + +/* 详情页面卡片 */ +.detail-card { + background-color: #ffffff; + border: 1px solid #e8e8e8; + border-radius: 4px; +} + +/* 详情页面头部 */ +.detail-header { + background-color: #f8f9fa; + border-bottom: 1px solid #e8e8e8; +} + +/* 详情标题 */ +.detail-title { + font-size: 20px; + font-weight: bold; + color: #333; +} + +/* 详情ID */ +.detail-id { + font-size: 12px; + color: #999; +} + +/* 详情内容区域 */ +.detail-content { + background-color: #ffffff; +} + +/* 左侧主体内容 */ +.detail-main { + background-color: #ffffff; +} + +/* 右侧基础信息 */ +.detail-side { + background-color: #f5f7fa; + border-radius: 4px; +} + +/* 右侧面板标题 */ +.detail-side-title { + font-size: 16px; + font-weight: bold; + color: #333; + margin-bottom: 15px; + padding-bottom: 10px; + border-bottom: 1px solid #e8e8e8; +} + +/* 字段组样式 */ +.detail-field-group { + margin-bottom: 0; +} + +/* 字段项样式 */ +.detail-field-item { + margin-bottom: 15px; + padding-bottom: 15px; + border-bottom: 1px solid #f0f0f0; + overflow: hidden; +} + +.detail-field-item:last-child { + border-bottom: none; + margin-bottom: 0; + padding-bottom: 0; +} + +/* 字段标签样式 */ +.detail-field-label { + font-weight: bold; + color: #666; + margin-bottom: 5px; + font-size: 14px; + float: left; + width: 100px; + text-align: left; +} + +/* 字段值样式 */ +.detail-field-value { + color: #333; + line-height: 1.5; + font-size: 14px; + margin-left: 110px; + min-height: 30px; + word-break: break-word; +} + +/* 详情图片样式 */ +.detail-image { + max-width: 100%; + height: auto; + border-radius: 4px; + border: 1px solid #e8e8e8; +} + +/* 详情操作按钮 */ +.detail-actions { + text-align: right; +} + +/* 响应式设计 */ +@media (max-width: 768px) { + .detail-field-label { + float: none; + width: 100%; + margin-bottom: 5px; + } + .detail-field-value { + margin-left: 0; + } +} .search-hide-item { display: none; } diff --git a/public/static/admin/css/public.scss b/public/static/admin/css/public.scss index c59b042..401dba3 100644 --- a/public/static/admin/css/public.scss +++ b/public/static/admin/css/public.scss @@ -538,8 +538,131 @@ table样式 } +/** +详情页面样式 + */ +/* 详情页面容器 */ +.detail-container { + background-color: #ffffff; +} +/* 详情页面卡片 */ +.detail-card { + background-color: #ffffff; + border: 1px solid #e8e8e8; + border-radius: 4px; +} +/* 详情页面头部 */ +.detail-header { + background-color: #f8f9fa; + border-bottom: 1px solid #e8e8e8; +} + +/* 详情标题 */ +.detail-title { + font-size: 20px; + font-weight: bold; + color: #333; +} + +/* 详情ID */ +.detail-id { + font-size: 12px; + color: #999; +} + +/* 详情内容区域 */ +.detail-content { + background-color: #ffffff; +} + +/* 左侧主体内容 */ +.detail-main { + background-color: #ffffff; +} + +/* 右侧基础信息 */ +.detail-side { + background-color: #f5f7fa; + border-radius: 4px; +} + +/* 右侧面板标题 */ +.detail-side-title { + font-size: 16px; + font-weight: bold; + color: #333; + margin-bottom: 15px; + padding-bottom: 10px; + border-bottom: 1px solid #e8e8e8; +} + +/* 字段组样式 */ +.detail-field-group { + margin-bottom: 0; +} + +/* 字段项样式 */ +.detail-field-item { + margin-bottom: 15px; + padding-bottom: 15px; + border-bottom: 1px solid #f0f0f0; + overflow: hidden; +} + +.detail-field-item:last-child { + border-bottom: none; + margin-bottom: 0; + padding-bottom: 0; +} + +/* 字段标签样式 */ +.detail-field-label { + font-weight: bold; + color: #666; + margin-bottom: 5px; + font-size: 14px; + float: left; + width: 100px; + text-align: left; +} + +/* 字段值样式 */ +.detail-field-value { + color: #333; + line-height: 1.5; + font-size: 14px; + margin-left: 110px; + min-height: 30px; + word-break: break-word; +} + +/* 详情图片样式 */ +.detail-image { + max-width: 100%; + height: auto; + border-radius: 4px; + border: 1px solid #e8e8e8; +} + +/* 详情操作按钮 */ +.detail-actions { + text-align: right; +} + +/* 响应式设计 */ +@media (max-width: 768px) { + .detail-field-label { + float: none; + width: 100%; + margin-bottom: 5px; + } + + .detail-field-value { + margin-left: 0; + } +} .search-hide-item { display: none; diff --git a/public/static/common/css/theme/index.css b/public/static/common/css/theme/index.css index 012cc78..ae2d7c5 100644 --- a/public/static/common/css/theme/index.css +++ b/public/static/common/css/theme/index.css @@ -89,8 +89,7 @@ .elem-style-neomorphic .elem-style-sicfi .layui-side.layui-bg-black > .layuimini-menu-left > ul, .elem-style-sicfi .elem-style-neomorphic .layuimini-menu-left-zoom > ul, .elem-style-neomorphic .elem-style-sicfi .layuimini-menu-left-zoom > ul, .elem-style-sicfi .elem-style-neomorphic .layuimini-qiuck-module, .elem-style-neomorphic .elem-style-sicfi .layuimini-qiuck-module, .elem-style-sicfi .elem-style-neomorphic .panel, .elem-style-neomorphic .elem-style-sicfi .panel, .elem-style-sicfi .elem-style-neomorphic .layui-card, .elem-style-neomorphic .elem-style-sicfi .layui-card, .elem-style-sicfi .elem-style-neomorphic .layui-layer, .elem-style-neomorphic .elem-style-sicfi .layui-layer, .elem-style-sicfi .elem-style-neomorphic .layuimini-main, .elem-style-neomorphic .elem-style-sicfi .layuimini-main, .elem-style-sicfi .elem-style-neomorphic .layui-table-tool .layui-inline[lay-event], .elem-style-neomorphic .layui-table-tool .elem-style-sicfi .layui-inline[lay-event], .elem-style-sicfi .elem-style-win7 .layui-layer-easy .layui-layer-btn a, .elem-style-win7 .layui-layer-easy .layui-layer-btn .elem-style-sicfi a, .elem-style-sicfi .elem-style-nes .layui-layer-easy .layui-layer-btn a, .elem-style-nes .layui-layer-easy .layui-layer-btn .elem-style-sicfi a, .elem-style-sicfi .elem-style-nes .layuimini-container .layui-table-tool .layui-inline[lay-event], .elem-style-nes .layuimini-container .layui-table-tool .elem-style-sicfi .layui-inline[lay-event], .elem-style-sicfi .elem-style-gtk .layuimini-header-menu > li.layui-nav-item, .elem-style-gtk .elem-style-sicfi .layuimini-header-menu > li.layui-nav-item, .elem-style-sicfi .elem-style-gtk .layui-tab-brief > .layui-tab-title li, .elem-style-gtk .layui-tab-brief > .layui-tab-title .elem-style-sicfi li, .elem-style-sicfi .elem-style-gtk .layui-laydate-footer span, .elem-style-gtk .layui-laydate-footer .elem-style-sicfi span, .elem-style-sicfi .elem-style-gtk .laydate-footer-btns span, .elem-style-gtk .laydate-footer-btns .elem-style-sicfi span, .elem-style-sicfi .elem-style-gtk .layuimini-container .layui-table-tool .layui-inline[lay-event], .elem-style-gtk .layuimini-container .layui-table-tool .elem-style-sicfi .layui-inline[lay-event], .elem-style-sicfi .layui-layer-easy .layui-layer-btn a { - -webkit-clip-path: polygon(0 0, 100% 0, 100% calc(100% - 10px), calc(100% - 10px) 100%, 0 100%, 0 0); - clip-path: polygon(0 0, 100% 0, 100% calc(100% - 10px), calc(100% - 10px) 100%, 0 100%, 0 0); + clip-path: polygon(0 0, 100% 0, 100% calc(100% - 10px), calc(100% - 10px) 100%, 0 100%, 0 0); padding-right: 10px; position: relative; background-color: transparent; @@ -119,8 +118,7 @@ display: block; position: absolute; z-index: -1; - -webkit-clip-path: polygon(0 0, 100% 0, 100% calc(100% - 10px), calc(100% - 10px) 100%, 0 100%, 0 0); - clip-path: polygon(0 0, 100% 0, 100% calc(100% - 10px), calc(100% - 10px) 100%, 0 100%, 0 0); + clip-path: polygon(0 0, 100% 0, 100% calc(100% - 10px), calc(100% - 10px) 100%, 0 100%, 0 0); width: 100%; height: 100%; left: -0.5px; @@ -138,8 +136,7 @@ display: block; position: absolute; z-index: -1; - -webkit-clip-path: polygon(0 0, 100% 0, 100% calc(100% - 10px), calc(100% - 10px) 100%, 0 100%, 0 0); - clip-path: polygon(0 0, 100% 0, 100% calc(100% - 10px), calc(100% - 10px) 100%, 0 100%, 0 0); + clip-path: polygon(0 0, 100% 0, 100% calc(100% - 10px), calc(100% - 10px) 100%, 0 100%, 0 0); width: 100%; height: 100%; left: -0.5px; @@ -275,8 +272,7 @@ border-color: rgb(126, 252, 246); border-width: 1px; border-style: solid; - -webkit-clip-path: polygon(0 0, 100% 0, 100% calc(100% - 10px), calc(100% - 10px) 100%, 0 100%, 0 0); - clip-path: polygon(0 0, 100% 0, 100% calc(100% - 10px), calc(100% - 10px) 100%, 0 100%, 0 0); + clip-path: polygon(0 0, 100% 0, 100% calc(100% - 10px), calc(100% - 10px) 100%, 0 100%, 0 0); position: absolute; left: 0; top: 0; @@ -298,8 +294,7 @@ background-color: rgb(2, 17, 20) !important; } .elem-style-sicfi .layuimini-color .elem-content li { - -webkit-clip-path: polygon(0 0, 100% 0, 100% calc(100% - 10px), calc(100% - 10px) 100%, 0 100%, 0 0); - clip-path: polygon(0 0, 100% 0, 100% calc(100% - 10px), calc(100% - 10px) 100%, 0 100%, 0 0); + clip-path: polygon(0 0, 100% 0, 100% calc(100% - 10px), calc(100% - 10px) 100%, 0 100%, 0 0); } .elem-style-sicfi .layuimini-color .elem-content li.layui-this { background-color: rgb(126, 252, 246); @@ -671,8 +666,7 @@ background-color: rgb(126, 252, 246); border-color: rgb(6, 216, 215); color: rgb(126, 252, 246) !important; - -webkit-clip-path: polygon(0 0, 100% 0, 100% calc(100% - 10px), calc(100% - 10px) 100%, 0 100%, 0 0); - clip-path: polygon(0 0, 100% 0, 100% calc(100% - 10px), calc(100% - 10px) 100%, 0 100%, 0 0); + clip-path: polygon(0 0, 100% 0, 100% calc(100% - 10px), calc(100% - 10px) 100%, 0 100%, 0 0); } .elem-style-sicfi .layui-layer-shade { background-color: #fff !important; @@ -682,8 +676,7 @@ width: calc(100% - 10px); } .elem-style-sicfi .layuimini-menu-left .layui-nav .layui-nav-item { - -webkit-clip-path: polygon(0 0, 100% 0, 100% calc(100% - 10px), calc(100% - 10px) 100%, 0 100%, 0 0); - clip-path: polygon(0 0, 100% 0, 100% calc(100% - 10px), calc(100% - 10px) 100%, 0 100%, 0 0); + clip-path: polygon(0 0, 100% 0, 100% calc(100% - 10px), calc(100% - 10px) 100%, 0 100%, 0 0); color: rgb(126, 252, 246); background-color: rgba(62, 251, 251, 0.5); } From 0e92ab23634828667bfdb892a989ab058342fa24 Mon Sep 17 00:00:00 2001 From: augushong Date: Thu, 8 Jan 2026 23:43:21 +0800 Subject: [PATCH 2/4] =?UTF-8?q?feat:=20=E5=88=9D=E6=AD=A5=E5=AE=8C?= =?UTF-8?q?=E6=88=90=E8=AF=A6=E6=83=85=E7=94=9F=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .trae/documents/添加CURD详情页面生成功能.md | 134 --------- .trae/rules/project_rules.md => CODERULE.md | 0 app/admin/controller/test/Goods.php | 24 +- app/admin/model/TestGoods.php | 36 ++- app/admin/view/test/goods/_common.js | 3 +- app/admin/view/test/goods/index.js | 17 +- app/admin/view/test/goods/read.html | 260 +++++++++++++++++- .../service/curd/BuildCurdServiceBase.php | 222 ++++++++------- .../curd/templates/controller/select.code | 6 +- .../service/curd/templates/js/_common.code | 3 +- .../curd/templates/model/accessor.code | 12 + .../service/curd/templates/model/model.code | 4 +- .../curd/templates/view/module/readDate.code | 10 + .../templates/view/module/readEditor.code | 10 + .../curd/templates/view/module/readFile.code | 13 + .../curd/templates/view/module/readFiles.code | 17 ++ .../curd/templates/view/module/readImage.code | 10 + .../templates/view/module/readImages.code | 12 + .../templates/view/module/readSelect.code | 6 + .../templates/view/module/readSwitch.code | 6 + .../curd/templates/view/module/readText.code | 10 + .../templates/view/module/readTextarea.code | 10 + 22 files changed, 578 insertions(+), 247 deletions(-) delete mode 100644 .trae/documents/添加CURD详情页面生成功能.md rename .trae/rules/project_rules.md => CODERULE.md (100%) create mode 100644 extend/base/admin/service/curd/templates/model/accessor.code create mode 100644 extend/base/admin/service/curd/templates/view/module/readDate.code create mode 100644 extend/base/admin/service/curd/templates/view/module/readEditor.code create mode 100644 extend/base/admin/service/curd/templates/view/module/readFile.code create mode 100644 extend/base/admin/service/curd/templates/view/module/readFiles.code create mode 100644 extend/base/admin/service/curd/templates/view/module/readImage.code create mode 100644 extend/base/admin/service/curd/templates/view/module/readImages.code create mode 100644 extend/base/admin/service/curd/templates/view/module/readSelect.code create mode 100644 extend/base/admin/service/curd/templates/view/module/readSwitch.code create mode 100644 extend/base/admin/service/curd/templates/view/module/readText.code create mode 100644 extend/base/admin/service/curd/templates/view/module/readTextarea.code diff --git a/.trae/documents/添加CURD详情页面生成功能.md b/.trae/documents/添加CURD详情页面生成功能.md deleted file mode 100644 index 2d1b084..0000000 --- a/.trae/documents/添加CURD详情页面生成功能.md +++ /dev/null @@ -1,134 +0,0 @@ -# CURD详情页面生成功能实现计划 - -## 1. 需求分析 - -* 当前CURD生成功能不包含详情页面 - -* 详情页面需要合理布局:顶部是标题+ID,左侧8/12是主体,右侧4/12是基础字段 - -* 详情页面需要包含编辑、删除、返回等基础按钮操作 - -* 支持后续扩展更多字段 - -* 使用Layui栅格系统 - -## 2. 实现步骤 - -### 2.1 添加详情方法到CURD Trait - -* 在 `CurdTraitBase.php` 中添加 `read` 方法 - -* 实现详情数据获取和页面渲染逻辑 - -### 2.2 创建详情页面模板 - -* 创建 `view/read.code` 主模板 - -* 设计Layui风格布局: - * 顶部区域:标题、ID和操作按钮(编辑、删除、返回) - * 内容区域:使用 `layui-row` 和 `layui-col-md-*` 实现8/4分栏 - * 左侧:主体字段(8列) - * 右侧:基础字段(4列,包含创建时间、更新时间等) - -### 2.3 修改BuildCurdServiceBase - -* 在 `renderView` 方法中添加详情页面生成逻辑 - -* 实现字段分类: - * 主体字段:除ID、创建时间、更新时间外的大部分字段 - * 基础字段:ID、创建时间、更新时间、状态等系统字段 - -* 添加详情页面到文件列表 - -### 2.4 更新JS文件生成 - -* 修改 `js/index.code` 模板 - -* 在操作列添加详情按钮 - -* 实现详情跳转逻辑 - -### 2.5 更新控制器模板 - -* 确保控制器支持详情页面路由 - -## 3. 布局设计(Layui风格) - -```html - -
-
-
-
-

{{title}}

-
ID: {{id}}
-
-
- - - -
-
-
- - -
-
- -
-
- -
-
- - -
-
- -
-
-
-
-
-``` - -## 4. 字段分类规则 - -* **主体字段**:所有非系统字段,如名称、描述、内容等 - -* **基础字段**: - * id - * create_time - * update_time - * status - * 其他系统相关字段 - -## 5. 实现要点 - -* 保持与Layui框架风格一致 - -* 遵循现有代码生成模式 - -* 支持后续字段扩展 - -* 确保详情页面与现有功能无缝集成 - -* 添加必要的JavaScript交互逻辑 - -## 6. 文件修改清单 - -1. `extend/base/admin/traits/CurdTraitBase.php` - 添加read方法 -2. `extend/base/admin/service/curd/templates/view/read.code` - 详情页面模板 -3. `extend/base/admin/service/curd/BuildCurdServiceBase.php` - 添加详情页面生成逻辑 -4. `extend/base/admin/service/curd/templates/js/index.code` - 添加详情按钮 -5. `extend/base/admin/service/curd/templates/js/read.code` - 详情页面JS逻辑 - -## 7. 详情页面按钮功能 - -* **返回**:返回上一页 - -* **编辑**:跳转到编辑页面 - -* **删除**:调用删除接口,删除当前数据 - -* 所有按钮使用Layui样式,保持一致的视觉效果 \ No newline at end of file diff --git a/.trae/rules/project_rules.md b/CODERULE.md similarity index 100% rename from .trae/rules/project_rules.md rename to CODERULE.md diff --git a/app/admin/controller/test/Goods.php b/app/admin/controller/test/Goods.php index 3601754..9d9a9eb 100644 --- a/app/admin/controller/test/Goods.php +++ b/app/admin/controller/test/Goods.php @@ -27,13 +27,29 @@ class Goods extends AdminController $this->model = new \app\admin\model\TestGoods(); - $this->assign('select_list_status', $this->model::SELECT_LIST_STATUS, true); + $select_list_status_list = []; + foreach ($this->model::SELECT_LIST_STATUS as $key => $value) { + $select_list_status_list[] = ['value' => $key, 'label' => $value]; + } + $this->assign('select_list_status', $select_list_status_list, true); - $this->assign('select_list_time_status', $this->model::SELECT_LIST_TIME_STATUS, true); + $select_list_time_status_list = []; + foreach ($this->model::SELECT_LIST_TIME_STATUS as $key => $value) { + $select_list_time_status_list[] = ['value' => $key, 'label' => $value]; + } + $this->assign('select_list_time_status', $select_list_time_status_list, true); - $this->assign('select_list_is_recommend', $this->model::SELECT_LIST_IS_RECOMMEND, true); + $select_list_is_recommend_list = []; + foreach ($this->model::SELECT_LIST_IS_RECOMMEND as $key => $value) { + $select_list_is_recommend_list[] = ['value' => $key, 'label' => $value]; + } + $this->assign('select_list_is_recommend', $select_list_is_recommend_list, true); - $this->assign('select_list_shop_type', $this->model::SELECT_LIST_SHOP_TYPE, true); + $select_list_shop_type_list = []; + foreach ($this->model::SELECT_LIST_SHOP_TYPE as $key => $value) { + $select_list_shop_type_list[] = ['value' => $key, 'label' => $value]; + } + $this->assign('select_list_shop_type', $select_list_shop_type_list, true); } diff --git a/app/admin/model/TestGoods.php b/app/admin/model/TestGoods.php index 0c12663..b7d911c 100644 --- a/app/admin/model/TestGoods.php +++ b/app/admin/model/TestGoods.php @@ -41,15 +41,39 @@ class TestGoods extends TimeModel protected $deleteTime = "delete_time"; - public const SELECT_LIST_STATUS = ['0'=>'正常','1'=>'禁用',]; + public const SELECT_LIST_STATUS = ['0' => '正常', '1' => '禁用']; - public const SELECT_LIST_TIME_STATUS = ['0'=>'未参加','1'=>'已开始','3'=>'已结束',]; + public const SELECT_LIST_TIME_STATUS = ['0' => '未参加', '1' => '已开始', '3' => '已结束']; - public const SELECT_LIST_IS_RECOMMEND = ['0'=>'不推荐','1'=>'推荐',]; + public const SELECT_LIST_IS_RECOMMEND = ['0' => '不推荐', '1' => '推荐']; - public const SELECT_LIST_SHOP_TYPE = ['taobao'=>'淘宝','jd'=>'京东',]; + public const SELECT_LIST_SHOP_TYPE = ['taobao' => '淘宝', 'jd' => '京东']; + + /** + * 商品图片获取器 + * @param $value + * @return array + */ + public function getImagesListAttr($value, $data) + { + if (empty($data['images'])) { + return []; + } + return explode('|', $data['images']); + } + /** + * 检测报告获取器 + * @param $value + * @return array + */ + public function getVerfiyFileListAttr($value, $data) + { + if (empty($data['verfiy_file'])) { + return []; + } + return explode('|', $data['verfiy_file']); + } - public function mallCate() { @@ -57,4 +81,4 @@ class TestGoods extends TimeModel } -} \ No newline at end of file +} diff --git a/app/admin/view/test/goods/_common.js b/app/admin/view/test/goods/_common.js index 6e85503..ae3225b 100644 --- a/app/admin/view/test/goods/_common.js +++ b/app/admin/view/test/goods/_common.js @@ -4,7 +4,8 @@ var init = { indexUrl: 'test.goods/index', addUrl: 'test.goods/add' + location.search, editUrl: 'test.goods/edit', + readUrl: 'test.goods/read', deleteUrl: 'test.goods/delete', exportUrl: 'test.goods/export', modifyUrl: 'test.goods/modify', -}; \ No newline at end of file +}; diff --git a/app/admin/view/test/goods/index.js b/app/admin/view/test/goods/index.js index 8c46dfe..01c9dcc 100644 --- a/app/admin/view/test/goods/index.js +++ b/app/admin/view/test/goods/index.js @@ -2,7 +2,22 @@ $(function(){ ua.table.render({ init: init, cols: [[ - {type: 'checkbox'}, {field: 'id', title: 'id'}, {field: 'cate_id', title: '分类ID'}, {field: 'title', title: '商品名称'}, {field: 'logo', title: '商品logo', templet: ua.table.image}, {field: 'total_stock', title: '总库存'}, {field: 'sort', title: '排序', edit: 'text'}, {field: 'status', search: 'select', selectList: ua.getDataBrage('select_list_status'), title: '状态', templet: ua.table.switch}, {field: 'cert_file', title: '合格证', templet: ua.table.url}, {field: 'remark', title: '备注说明', templet: ua.table.text}, {field: 'create_time', title: 'create_time'}, {field: 'publish_time', title: '发布日期'}, {field: 'sale_time', title: '售卖日期'}, {field: 'intro', title: '简介'}, {field: 'time_status', search: 'select', selectList: ua.getDataBrage('select_list_time_status'), title: '秒杀状态'}, {field: 'is_recommend', search: 'select', selectList: ua.getDataBrage('select_list_is_recommend'), title: '是否推荐'}, {field: 'shop_type', search: 'select', selectList: ua.getDataBrage('select_list_shop_type'), title: '商品类型'}, {field: 'from_area', title: '产地'}, {field: 'store_city', title: '仓库'}, {field: 'tag_input', title: '商品标签 (输入)'}, {field: 'uid', title: '唯一id'}, {field: 'price', title: '价格'}, {field: 'detail', title: '详情'}, {field: 'mallCate.id', title: ''}, {field: 'mallCate.title', title: '分类名'}, {field: 'mallCate.image', title: '分类图片', templet: ua.table.image}, {field: 'mallCate.sort', title: '排序', edit: 'text'}, {field: 'mallCate.status', title: '状态', templet: ua.table.switch}, {field: 'mallCate.remark', title: '备注说明', templet: ua.table.text}, {field: 'mallCate.create_time', title: '创建时间'}, {width: 250, title: '操作', templet: ua.table.tool, operat: [{class: 'layui-btn layui-btn-primary layui-btn-xs', method: 'tab', field: 'id', text: '详情', title: '查看详情', auth: 'read', url: 'read', icon: ''}, 'edit', 'delete'], fixed:'right'}, + {type: 'checkbox'}, {field: 'id', title: 'id'}, {field: 'cate_id', title: '分类ID'}, {field: 'title', title: '商品名称'}, {field: 'logo', title: '商品logo', templet: ua.table.image}, {field: 'total_stock', title: '总库存'}, {field: 'sort', title: '排序', edit: 'text'}, {field: 'status', search: 'select', selectList: ua.getDataBrage('select_list_status'), title: '状态', templet: ua.table.switch}, {field: 'cert_file', title: '合格证', templet: ua.table.url}, {field: 'remark', title: '备注说明', templet: ua.table.text}, {field: 'create_time', title: 'create_time'}, {field: 'publish_time', title: '发布日期'}, {field: 'sale_time', title: '售卖日期'}, {field: 'intro', title: '简介'}, {field: 'time_status', search: 'select', selectList: ua.getDataBrage('select_list_time_status'), title: '秒杀状态'}, {field: 'is_recommend', search: 'select', selectList: ua.getDataBrage('select_list_is_recommend'), title: '是否推荐'}, {field: 'shop_type', search: 'select', selectList: ua.getDataBrage('select_list_shop_type'), title: '商品类型'}, {field: 'from_area', title: '产地'}, {field: 'store_city', title: '仓库'}, {field: 'tag_input', title: '商品标签 (输入)'}, {field: 'uid', title: '唯一id'}, {field: 'price', title: '价格'}, {field: 'detail', title: '详情'}, {field: 'mallCate.id', title: ''}, {field: 'mallCate.title', title: '分类名'}, {field: 'mallCate.image', title: '分类图片', templet: ua.table.image}, {field: 'mallCate.sort', title: '排序', edit: 'text'}, {field: 'mallCate.status', title: '状态', templet: ua.table.switch}, {field: 'mallCate.remark', title: '备注说明', templet: ua.table.text}, {field: 'mallCate.create_time', title: '创建时间'}, { + width: 250, title: '操作', templet: ua.table.tool, fixed: 'right', operat: [ + [{ + class: 'layui-btn layui-btn-primary layui-btn-xs', + method: 'tab', + field: 'id', + text: '详情', + title: '查看详情', + auth: 'read', + url: init.readUrl, + icon: '' + }], + 'edit', + 'delete' + ] + }, ]], }); diff --git a/app/admin/view/test/goods/read.html b/app/admin/view/test/goods/read.html index 4c29a4b..d0513e9 100644 --- a/app/admin/view/test/goods/read.html +++ b/app/admin/view/test/goods/read.html @@ -19,7 +19,237 @@
-
分类ID
{$row.cate_id|default=''}
商品名称
{$row.title|default=''}
商品logo
商品图片
{$row.images|default=''}
商品描述
{$row.describe|raw|default=''}
总库存
{$row.total_stock|default=''}
合格证
{$row.cert_file|default=''}
检测报告
{$row.verfiy_file|default=''}
备注说明
{$row.remark|raw|default=''}
发布日期
{$row.publish_time|default=''}
售卖日期
{$row.sale_time|default=''}
简介
{$row.intro|raw|default=''}
秒杀状态
{$row.time_status|default=''}
是否推荐
{eq name="row.is_recommend" value="1"}启用{else/}禁用{/eq}
商品类型
{$row.shop_type|default=''}
商品标签
{$row.tag|default=''}
商品标签(单选)
{$row.tag_backup|default=''}
产地
{$row.from_area|default=''}
仓库
{$row.store_city|default=''}
商品标签 (输入)
{$row.tag_input|default=''}
唯一id
{$row.uid|default=''}
价格
{$row.price|default=''}
详情
{$row.detail|default=''}
+
+
分类ID
+
+ {notempty name="row.cate_id"} + {$row.cate_id} + {else/} + 暂无数据 + {/notempty} +
+
+
+
商品名称
+
+ {notempty name="row.title"} + {$row.title} + {else/} + 暂无数据 + {/notempty} +
+
+
+
商品logo
+
+ {notempty name="row.logo"} + + {else/} + 暂无图片 + {/notempty} +
+
+
+
商品图片
+
+ {notempty name="row.images_list"} + {volist name="row.images_list" id="img"} + + {/volist} + {else/} + 暂无图片 + {/notempty} +
+
+
+
商品描述
+
+ {notempty name="row.describe"} + {$row.describe|raw} + {else/} + 暂无内容 + {/notempty} +
+
+
+
总库存
+
+ {notempty name="row.total_stock"} + {$row.total_stock} + {else/} + 暂无数据 + {/notempty} +
+
+
+
合格证
+
+ {notempty name="row.cert_file"} + + 下载文件 + +
{$row.cert_file}
+ {else/} + 暂无文件 + {/notempty} +
+
+
+
检测报告
+
+ {notempty name="row.verfiy_file_list"} + {volist name="row.verfiy_file_list" id="file"} + + {/volist} + {else/} + 暂无文件 + {/notempty} +
+
+
+
备注说明
+
+ {notempty name="row.remark"} + {$row.remark|raw} + {else/} + 暂无内容 + {/notempty} +
+
+
+
发布日期
+
+ {notempty name="row.publish_time"} + {$row.publish_time|date="Y-m-d H:i:s"} + {else/} + 暂无数据 + {/notempty} +
+
+
+
售卖日期
+
+ {notempty name="row.sale_time"} + {$row.sale_time|date="Y-m-d H:i:s"} + {else/} + 暂无数据 + {/notempty} +
+
+
+
简介
+
+ {notempty name="row.intro"} + {$row.intro|raw} + {else/} + 暂无内容 + {/notempty} +
+
+
+
秒杀状态
+
+ {volist name="select_list_time_status" id="vo"}{eq name="vo.value" value="$row.time_status"}{$vo.label}{/eq}{/volist} +
+
+
+
是否推荐
+
+ {volist name="select_list_is_recommend" id="vo"}{eq name="vo.value" value="$row.is_recommend"}{volist name="select_list_is_recommend" id="item"}{eq name="item.value" value="$row.is_recommend"}{$item.label}{/eq}{/volist}{/eq}{/volist} +
+
+
+
商品类型
+
+ {volist name="row.shop_type|explode=','" id="item">{volist name="select_list_shop_type" id="vo"}{eq name="vo.value" value="$item"}{$vo.label}{/eq}{/volist}{/volist} +
+
+
+
商品标签
+
+ {notempty name="row.tag"} + {$row.tag} + {else/} + 暂无数据 + {/notempty} +
+
+
+
商品标签(单选)
+
+ {notempty name="row.tag_backup"} + {$row.tag_backup} + {else/} + 暂无数据 + {/notempty} +
+
+
+
产地
+
+ {notempty name="row.from_area"} + {$row.from_area} + {else/} + 暂无数据 + {/notempty} +
+
+
+
仓库
+
+ {notempty name="row.store_city"} + {$row.store_city} + {else/} + 暂无数据 + {/notempty} +
+
+
+
商品标签 (输入)
+
+ {notempty name="row.tag_input"} + {$row.tag_input} + {else/} + 暂无数据 + {/notempty} +
+
+
+
唯一id
+
+ {notempty name="row.uid"} + {$row.uid} + {else/} + 暂无数据 + {/notempty} +
+
+
+
价格
+
+ {notempty name="row.price"} + {$row.price} + {else/} + 暂无数据 + {/notempty} +
+
+
+
详情
+
+ {notempty name="row.detail"} + {$row.detail} + {else/} + 暂无数据 + {/notempty} +
+
+
@@ -30,7 +260,33 @@
ID
{$row.id}
-
排序
{$row.sort|default=''}
状态
{$row.status|default=''}
create_time
{$row.create_time|default=''}
+
+
排序
+
+ {notempty name="row.sort"} + {$row.sort} + {else/} + 暂无数据 + {/notempty} +
+
+
+
状态
+
+ {volist name="select_list_status" id="vo"}{eq name="vo.value" value="$row.status"}{volist name="select_list_status" id="item"}{eq name="item.value" value="$row.status"}{$item.label}{/eq}{/volist}{/eq}{/volist} +
+
+
+
create_time
+
+ {notempty name="row.create_time"} + {$row.create_time} + {else/} + 暂无数据 + {/notempty} +
+
+ diff --git a/extend/base/admin/service/curd/BuildCurdServiceBase.php b/extend/base/admin/service/curd/BuildCurdServiceBase.php index e8eab14..7c1a79c 100644 --- a/extend/base/admin/service/curd/BuildCurdServiceBase.php +++ b/extend/base/admin/service/curd/BuildCurdServiceBase.php @@ -760,9 +760,9 @@ class BuildCurdServiceBase $values = '['; foreach ($array as $k => $v) { - $values .= "'{$k}'=>'{$v}',"; + $values .= "'{$k}' => '{$v}', "; } - $values .= ']'; + $values = rtrim($values, ', ') . ']'; $selectCode = $this->replaceTemplate( $this->getTemplate("model{$this->DS}select"), [ @@ -774,6 +774,31 @@ class BuildCurdServiceBase return $selectCode; } + /** + * 构建获取器模型(用于多图片、多文件字段). + * @param $field + * @param $val + * @return mixed + */ + protected function buildAccessorModel($field, $val) + { + // 获取器名称,如 images -> ImagesListAttr + $accessorName = Str::studly($field) . 'List'; + $separator = isset($val['define']) ? $val['define'] : '|'; + + $accessorCode = $this->replaceTemplate( + $this->getTemplate("model{$this->DS}accessor"), + [ + 'comment' => $val['comment'], + 'accessorName' => $accessorName, + 'field' => $field, + 'separator' => $separator, + ] + ); + + return $accessorCode; + } + /** * 构建下拉框视图. * @param $field @@ -1179,6 +1204,7 @@ class BuildCurdServiceBase } $selectList = ''; + $accessorList = ''; $doc_content = ''; @@ -1186,6 +1212,12 @@ class BuildCurdServiceBase if (isset($val['formType']) && in_array($val['formType'], ['select', 'switch', 'radio', 'checkbox']) && isset($val['define'])) { $selectList .= $this->buildSelectModel($field, $val['define']); } + + // 为多图片和多文件字段生成获取器 + if (in_array($val['formType'], ['images', 'files'])) { + $accessorList .= $this->buildAccessorModel($field, $val); + } + $doc_content .= " * @property {$val['property_type']} \${$val['property_name']} {$val['comment']} {$val['data_list']}\n"; } @@ -1207,6 +1239,7 @@ class BuildCurdServiceBase 'deleteTime' => $this->delete ? '"delete_time"' : 'false', 'relationList' => $relationList, 'selectList' => $selectList, + 'accessorList' => $accessorList, 'doc_content' => $doc_content, ] ); @@ -1467,97 +1500,7 @@ class BuildCurdServiceBase continue; } - $templateFile = "view{$this->DS}module{$this->DS}input"; - $value = '{$row.' . $field . '|default=\'\'}'; - - // 根据字段类型选择不同的模板 - if ($val['formType'] == 'image') { - $templateFile = "view{$this->DS}module{$this->DS}image"; - } elseif ($val['formType'] == 'images') { - $templateFile = "view{$this->DS}module{$this->DS}images"; - } elseif ($val['formType'] == 'file') { - $templateFile = "view{$this->DS}module{$this->DS}file"; - } elseif ($val['formType'] == 'files') { - $templateFile = "view{$this->DS}module{$this->DS}files"; - } elseif ($val['formType'] == 'editor' || in_array($field, ['remark']) || $val['formType'] == 'textarea') { - $templateFile = "view{$this->DS}module{$this->DS}textarea"; - $value = '{$row.' . $field . '|raw|default=\'\'}'; - } elseif ($val['formType'] == 'date') { - $templateFile = "view{$this->DS}module{$this->DS}date"; - if (isset($val['define']) && !empty($val['define'])) { - $define = $val['define']; - } else { - $define = 'datetime'; - } - if (!in_array($define, ['year', 'month', 'date', 'time', 'datetime'])) { - $define = 'datetime'; - } - } elseif ($val['formType'] == 'radio' || $val['formType'] == 'switch') { - $templateFile = "view{$this->DS}module{$this->DS}radio"; - if (isset($val['define']) && !empty($val['define'])) { - $define = $this->buildRadioView($field, '{in name="k" value="$row.' . $field . '"}checked=""{/in}'); - } - } elseif ($val['formType'] == 'checkbox') { - $templateFile = "view{$this->DS}module{$this->DS}checkbox"; - if (isset($val['define']) && !empty($val['define'])) { - $define = $this->buildCheckboxView($field, '{in name="k" value="$row.' . $field . '"}checked=""{/in}'); - } - } elseif ($val['formType'] == 'select') { - $templateFile = "view{$this->DS}module{$this->DS}select"; - if (isset($val['bindRelation'])) { - $define = $this->buildOptionView($val['bindRelation'], '{in name="k" value="$row.' . $field . '"}selected=""{/in}'); - } elseif (isset($val['define']) && !empty($val['define'])) { - $define = $this->buildOptionView($field, '{in name="k" value="$row.' . $field . '"}selected=""{/in}'); - } - } elseif ($val['formType'] == 'relation') { - $val['define']['type'] = 'radio'; - $val['define']['valueField'] = 'id'; - $val['define']['fieldName'] = $val['define']['relationBindSelect']; - $templateFile = "view{$this->DS}module{$this->DS}table"; - $define = $this->buildTableView($field, $val, $value); - } elseif ($val['formType'] == 'table') { - $templateFile = "view{$this->DS}module{$this->DS}table"; - $define = $this->buildTableView($field, $val, $value); - } elseif ($val['formType'] == 'city') { - $templateFile = "view{$this->DS}module{$this->DS}city"; - $define = $this->buildCityView($field, $val, $value); - } elseif ($val['formType'] == 'tag') { - $templateFile = "view{$this->DS}module{$this->DS}tag"; - } - - // 直接生成详情页面的字段展示HTML,使用简单的div结构 - $fieldContent = '
'; - $fieldContent .= '
' . $val['comment'] . '
'; - $fieldContent .= '
'; - - // 根据字段类型处理值的显示 - if ($val['formType'] == 'editor' || in_array($field, ['remark']) || $val['formType'] == 'textarea') { - $fieldContent .= '{$row.' . $field . '|raw|default=\'\'}'; - } elseif ($val['formType'] == 'image') { - $fieldContent .= ''; - } elseif ($val['formType'] == 'switch') { - $fieldContent .= '{eq name="row.' . $field . '" value="1"}启用{else/}禁用{/eq}'; - } else { - $fieldContent .= '{$row.' . $field . '|default=\'\'}'; - } - - $fieldContent .= '
'; - $fieldContent .= '
'; - - // 注释掉表单模板生成逻辑 - /* - $fieldContent = $this->replaceTemplate( - $this->getTemplate($templateFile), - [ - 'comment' => $val['comment'], - 'field' => $field, - 'required' => '', - 'required_text' => '', - 'value' => $value, - 'define' => $define, - ] - ); - */ + $fieldContent = $this->buildReadFieldContent($field, $val); // 根据字段类型分配到不同区域 if (in_array($field, $basicFieldList)) { @@ -1570,7 +1513,6 @@ class BuildCurdServiceBase $viewReadValue = $this->replaceTemplate( $this->getTemplate("view{$this->DS}read"), [ - 'mainFields' => $mainFields, 'basicFields' => $basicFields, ] @@ -1661,7 +1603,22 @@ class BuildCurdServiceBase } } - $indexCols .= $this->formatColsRow("{width: 250, title: '操作', templet: ua.table.tool, operat: [{class: 'layui-btn layui-btn-primary layui-btn-xs', method: 'tab', field: 'id', text: '详情', title: '查看详情', auth: 'read', url: 'read', icon: ''}, 'edit', 'delete'], fixed:'right'}, + $indexCols .= $this->formatColsRow("{ + width: 250, title: '操作', templet: ua.table.tool, fixed: 'right', operat: [ + [{ + class: 'layui-btn layui-btn-primary layui-btn-xs', + method: 'tab', + field: 'id', + text: '详情', + title: '查看详情', + auth: 'read', + url: init.readUrl, + icon: '' + }], + 'edit', + 'delete' + ] + }, "); $js_index = $this->replaceTemplate( @@ -1884,4 +1841,79 @@ class BuildCurdServiceBase return 'mixed'; } + + /** + * 构建详情页字段内容 + * @param $field + * @param $val + * @return string + */ + protected function buildReadFieldContent($field, $val) + { + $templateFile = "view{$this->DS}module{$this->DS}readText"; + $define = ''; + + // 根据formType去获取具体的详情页模板 + if ($val['formType'] == 'image') { + $templateFile = "view{$this->DS}module{$this->DS}readImage"; + } elseif ($val['formType'] == 'images') { + $templateFile = "view{$this->DS}module{$this->DS}readImages"; + $define = isset($val['define']) ? $val['define'] : '|'; + } elseif ($val['formType'] == 'file') { + $templateFile = "view{$this->DS}module{$this->DS}readFile"; + } elseif ($val['formType'] == 'files') { + $templateFile = "view{$this->DS}module{$this->DS}readFiles"; + $define = isset($val['define']) ? $val['define'] : '|'; + } elseif ($val['formType'] == 'editor') { + $templateFile = "view{$this->DS}module{$this->DS}readEditor"; + } elseif (in_array($field, ['remark']) || $val['formType'] == 'textarea') { + $templateFile = "view{$this->DS}module{$this->DS}readTextarea"; + } elseif ($val['formType'] == 'date') { + $templateFile = "view{$this->DS}module{$this->DS}readDate"; + } elseif ($val['formType'] == 'radio' || $val['formType'] == 'switch') { + $templateFile = "view{$this->DS}module{$this->DS}readSwitch"; + if (isset($val['define']) && !empty($val['define'])) { + // 构建下拉选择的显示值 + $var_name = $this->getFieldVarName($field); + $define = '{volist name="' . $var_name . '" id="vo"}{eq name="vo.value" value="$row.' . $field . '"}{volist name="' . $var_name . '" id="item"}{eq name="item.value" value="$row.' . $field . '"}{$item.label}{/eq}{/volist}{/eq}{/volist}'; + } + } elseif ($val['formType'] == 'checkbox') { + $templateFile = "view{$this->DS}module{$this->DS}readSelect"; + if (isset($val['define']) && !empty($val['define'])) { + $var_name = $this->getFieldVarName($field); + $define = '{volist name="row.' . $field . '|explode=\',\'" id="item">{volist name="' . $var_name . '" id="vo"}{eq name="vo.value" value="$item"}{$vo.label}{/eq}{/volist}{/volist}'; + } + } elseif ($val['formType'] == 'select') { + $templateFile = "view{$this->DS}module{$this->DS}readSelect"; + if (isset($val['bindRelation'])) { + $define = '{$row.' . $field . '}'; + } elseif (isset($val['define']) && !empty($val['define'])) { + $var_name = $this->getFieldVarName($field); + $define = '{volist name="' . $var_name . '" id="vo"}{eq name="vo.value" value="$row.' . $field . '"}{$vo.label}{/eq}{/volist}'; + } + } elseif ($val['formType'] == 'relation') { + // 关联表字段暂时使用文本显示 + $templateFile = "view{$this->DS}module{$this->DS}readText"; + } elseif ($val['formType'] == 'table') { + // 表格选择器暂时使用文本显示 + $templateFile = "view{$this->DS}module{$this->DS}readText"; + } elseif ($val['formType'] == 'city') { + // 城市选择器暂时使用文本显示 + $templateFile = "view{$this->DS}module{$this->DS}readText"; + } elseif ($val['formType'] == 'tag') { + // 标签暂时使用文本显示 + $templateFile = "view{$this->DS}module{$this->DS}readText"; + } + + $fieldContent = $this->replaceTemplate( + $this->getTemplate($templateFile), + [ + 'comment' => $val['comment'], + 'field' => $field, + 'define' => $define, + ] + ); + + return $fieldContent; + } } diff --git a/extend/base/admin/service/curd/templates/controller/select.code b/extend/base/admin/service/curd/templates/controller/select.code index ac7ddda..1387626 100644 --- a/extend/base/admin/service/curd/templates/controller/select.code +++ b/extend/base/admin/service/curd/templates/controller/select.code @@ -1,2 +1,6 @@ - $this->assign('{{var_name}}', $this->model::{{name}}, true); + ${{var_name}}_list = []; + foreach ($this->model::{{name}} as $key => $value) { + ${{var_name}}_list[] = ['value' => $key, 'label' => $value]; + } + $this->assign('{{var_name}}', ${{var_name}}_list, true); diff --git a/extend/base/admin/service/curd/templates/js/_common.code b/extend/base/admin/service/curd/templates/js/_common.code index a0f7405..1e45c83 100644 --- a/extend/base/admin/service/curd/templates/js/_common.code +++ b/extend/base/admin/service/curd/templates/js/_common.code @@ -4,7 +4,8 @@ var init = { indexUrl: '{{controllerUrl}}/index', addUrl: '{{controllerUrl}}/add' + location.search, editUrl: '{{controllerUrl}}/edit', + readUrl: '{{controllerUrl}}/read', deleteUrl: '{{controllerUrl}}/delete', exportUrl: '{{controllerUrl}}/export', modifyUrl: '{{controllerUrl}}/modify', -}; \ No newline at end of file +}; diff --git a/extend/base/admin/service/curd/templates/model/accessor.code b/extend/base/admin/service/curd/templates/model/accessor.code new file mode 100644 index 0000000..78b33fd --- /dev/null +++ b/extend/base/admin/service/curd/templates/model/accessor.code @@ -0,0 +1,12 @@ + /** + * {{comment}}获取器 + * @param $value + * @return array + */ + public function get{{accessorName}}Attr($value, $data) + { + if (empty($data['{{field}}'])) { + return []; + } + return explode('{{separator}}', $data['{{field}}']); + } diff --git a/extend/base/admin/service/curd/templates/model/model.code b/extend/base/admin/service/curd/templates/model/model.code index 31dd34c..ebe9836 100644 --- a/extend/base/admin/service/curd/templates/model/model.code +++ b/extend/base/admin/service/curd/templates/model/model.code @@ -15,7 +15,7 @@ class {{modelName}} extends TimeModel protected $deleteTime = {{deleteTime}}; {{selectList}} - + {{accessorList}} {{relationList}} -} \ No newline at end of file +} diff --git a/extend/base/admin/service/curd/templates/view/module/readDate.code b/extend/base/admin/service/curd/templates/view/module/readDate.code new file mode 100644 index 0000000..be95fba --- /dev/null +++ b/extend/base/admin/service/curd/templates/view/module/readDate.code @@ -0,0 +1,10 @@ +
+
{{comment}}
+
+ {notempty name="row.{{field}}"} + {$row.{{field}}|date="Y-m-d H:i:s"} + {else/} + 暂无数据 + {/notempty} +
+
diff --git a/extend/base/admin/service/curd/templates/view/module/readEditor.code b/extend/base/admin/service/curd/templates/view/module/readEditor.code new file mode 100644 index 0000000..3503ead --- /dev/null +++ b/extend/base/admin/service/curd/templates/view/module/readEditor.code @@ -0,0 +1,10 @@ +
+
{{comment}}
+
+ {notempty name="row.{{field}}"} + {$row.{{field}}|raw} + {else/} + 暂无内容 + {/notempty} +
+
diff --git a/extend/base/admin/service/curd/templates/view/module/readFile.code b/extend/base/admin/service/curd/templates/view/module/readFile.code new file mode 100644 index 0000000..c10eb68 --- /dev/null +++ b/extend/base/admin/service/curd/templates/view/module/readFile.code @@ -0,0 +1,13 @@ +
+
{{comment}}
+
+ {notempty name="row.{{field}}"} + + 下载文件 + +
{$row.{{field}}}
+ {else/} + 暂无文件 + {/notempty} +
+
diff --git a/extend/base/admin/service/curd/templates/view/module/readFiles.code b/extend/base/admin/service/curd/templates/view/module/readFiles.code new file mode 100644 index 0000000..e290164 --- /dev/null +++ b/extend/base/admin/service/curd/templates/view/module/readFiles.code @@ -0,0 +1,17 @@ +
+
{{comment}}
+
+ {notempty name="row.{{field}}_list"} + {volist name="row.{{field}}_list" id="file"} +
+ + 文件 {$key + 1} + + {$file} +
+ {/volist} + {else/} + 暂无文件 + {/notempty} +
+
diff --git a/extend/base/admin/service/curd/templates/view/module/readImage.code b/extend/base/admin/service/curd/templates/view/module/readImage.code new file mode 100644 index 0000000..aac69ed --- /dev/null +++ b/extend/base/admin/service/curd/templates/view/module/readImage.code @@ -0,0 +1,10 @@ +
+
{{comment}}
+
+ {notempty name="row.{{field}}"} + + {else/} + 暂无图片 + {/notempty} +
+
diff --git a/extend/base/admin/service/curd/templates/view/module/readImages.code b/extend/base/admin/service/curd/templates/view/module/readImages.code new file mode 100644 index 0000000..82df787 --- /dev/null +++ b/extend/base/admin/service/curd/templates/view/module/readImages.code @@ -0,0 +1,12 @@ +
+
{{comment}}
+
+ {notempty name="row.{{field}}_list"} + {volist name="row.{{field}}_list" id="img"} + + {/volist} + {else/} + 暂无图片 + {/notempty} +
+
diff --git a/extend/base/admin/service/curd/templates/view/module/readSelect.code b/extend/base/admin/service/curd/templates/view/module/readSelect.code new file mode 100644 index 0000000..e779548 --- /dev/null +++ b/extend/base/admin/service/curd/templates/view/module/readSelect.code @@ -0,0 +1,6 @@ +
+
{{comment}}
+
+ {{define}} +
+
diff --git a/extend/base/admin/service/curd/templates/view/module/readSwitch.code b/extend/base/admin/service/curd/templates/view/module/readSwitch.code new file mode 100644 index 0000000..e779548 --- /dev/null +++ b/extend/base/admin/service/curd/templates/view/module/readSwitch.code @@ -0,0 +1,6 @@ +
+
{{comment}}
+
+ {{define}} +
+
diff --git a/extend/base/admin/service/curd/templates/view/module/readText.code b/extend/base/admin/service/curd/templates/view/module/readText.code new file mode 100644 index 0000000..10c88b5 --- /dev/null +++ b/extend/base/admin/service/curd/templates/view/module/readText.code @@ -0,0 +1,10 @@ +
+
{{comment}}
+
+ {notempty name="row.{{field}}"} + {$row.{{field}}} + {else/} + 暂无数据 + {/notempty} +
+
diff --git a/extend/base/admin/service/curd/templates/view/module/readTextarea.code b/extend/base/admin/service/curd/templates/view/module/readTextarea.code new file mode 100644 index 0000000..5d4f7bd --- /dev/null +++ b/extend/base/admin/service/curd/templates/view/module/readTextarea.code @@ -0,0 +1,10 @@ +
+
{{comment}}
+
+ {notempty name="row.{{field}}"} + {$row.{{field}}|raw} + {else/} + 暂无内容 + {/notempty} +
+
From d5be4cbbaa88c158adb2837ce660586af516896f Mon Sep 17 00:00:00 2001 From: augushong Date: Fri, 9 Jan 2026 00:02:33 +0800 Subject: [PATCH 3/4] =?UTF-8?q?feat:=20=E5=AE=8C=E6=88=90=E5=9F=BA?= =?UTF-8?q?=E6=9C=AC=E7=9A=84=E8=AF=A6=E6=83=85=E7=94=9F=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/admin/controller/test/Goods.php | 24 ++++--------------- app/admin/model/TestGoods.php | 12 ++++++++++ app/admin/view/test/goods/read.html | 15 ++++++------ .../service/curd/BuildCurdServiceBase.php | 21 +++++++++++----- .../curd/templates/controller/select.code | 6 +---- .../service/curd/templates/view/read.code | 7 +++--- public/static/admin/css/public.css | 6 ++--- public/static/admin/css/public.scss | 6 ++--- 8 files changed, 46 insertions(+), 51 deletions(-) diff --git a/app/admin/controller/test/Goods.php b/app/admin/controller/test/Goods.php index 9d9a9eb..3601754 100644 --- a/app/admin/controller/test/Goods.php +++ b/app/admin/controller/test/Goods.php @@ -27,29 +27,13 @@ class Goods extends AdminController $this->model = new \app\admin\model\TestGoods(); - $select_list_status_list = []; - foreach ($this->model::SELECT_LIST_STATUS as $key => $value) { - $select_list_status_list[] = ['value' => $key, 'label' => $value]; - } - $this->assign('select_list_status', $select_list_status_list, true); + $this->assign('select_list_status', $this->model::SELECT_LIST_STATUS, true); - $select_list_time_status_list = []; - foreach ($this->model::SELECT_LIST_TIME_STATUS as $key => $value) { - $select_list_time_status_list[] = ['value' => $key, 'label' => $value]; - } - $this->assign('select_list_time_status', $select_list_time_status_list, true); + $this->assign('select_list_time_status', $this->model::SELECT_LIST_TIME_STATUS, true); - $select_list_is_recommend_list = []; - foreach ($this->model::SELECT_LIST_IS_RECOMMEND as $key => $value) { - $select_list_is_recommend_list[] = ['value' => $key, 'label' => $value]; - } - $this->assign('select_list_is_recommend', $select_list_is_recommend_list, true); + $this->assign('select_list_is_recommend', $this->model::SELECT_LIST_IS_RECOMMEND, true); - $select_list_shop_type_list = []; - foreach ($this->model::SELECT_LIST_SHOP_TYPE as $key => $value) { - $select_list_shop_type_list[] = ['value' => $key, 'label' => $value]; - } - $this->assign('select_list_shop_type', $select_list_shop_type_list, true); + $this->assign('select_list_shop_type', $this->model::SELECT_LIST_SHOP_TYPE, true); } diff --git a/app/admin/model/TestGoods.php b/app/admin/model/TestGoods.php index b7d911c..49b5126 100644 --- a/app/admin/model/TestGoods.php +++ b/app/admin/model/TestGoods.php @@ -73,6 +73,18 @@ class TestGoods extends TimeModel } return explode('|', $data['verfiy_file']); } + /** + * 商品类型获取器 + * @param $value + * @return array + */ + public function getShopTypeListAttr($value, $data) + { + if (empty($data['shop_type'])) { + return []; + } + return explode(',', $data['shop_type']); + } public function mallCate() diff --git a/app/admin/view/test/goods/read.html b/app/admin/view/test/goods/read.html index d0513e9..2d6a677 100644 --- a/app/admin/view/test/goods/read.html +++ b/app/admin/view/test/goods/read.html @@ -8,14 +8,13 @@
ID: {$row.id}
- - - + +
-
+
@@ -154,19 +153,19 @@
秒杀状态
- {volist name="select_list_time_status" id="vo"}{eq name="vo.value" value="$row.time_status"}{$vo.label}{/eq}{/volist} + {$select_list_time_status[$row.time_status]|default=''}
是否推荐
- {volist name="select_list_is_recommend" id="vo"}{eq name="vo.value" value="$row.is_recommend"}{volist name="select_list_is_recommend" id="item"}{eq name="item.value" value="$row.is_recommend"}{$item.label}{/eq}{/volist}{/eq}{/volist} + {$select_list_is_recommend[$row.is_recommend]|default=''}
商品类型
- {volist name="row.shop_type|explode=','" id="item">{volist name="select_list_shop_type" id="vo"}{eq name="vo.value" value="$item"}{$vo.label}{/eq}{/volist}{/volist} + {volist name="row.shop_type_list" id="item"}{$select_list_shop_type[$item]|default=''}{/volist}
@@ -273,7 +272,7 @@
状态
- {volist name="select_list_status" id="vo"}{eq name="vo.value" value="$row.status"}{volist name="select_list_status" id="item"}{eq name="item.value" value="$row.status"}{$item.label}{/eq}{/volist}{/eq}{/volist} + {$select_list_status[$row.status]|default=''}
diff --git a/extend/base/admin/service/curd/BuildCurdServiceBase.php b/extend/base/admin/service/curd/BuildCurdServiceBase.php index 7c1a79c..d63eea8 100644 --- a/extend/base/admin/service/curd/BuildCurdServiceBase.php +++ b/extend/base/admin/service/curd/BuildCurdServiceBase.php @@ -1213,8 +1213,16 @@ class BuildCurdServiceBase $selectList .= $this->buildSelectModel($field, $val['define']); } - // 为多图片和多文件字段生成获取器 - if (in_array($val['formType'], ['images', 'files'])) { + // 为多图片、多文件、多选字段生成获取器 + if (in_array($val['formType'], ['images', 'files', 'checkbox'])) { + // checkbox 使用逗号分隔,images/files 使用自定义分隔符 + if ($val['formType'] == 'checkbox') { + $val['define'] = ','; // 多选框固定使用逗号分隔 + } elseif ($val['formType'] == 'images' || $val['formType'] == 'files') { + if (!isset($val['define'])) { + $val['define'] = '|'; // 默认分隔符 + } + } $accessorList .= $this->buildAccessorModel($field, $val); } @@ -1873,15 +1881,16 @@ class BuildCurdServiceBase } elseif ($val['formType'] == 'radio' || $val['formType'] == 'switch') { $templateFile = "view{$this->DS}module{$this->DS}readSwitch"; if (isset($val['define']) && !empty($val['define'])) { - // 构建下拉选择的显示值 + // 使用 kv 格式直接获取值 $var_name = $this->getFieldVarName($field); - $define = '{volist name="' . $var_name . '" id="vo"}{eq name="vo.value" value="$row.' . $field . '"}{volist name="' . $var_name . '" id="item"}{eq name="item.value" value="$row.' . $field . '"}{$item.label}{/eq}{/volist}{/eq}{/volist}'; + $define = '{$' . $var_name . '[$row.' . $field . ']|default=\'\'}'; } } elseif ($val['formType'] == 'checkbox') { $templateFile = "view{$this->DS}module{$this->DS}readSelect"; if (isset($val['define']) && !empty($val['define'])) { $var_name = $this->getFieldVarName($field); - $define = '{volist name="row.' . $field . '|explode=\',\'" id="item">{volist name="' . $var_name . '" id="vo"}{eq name="vo.value" value="$item"}{$vo.label}{/eq}{/volist}{/volist}'; + // 使用获取器列表,如 shop_type_list + $define = '{volist name="row.' . $field . '_list" id="item"}{$' . $var_name . '[$item]|default=\'\'}{/volist}'; } } elseif ($val['formType'] == 'select') { $templateFile = "view{$this->DS}module{$this->DS}readSelect"; @@ -1889,7 +1898,7 @@ class BuildCurdServiceBase $define = '{$row.' . $field . '}'; } elseif (isset($val['define']) && !empty($val['define'])) { $var_name = $this->getFieldVarName($field); - $define = '{volist name="' . $var_name . '" id="vo"}{eq name="vo.value" value="$row.' . $field . '"}{$vo.label}{/eq}{/volist}'; + $define = '{$' . $var_name . '[$row.' . $field . ']|default=\'\'}'; } } elseif ($val['formType'] == 'relation') { // 关联表字段暂时使用文本显示 diff --git a/extend/base/admin/service/curd/templates/controller/select.code b/extend/base/admin/service/curd/templates/controller/select.code index 1387626..ac7ddda 100644 --- a/extend/base/admin/service/curd/templates/controller/select.code +++ b/extend/base/admin/service/curd/templates/controller/select.code @@ -1,6 +1,2 @@ - ${{var_name}}_list = []; - foreach ($this->model::{{name}} as $key => $value) { - ${{var_name}}_list[] = ['value' => $key, 'label' => $value]; - } - $this->assign('{{var_name}}', ${{var_name}}_list, true); + $this->assign('{{var_name}}', $this->model::{{name}}, true); diff --git a/extend/base/admin/service/curd/templates/view/read.code b/extend/base/admin/service/curd/templates/view/read.code index 1ce63aa..18e0e62 100644 --- a/extend/base/admin/service/curd/templates/view/read.code +++ b/extend/base/admin/service/curd/templates/view/read.code @@ -8,14 +8,13 @@
ID: {$row.id}
- - - + +
-
+
diff --git a/public/static/admin/css/public.css b/public/static/admin/css/public.css index 1aad26a..33a23ae 100644 --- a/public/static/admin/css/public.css +++ b/public/static/admin/css/public.css @@ -587,8 +587,7 @@ table样式 font-size: 16px; font-weight: bold; color: #333; - margin-bottom: 15px; - padding-bottom: 10px; + padding: 5px; border-bottom: 1px solid #e8e8e8; } @@ -599,8 +598,7 @@ table样式 /* 字段项样式 */ .detail-field-item { - margin-bottom: 15px; - padding-bottom: 15px; + padding: 5px; border-bottom: 1px solid #f0f0f0; overflow: hidden; } diff --git a/public/static/admin/css/public.scss b/public/static/admin/css/public.scss index 401dba3..bfa8629 100644 --- a/public/static/admin/css/public.scss +++ b/public/static/admin/css/public.scss @@ -593,8 +593,7 @@ table样式 font-size: 16px; font-weight: bold; color: #333; - margin-bottom: 15px; - padding-bottom: 10px; + padding: 5px; border-bottom: 1px solid #e8e8e8; } @@ -605,8 +604,7 @@ table样式 /* 字段项样式 */ .detail-field-item { - margin-bottom: 15px; - padding-bottom: 15px; + padding: 5px; border-bottom: 1px solid #f0f0f0; overflow: hidden; } From 4350e5f29454c4b13f5605ed35c0582d9001bd8b Mon Sep 17 00:00:00 2001 From: augushong Date: Fri, 9 Jan 2026 00:02:54 +0800 Subject: [PATCH 4/4] =?UTF-8?q?chore:=20=E5=88=A0=E9=99=A4=E6=B5=8B?= =?UTF-8?q?=E8=AF=95=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/admin/controller/test/Goods.php | 104 ---------- app/admin/model/TestGoods.php | 96 --------- app/admin/view/test/goods/_common.js | 11 - app/admin/view/test/goods/add.html | 200 ------------------ app/admin/view/test/goods/add.js | 3 - app/admin/view/test/goods/edit.html | 200 ------------------ app/admin/view/test/goods/edit.js | 3 - app/admin/view/test/goods/index.html | 13 -- app/admin/view/test/goods/index.js | 26 --- app/admin/view/test/goods/read.html | 295 --------------------------- app/admin/view/test/goods/read.js | 22 -- 11 files changed, 973 deletions(-) delete mode 100644 app/admin/controller/test/Goods.php delete mode 100644 app/admin/model/TestGoods.php delete mode 100644 app/admin/view/test/goods/_common.js delete mode 100644 app/admin/view/test/goods/add.html delete mode 100644 app/admin/view/test/goods/add.js delete mode 100644 app/admin/view/test/goods/edit.html delete mode 100644 app/admin/view/test/goods/edit.js delete mode 100644 app/admin/view/test/goods/index.html delete mode 100644 app/admin/view/test/goods/index.js delete mode 100644 app/admin/view/test/goods/read.html delete mode 100644 app/admin/view/test/goods/read.js diff --git a/app/admin/controller/test/Goods.php b/app/admin/controller/test/Goods.php deleted file mode 100644 index 3601754..0000000 --- a/app/admin/controller/test/Goods.php +++ /dev/null @@ -1,104 +0,0 @@ -model = new \app\admin\model\TestGoods(); - - $this->assign('select_list_status', $this->model::SELECT_LIST_STATUS, true); - - $this->assign('select_list_time_status', $this->model::SELECT_LIST_TIME_STATUS, true); - - $this->assign('select_list_is_recommend', $this->model::SELECT_LIST_IS_RECOMMEND, true); - - $this->assign('select_list_shop_type', $this->model::SELECT_LIST_SHOP_TYPE, true); - - } - - - /** - * @NodeAnotation(title="列表") - */ - public function index() - { - if ($this->request->isAjax()) { - if (input('selectFields')) { - return $this->selectList(); - } - list($page, $limit, $where) = $this->buildTableParames(); - $count = $this->model - ->withJoin(['mallCate'], 'LEFT') - ->where($where) - ->count(); - $list = $this->model - ->withJoin(['mallCate'], 'LEFT') - ->where($where) - ->page($page, $limit) - ->order($this->sort) - ->select(); - $data = [ - 'code' => 0, - 'msg' => '', - 'count' => $count, - 'data' => $list, - ]; - return json($data); - } - return $this->fetch(); - } - - - - /** - * @NodeAnotation(title="导出") - */ - public function export() - { - list($page, $limit, $where) = $this->buildTableParames(); - - - $this->model = $this->model->withJoin(['mallCate'], 'LEFT'); - - $fields = $this->request->param('fields', '{}', null); - $image_fields = $this->request->param('image_fields', '{}', null); - $select_fields = $this->request->param('select_fields', '{}', null); - $date_fields = $this->request->param('date_fields', '{}', null); - - $fields = json_decode($fields, true); - $image_fields = json_decode($image_fields, true); - $select_fields = json_decode($select_fields, true); - $date_fields = json_decode($date_fields, true); - - $content = \app\common\tools\ExportTools::excel($this->model, $where, $fields, $image_fields, $select_fields, $date_fields); - - $export_file_name = $this->exportFileName; - - if (empty($export_file_name)) { - $export_file_name = $this->model->getName(); - } - - return download($content, $export_file_name . date('YmdHis') . '.xlsx', true); - } -} \ No newline at end of file diff --git a/app/admin/model/TestGoods.php b/app/admin/model/TestGoods.php deleted file mode 100644 index 49b5126..0000000 --- a/app/admin/model/TestGoods.php +++ /dev/null @@ -1,96 +0,0 @@ - '正常', '1' => '禁用']; - - public const SELECT_LIST_TIME_STATUS = ['0' => '未参加', '1' => '已开始', '3' => '已结束']; - - public const SELECT_LIST_IS_RECOMMEND = ['0' => '不推荐', '1' => '推荐']; - - public const SELECT_LIST_SHOP_TYPE = ['taobao' => '淘宝', 'jd' => '京东']; - - /** - * 商品图片获取器 - * @param $value - * @return array - */ - public function getImagesListAttr($value, $data) - { - if (empty($data['images'])) { - return []; - } - return explode('|', $data['images']); - } - /** - * 检测报告获取器 - * @param $value - * @return array - */ - public function getVerfiyFileListAttr($value, $data) - { - if (empty($data['verfiy_file'])) { - return []; - } - return explode('|', $data['verfiy_file']); - } - /** - * 商品类型获取器 - * @param $value - * @return array - */ - public function getShopTypeListAttr($value, $data) - { - if (empty($data['shop_type'])) { - return []; - } - return explode(',', $data['shop_type']); - } - - - public function mallCate() - { - return $this->belongsTo('\app\admin\model\MallCate', 'cate_id', 'id'); - } - - -} diff --git a/app/admin/view/test/goods/_common.js b/app/admin/view/test/goods/_common.js deleted file mode 100644 index ae3225b..0000000 --- a/app/admin/view/test/goods/_common.js +++ /dev/null @@ -1,11 +0,0 @@ -var init = { - tableElem: '#currentTable', - tableRenderId: 'currentTableRenderId', - indexUrl: 'test.goods/index', - addUrl: 'test.goods/add' + location.search, - editUrl: 'test.goods/edit', - readUrl: 'test.goods/read', - deleteUrl: 'test.goods/delete', - exportUrl: 'test.goods/export', - modifyUrl: 'test.goods/modify', -}; diff --git a/app/admin/view/test/goods/add.html b/app/admin/view/test/goods/add.html deleted file mode 100644 index c034665..0000000 --- a/app/admin/view/test/goods/add.html +++ /dev/null @@ -1,200 +0,0 @@ -
-
- -
- -
-
- -
-
-
-
- -
- -
-
-
- -
- - -
-
-
- -
- - -
-
-
- -
- -
-
-
- -
- -
-
-
- -
- -
-
-
- -
- {foreach $select_list_status as $k=>$v} - - {/foreach} -
-
- -
- -
- - -
-
-
- -
- - -
-
-
- -
- -
-
-
- -
- -
-
-
- -
- -
-
-
- -
- -
-
-
- -
- -
-
-
- -
- {foreach $select_list_is_recommend as $k=>$v} - - {/foreach} -
-
- -
- -
- {foreach $select_list_shop_type as $k=>$v} - - {/foreach} -
-
- -
- -
-
- -
-
-
-
- -
-
- -
-
-
-
- -
- -
-
-
- -
- -
-
-
- -
-
-
-
-
- -
- -
-
-
- -
- -
-
-
- -
- -
-
-
-
- {notempty name='$Request.param.backTagId'} -
返回
- {/notempty} - - -
- -
-
\ No newline at end of file diff --git a/app/admin/view/test/goods/add.js b/app/admin/view/test/goods/add.js deleted file mode 100644 index 4a445e0..0000000 --- a/app/admin/view/test/goods/add.js +++ /dev/null @@ -1,3 +0,0 @@ -$(function(){ - ua.listen(); -}) \ No newline at end of file diff --git a/app/admin/view/test/goods/edit.html b/app/admin/view/test/goods/edit.html deleted file mode 100644 index 634c128..0000000 --- a/app/admin/view/test/goods/edit.html +++ /dev/null @@ -1,200 +0,0 @@ -
-
- -
- -
-
- -
-
-
-
- -
- -
-
-
- -
- - -
-
-
- -
- - -
-
-
- -
- -
-
-
- -
- -
-
-
- -
- -
-
-
- -
- {foreach $select_list_status as $k=>$v} - - {/foreach} -
-
- -
- -
- - -
-
-
- -
- - -
-
-
- -
- -
-
-
- -
- -
-
-
- -
- -
-
-
- -
- -
-
-
- -
- -
-
-
- -
- {foreach $select_list_is_recommend as $k=>$v} - - {/foreach} -
-
- -
- -
- {foreach $select_list_shop_type as $k=>$v} - - {/foreach} -
-
- -
- -
-
- -
-
-
-
- -
-
- -
-
-
-
- -
- -
-
-
- -
- -
-
-
- -
-
-
-
-
- -
- -
-
-
- -
- -
-
-
- -
- -
-
-
-
- {notempty name='$Request.param.backTagId'} -
返回
- {/notempty} - - -
- -
-
\ No newline at end of file diff --git a/app/admin/view/test/goods/edit.js b/app/admin/view/test/goods/edit.js deleted file mode 100644 index 4a445e0..0000000 --- a/app/admin/view/test/goods/edit.js +++ /dev/null @@ -1,3 +0,0 @@ -$(function(){ - ua.listen(); -}) \ No newline at end of file diff --git a/app/admin/view/test/goods/index.html b/app/admin/view/test/goods/index.html deleted file mode 100644 index 9e71a4f..0000000 --- a/app/admin/view/test/goods/index.html +++ /dev/null @@ -1,13 +0,0 @@ -
-
- -
-
-
\ No newline at end of file diff --git a/app/admin/view/test/goods/index.js b/app/admin/view/test/goods/index.js deleted file mode 100644 index 01c9dcc..0000000 --- a/app/admin/view/test/goods/index.js +++ /dev/null @@ -1,26 +0,0 @@ -$(function(){ - ua.table.render({ - init: init, - cols: [[ - {type: 'checkbox'}, {field: 'id', title: 'id'}, {field: 'cate_id', title: '分类ID'}, {field: 'title', title: '商品名称'}, {field: 'logo', title: '商品logo', templet: ua.table.image}, {field: 'total_stock', title: '总库存'}, {field: 'sort', title: '排序', edit: 'text'}, {field: 'status', search: 'select', selectList: ua.getDataBrage('select_list_status'), title: '状态', templet: ua.table.switch}, {field: 'cert_file', title: '合格证', templet: ua.table.url}, {field: 'remark', title: '备注说明', templet: ua.table.text}, {field: 'create_time', title: 'create_time'}, {field: 'publish_time', title: '发布日期'}, {field: 'sale_time', title: '售卖日期'}, {field: 'intro', title: '简介'}, {field: 'time_status', search: 'select', selectList: ua.getDataBrage('select_list_time_status'), title: '秒杀状态'}, {field: 'is_recommend', search: 'select', selectList: ua.getDataBrage('select_list_is_recommend'), title: '是否推荐'}, {field: 'shop_type', search: 'select', selectList: ua.getDataBrage('select_list_shop_type'), title: '商品类型'}, {field: 'from_area', title: '产地'}, {field: 'store_city', title: '仓库'}, {field: 'tag_input', title: '商品标签 (输入)'}, {field: 'uid', title: '唯一id'}, {field: 'price', title: '价格'}, {field: 'detail', title: '详情'}, {field: 'mallCate.id', title: ''}, {field: 'mallCate.title', title: '分类名'}, {field: 'mallCate.image', title: '分类图片', templet: ua.table.image}, {field: 'mallCate.sort', title: '排序', edit: 'text'}, {field: 'mallCate.status', title: '状态', templet: ua.table.switch}, {field: 'mallCate.remark', title: '备注说明', templet: ua.table.text}, {field: 'mallCate.create_time', title: '创建时间'}, { - width: 250, title: '操作', templet: ua.table.tool, fixed: 'right', operat: [ - [{ - class: 'layui-btn layui-btn-primary layui-btn-xs', - method: 'tab', - field: 'id', - text: '详情', - title: '查看详情', - auth: 'read', - url: init.readUrl, - icon: '' - }], - 'edit', - 'delete' - ] - }, - - ]], - }); - - ua.listen(); -}) \ No newline at end of file diff --git a/app/admin/view/test/goods/read.html b/app/admin/view/test/goods/read.html deleted file mode 100644 index 2d6a677..0000000 --- a/app/admin/view/test/goods/read.html +++ /dev/null @@ -1,295 +0,0 @@ -
-
-
-
-
-
-

#{$row.id} {$title}

-
ID: {$row.id}
-
-
- - -
-
-
-
-
- -
-
-
-
分类ID
-
- {notempty name="row.cate_id"} - {$row.cate_id} - {else/} - 暂无数据 - {/notempty} -
-
-
-
商品名称
-
- {notempty name="row.title"} - {$row.title} - {else/} - 暂无数据 - {/notempty} -
-
-
-
商品logo
-
- {notempty name="row.logo"} - - {else/} - 暂无图片 - {/notempty} -
-
-
-
商品图片
-
- {notempty name="row.images_list"} - {volist name="row.images_list" id="img"} - - {/volist} - {else/} - 暂无图片 - {/notempty} -
-
-
-
商品描述
-
- {notempty name="row.describe"} - {$row.describe|raw} - {else/} - 暂无内容 - {/notempty} -
-
-
-
总库存
-
- {notempty name="row.total_stock"} - {$row.total_stock} - {else/} - 暂无数据 - {/notempty} -
-
-
-
合格证
-
- {notempty name="row.cert_file"} - - 下载文件 - -
{$row.cert_file}
- {else/} - 暂无文件 - {/notempty} -
-
-
-
检测报告
-
- {notempty name="row.verfiy_file_list"} - {volist name="row.verfiy_file_list" id="file"} - - {/volist} - {else/} - 暂无文件 - {/notempty} -
-
-
-
备注说明
-
- {notempty name="row.remark"} - {$row.remark|raw} - {else/} - 暂无内容 - {/notempty} -
-
-
-
发布日期
-
- {notempty name="row.publish_time"} - {$row.publish_time|date="Y-m-d H:i:s"} - {else/} - 暂无数据 - {/notempty} -
-
-
-
售卖日期
-
- {notempty name="row.sale_time"} - {$row.sale_time|date="Y-m-d H:i:s"} - {else/} - 暂无数据 - {/notempty} -
-
-
-
简介
-
- {notempty name="row.intro"} - {$row.intro|raw} - {else/} - 暂无内容 - {/notempty} -
-
-
-
秒杀状态
-
- {$select_list_time_status[$row.time_status]|default=''} -
-
-
-
是否推荐
-
- {$select_list_is_recommend[$row.is_recommend]|default=''} -
-
-
-
商品类型
-
- {volist name="row.shop_type_list" id="item"}{$select_list_shop_type[$item]|default=''}{/volist} -
-
-
-
商品标签
-
- {notempty name="row.tag"} - {$row.tag} - {else/} - 暂无数据 - {/notempty} -
-
-
-
商品标签(单选)
-
- {notempty name="row.tag_backup"} - {$row.tag_backup} - {else/} - 暂无数据 - {/notempty} -
-
-
-
产地
-
- {notempty name="row.from_area"} - {$row.from_area} - {else/} - 暂无数据 - {/notempty} -
-
-
-
仓库
-
- {notempty name="row.store_city"} - {$row.store_city} - {else/} - 暂无数据 - {/notempty} -
-
-
-
商品标签 (输入)
-
- {notempty name="row.tag_input"} - {$row.tag_input} - {else/} - 暂无数据 - {/notempty} -
-
-
-
唯一id
-
- {notempty name="row.uid"} - {$row.uid} - {else/} - 暂无数据 - {/notempty} -
-
-
-
价格
-
- {notempty name="row.price"} - {$row.price} - {else/} - 暂无数据 - {/notempty} -
-
-
-
详情
-
- {notempty name="row.detail"} - {$row.detail} - {else/} - 暂无数据 - {/notempty} -
-
- -
-
- -
-

基础信息

-
-
-
ID
-
{$row.id}
-
-
-
排序
-
- {notempty name="row.sort"} - {$row.sort} - {else/} - 暂无数据 - {/notempty} -
-
-
-
状态
-
- {$select_list_status[$row.status]|default=''} -
-
-
-
create_time
-
- {notempty name="row.create_time"} - {$row.create_time} - {else/} - 暂无数据 - {/notempty} -
-
- -
-
-
-
-
-
-
\ No newline at end of file diff --git a/app/admin/view/test/goods/read.js b/app/admin/view/test/goods/read.js deleted file mode 100644 index f5671a7..0000000 --- a/app/admin/view/test/goods/read.js +++ /dev/null @@ -1,22 +0,0 @@ -$(function(){ - // 删除数据 - window.deleteData = function(id) { - layer.confirm('确定要删除这条数据吗?', { - icon: 3, - title: '提示' - }, function(index) { - $.post('{{:url("delete")}}', {id: id}, function(res) { - if (res.code == 0) { - layer.msg('删除成功', {icon: 1}, function() { - location.href = '{{:url("index")}}'; - }); - } else { - layer.msg(res.msg, {icon: 2}); - } - }, 'json'); - layer.close(index); - }); - }; - - ua.listen(); -}) \ No newline at end of file