commit a5029a2be78dd5306d99f176626eb0493f1e1aed Author: Jerry Yan <792602257@qq.com> Date: Thu Nov 21 16:40:44 2024 +0800 1 diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..f61bb03 --- /dev/null +++ b/.env.example @@ -0,0 +1,22 @@ +# 数据配置 +DB_TYPE=mysql +DB_MYSQL_HOST=thinkadmin.top +DB_MYSQL_PORT=3306 +DB_MYSQL_PREFIX= +DB_MYSQL_DATABASE=admin_v6 +DB_MYSQL_USERNAME=root +DB_MYSQL_PASSWORD= + +# 缓存配置 +CACHE_TYPE=file +CACHE_REDIS_HOST=127.0.0.1 +CACHE_REDIS_PORT=6379 +CACHE_REDIS_SELECT= +CACHE_REDIS_PASSWORD= + +# 会话配置 +SESSION_NAME=ssid +SESSION_TYPE=file +SESSION_STORE= +SESSION_EXPIRE=7200 +SESSION_PREFIX= \ No newline at end of file diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..fc8b101 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,3 @@ +*.js linguist-language=php +*.css linguist-language=php +*.html linguist-language=php \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a0c9754 --- /dev/null +++ b/.gitignore @@ -0,0 +1,50 @@ +.env +.git +.svn +.idea +.fleet +.vscode +.DS_Store + +/vendor +/runtime +/safefile +/nbproject +/composer.lock +!composer.json + +### 屏蔽环境文件 +/404.html +/.user.ini +/index.html +/public/upload +/public/404.html +/public/.htaccess +/public/.user.ini +/public/index.html +/public/favicon.ico +/database/sqlite.db + +### 屏蔽插件文件 +/app/admin +/app/wechat + +### 屏蔽配置文件 +/config/app.php +/config/cookie.php +/config/lang.php +/config/log.php +/config/route.php +/config/session.php +/config/view.php + +/public/static/plugs +/public/static/theme +/public/static/admin.js +/public/static/login.js + +### 屏蔽数据库脚本 +/database/migrations/*_install_*.php +/database/migrations/*_upgrade_*.php +!database/migrations/*_install_table.php +!database/migrations/*_install_package.php diff --git a/app/index/controller/Index.php b/app/index/controller/Index.php new file mode 100644 index 0000000..2f5fbf7 --- /dev/null +++ b/app/index/controller/Index.php @@ -0,0 +1,27 @@ +redirect(sysuri('admin/login/index')); + } +} diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..d28b2f1 --- /dev/null +++ b/composer.json @@ -0,0 +1,53 @@ +{ + "type": "project", + "name": "jerryyan/guangan", + "version": "0.0.1", + "license": "MIT", + "description": "Application Development Framework", + "keywords": [ + "ThinkAdmin", + "ThinkLibrary", + "WeChatDeveloper" + ], + "authors": [ + { + "name": "Anyon", + "email": "zoujingli@qq.com" + } + ], + "config": { + "allow-plugins": { + "zoujingli/think-install": true + } + }, + "require": { + "php": ">=7.1", + "jerryyan/think-plugs-cms": "@dev", + "jerryyan/think-plugs-points-mall": "@dev", + "jerryyan/think-plugs-ticket": "@dev", + "zoujingli/think-plugs-admin": "^1.0", + "zoujingli/think-plugs-wechat": "^1.0", + "zoujingli/think-plugs-center": "^1.0", + "zoujingli/think-plugs-account": "^1.0", + "ext-json": "*" + }, + "repositories": { + "jerryyan/think-plugs-cms": { + "type": "path", + "url": "./plugs/think-plugs-cms" + }, + "jerryyan/think-plugs-points-mall": { + "type": "path", + "url": "./plugs/think-plugs-points-mall" + }, + "jerryyan/think-plugs-ticket": { + "type": "path", + "url": "./plugs/think-plugs-ticket" + } + }, + "autoload": { + "psr-4": { + "app\\": "app" + } + } +} diff --git a/config/cache.php b/config/cache.php new file mode 100644 index 0000000..25d927a --- /dev/null +++ b/config/cache.php @@ -0,0 +1,51 @@ + 'file', + // 缓存连接配置 + 'stores' => [ + 'file' => [ + // 驱动方式 + 'type' => 'File', + // 缓存保存目录 + 'path' => '', + // 缓存名称前缀 + 'prefix' => '', + // 缓存有效期 0 表示永久缓存 + 'expire' => 0, + // 缓存标签前缀 + 'tag_prefix' => 'tag:', + // 序列化机制 + 'serialize' => [], + ], + 'safe' => [ + // 驱动方式 + 'type' => 'File', + // 缓存保存目录 + 'path' => syspath('safefile/cache/'), + // 缓存名称前缀 + 'prefix' => '', + // 缓存有效期 0 表示永久缓存 + 'expire' => 0, + // 缓存标签前缀 + 'tag_prefix' => 'tag:', + // 序列化机制 + 'serialize' => [], + ], + ], +]; \ No newline at end of file diff --git a/config/database.php b/config/database.php new file mode 100644 index 0000000..ca3f736 --- /dev/null +++ b/config/database.php @@ -0,0 +1,82 @@ + 'mysql', + // 自定义时间查询规则 + 'time_query_rule' => [], + // 自动写入时间戳字段 + 'auto_timestamp' => true, + // 时间字段取出后的默认时间格式 + 'datetime_format' => 'Y-m-d H:i:s', + // 数据库连接配置信息 + 'connections' => [ + 'mysql' => [ + // 数据库类型 + 'type' => 'mysql', + // 服务器地址 + 'hostname' => 'database.jerryyan.net', + // 数据库名 + 'database' => 'guangan', + // 用户名 + 'username' => 'guangan', + // 密码 + 'password' => 'guangan123', + // 端口 + 'hostport' => '33306', + // 数据库连接参数 + 'params' => [], + // 数据库编码默认采用 utf8 + 'charset' => 'utf8mb4', + // 数据库表前缀 + 'prefix' => '', + // 数据库部署方式:0 集中式(单一服务器),1 分布式(主从服务器) + 'deploy' => 0, + // 数据库读写是否分离 主从式有效 + 'rw_separate' => false, + // 读写分离后 主服务器数量 + 'master_num' => 1, + // 指定从服务器序号 + 'slave_no' => '', + // 检查字段是否存在 + 'fields_strict' => true, + // 是否需要断线重连 + 'break_reconnect' => false, + // 监听SQL执行日志 + 'trigger_sql' => true, + // 开启字段类型缓存 + 'fields_cache' => isOnline(), + ], + 'sqlite' => [ + 'charset' => 'utf8', + // 数据库类型 + 'type' => 'sqlite', + // 数据库文件 + 'database' => syspath('database/sqlite.db'), + // 监听执行日志 + 'trigger_sql' => true, + // 其他参数字段 + 'deploy' => 0, + 'suffix' => '', + 'prefix' => '', + 'hostname' => '', + 'hostport' => '', + 'username' => '', + 'password' => '', + ], + ], +]; diff --git a/config/phinx.php b/config/phinx.php new file mode 100644 index 0000000..a9ee866 --- /dev/null +++ b/config/phinx.php @@ -0,0 +1,24 @@ + [], + // 创建数据表,填写表名 + 'tables' => [], + // 备份数据表,填写表名 + 'backup' => [], +]; \ No newline at end of file diff --git a/license b/license new file mode 100644 index 0000000..66b2d00 --- /dev/null +++ b/license @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2014-2023 Anyon + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/plugin.md b/plugin.md new file mode 100644 index 0000000..e186a3f --- /dev/null +++ b/plugin.md @@ -0,0 +1,135 @@ +# 插件生态 + +》》》 更多插件正在开发,敬请期待…… 《《《 + +目前插件更新比较频繁,如果有发现 **bug**,请尝试升级最新版本。 + +如果问题依旧,请到 [Gitee](https://gitee.com/zoujingli/ThinkAdmin/issues) 提交问题,提交的内容中需要标注插件名称及问题详情,最好附加环境版本信息。 + +使用现有插件前请务必认真阅读每个插件的介绍,如果需要开发自己的插件请查看 [插件开发](https://thinkadmin.top/system/plugin-register.html) 章节。 + +通常情况下,使用 **admin** 及 **wechat** 两个插件就可以完成系统定制开发,且这两个插件都是遵循 **MIT** 协议开源,不影响商业授权。 + +## 免费开源插件 + +> 后台基础 Admin 管理插件( 已稳定可用 ) +> +> * 插件标识:`admin` +> * 插件包名:`zoujingli/think-plugs-admin` +> * 安装方式:`composer require zoujingli/think-plugs-admin` +> * 插件仓库:[https://gitee.com/zoujingli/think-plugs-admin](https://gitee.com/zoujingli/think-plugs-admin) +> * 文档地址:[查看文档](https://thinkadmin.top/plugin/think-plugs-admin.html) +> * 开源协议:[MIT](https://mit-license.org) ( 免费开源,支持本地插件化定制 ) + +> 后台基础 WeChat 微信插件( 已稳定可用 ) +> * 插件标识:`wechat` +> * 插件包名:`zoujingli/think-plugs-wechat` +> * 安装方式:`composer require zoujingli/think-plugs-wechat` +> * 插件仓库:[https://gitee.com/zoujingli/think-plugs-wechat](https://gitee.com/zoujingli/think-plugs-wechat) +> * 文档地址:[查看文档](https://thinkadmin.top/plugin/think-plugs-wechat.html) +> * 开源协议:[MIT](https://mit-license.org) ( 免费开源,支持本地插件化定制 ) + +> 后台静态 Static 初始化插件 ( 通常不需要独立安装 ) +> * 插件标识:`static` +> * 插件包名:`zoujingli/think-plugs-static` +> * 安装方式:`composer require zoujingli/think-plugs-static` +> * 插件仓库:[https://gitee.com/zoujingli/think-plugs-static](https://gitee.com/zoujingli/think-plugs-static) +> * 开源协议:[MIT](https://mit-license.org) ( 免费开源,部分插件包含其他开源协议,具体可以查看源文件,不支持本地插件化定制 ) + +> 基础插件市场系统 ( 开发中,后期开放 ThinkAdmin 生态市场 ) +> * 插件标识:`plugin-center` +> * 插件包名:`zoujingli/think-plugs-center` +> * 安装方式:`composer require zoujingli/think-plugs-center` +> * 插件仓库:[https://gitee.com/zoujingli/think-plugs-center](https://gitee.com/zoujingli/think-plugs-center) +> * 文档地址:[查看文档](https://thinkadmin.top/plugin/think-plugs-center.html) +> * 开源协议:[Apache2](https://www.apache.org/licenses/LICENSE-2.0) ( 免费开源,建议保留版权注释,支持本地插件化定制 ) + +> 基础插件市场系统 ( 已稳定可用,建议使用 plugin-center ) +> * 插件标识:`plugin-center-simple` +> * 插件包名:`zoujingli/think-plugs-center-simple` +> * 安装方式:`composer require zoujingli/think-plugs-center-simple` +> * 插件仓库:[https://gitee.com/zoujingli/think-plugs-center-simple](https://gitee.com/zoujingli/think-plugs-center-simple) +> * 文档地址:[查看文档](https://thinkadmin.top/plugin/think-plugs-center-simple.html) +> * 开源协议:[Apache2](https://www.apache.org/licenses/LICENSE-2.0) ( 免费开源,建议保留版权注释,支持本地插件化定制 ) + +> 基于 Workerman 的 网络服务插件 ( 已稳定可用 ) +> * 插件标识:`plugin-worker` +> * 插件包名:`zoujingli/think-plugs-worker` +> * 安装方式:`composer require zoujingli/think-plugs-worker` +> * 插件仓库:[https://gitee.com/zoujingli/think-plugs-worker](https://gitee.com/zoujingli/think-plugs-worker) +> * 文档地址:[查看文档](https://thinkadmin.top/plugin/think-plugs-worker.html) +> * 开源协议:[Apache2](https://www.apache.org/licenses/LICENSE-2.0) ( 免费开源,建议保留版权注释,支持本地插件化定制 ) + +## 会员尊享插件 + +> 多端用户账号系统 ( 已稳定可用 ) +> * 插件标识:`plugin-account` +> * 插件包名:`zoujingli/think-plugs-account` +> * 安装方式:`composer require zoujingli/think-plugs-account` +> * 插件仓库:[https://gitee.com/zoujingli/think-plugs-account](https://gitee.com/zoujingli/think-plugs-account) +> * 文档地址:[查看文档](https://thinkadmin.top/plugin/think-plugs-account.html) +> * 授权协议:[VIP授权](https://thinkadmin.top/vip-introduce.html) ( 非VIP用户仅可用于学习,不得商用,支持本地插件化定制 ) + +> 多端支付管理系统 ( 已稳定可用 ) +> * 插件标识:`plugin-payment` +> * 插件包名:`zoujingli/think-plugs-payment` +> * 安装方式:`composer require zoujingli/think-plugs-payment` +> * 插件仓库:[https://gitee.com/zoujingli/think-plugs-payment](https://gitee.com/zoujingli/think-plugs-payment) +> * 文档地址:[查看文档](https://thinkadmin.top/plugin/think-plugs-payment.html) +> * 授权协议:[VIP授权](https://thinkadmin.top/vip-introduce.html) ( 非VIP用户仅可用于学习,不得商用,支持本地插件化定制 ) + +> 多端微商城系统 ( 已稳定可用 ) +> * 插件标识:`plugin-wemall` +> * 插件包名:`zoujingli/think-plugs-wemall` +> * 安装方式:`composer require zoujingli/think-plugs-wemall` +> * 插件仓库:[https://gitee.com/zoujingli/think-plugs-wemall](https://gitee.com/zoujingli/think-plugs-wemall) +> * 文档地址:[查看文档](https://thinkadmin.top/plugin/think-plugs-wemall.html) +> * 授权协议:[VIP授权](https://thinkadmin.top/vip-introduce.html) ( 非VIP用户仅可用于学习,不得商用,支持本地插件化定制 ) + +> 微信开放平台基础插件( 已稳定可用 ) +> * 插件标识:`plugin-wechat-service` +> * 插件包名:`zoujingli/think-plugs-wechat-service` +> * 安装方式:`composer require zoujingli/think-plugs-wechat-service` +> * 插件仓库:[https://gitee.com/zoujingli/think-plugs-wechat-service](https://gitee.com/zoujingli/think-plugs-wechat-service) +> * 文档地址:[查看文档](https://thinkadmin.top/plugin/think-plugs-wechat-service.html) +> * 授权协议:[VIP授权](https://thinkadmin.top/vip-introduce.html) ( 非VIP用户仅可用于学习,不得商用,支持本地插件化定制 ) + +## 收费授权插件 + +> 一物一码溯源系统 ( 开发中,还未发布 ) +> * 插件标识:`plugin-wuma` +> * 插件包名:`zoujingli/think-plugs-wuma` +> * 安装方式:`composer require zoujingli/think-plugs-wuma` +> * 插件仓库:[https://gitee.com/zoujingli/think-plugs-wuma](https://gitee.com/zoujingli/think-plugs-wuma) +> * 文档地址:[查看文档](https://thinkadmin.top/plugin/think-plugs-wuma.html) +> * 授权协议:[收费授权](https://thinkadmin.top/fee-introduce.html) ( 未获得授权仅可用于学习,不得商用,支持本地插件化定制 ) + +## 案例安装体验 + +如果需要本地化定制开发,请参考[插件本地化定制](https://thinkadmin.top/system/plugin-developer.html)文档 + +```shell +# 创建项目 +composer create-project zoujingli/thinkadmin + +# 进入项目目录 +cd thinkadmin + +# 安装微信插件 +composer require zoujingli/think-plugs-wechat + +# 安装插件管理中心 +composer require zoujingli/think-plugs-center + +# 安装多端账号管理 +composer require zoujingli/think-plugs-account + +# 安装多端支付管理 +composer require zoujingli/think-plugs-payment + +# 安装多端商城管理 +composer require zoujingli/think-plugs-wemall + +# 启动 WEB 内置服务 +php think run --host 127.0.0.1 +``` \ No newline at end of file diff --git a/plugs/think-plugs-cms/composer.json b/plugs/think-plugs-cms/composer.json new file mode 100644 index 0000000..91e61ea --- /dev/null +++ b/plugs/think-plugs-cms/composer.json @@ -0,0 +1,41 @@ +{ + "type": "think-admin-plugin", + "name": "jerryyan/think-plugs-cms", + "license": "WTFPL", + "homepage": "https://thinkadmin.top", + "description": "CMS Plugin for ThinkAdmin", + "authors": [ + { + "name": "Jerry Yan", + "email": "jerryyan0912@qq.com" + } + ], + "require": { + "php": ">7.1" + }, + "autoload": { + "psr-4": { + "plugin\\cms\\": "src" + } + }, + "extra": { + "config": { + "type": "module", + "name": "新闻资讯", + "document": "https://thinkadmin.top/plugin/think-plugs-wechat.html", + "description": "新闻资讯" + }, + "think": { + "services": [ + "plugin\\cms\\Service" + ] + } + }, + "minimum-stability": "dev", + "config": { + "sort-packages": true, + "allow-plugins": { + "zoujingli/think-install": true + } + } +} diff --git a/plugs/think-plugs-cms/src/Service.php b/plugs/think-plugs-cms/src/Service.php new file mode 100644 index 0000000..79dbe17 --- /dev/null +++ b/plugs/think-plugs-cms/src/Service.php @@ -0,0 +1,36 @@ + '是', + '0' => '否' + ]); + } + + public static function menu(): array + { + $code = app(static::class)->appCode; + return [ + [ + 'name' => '文章管理', + 'subs' => [ + ['name' => '文章分类', 'icon' => 'layui-icon layui-icon-template-1', 'node' => "{$code}/category/index"], + ['name' => '文章列表', 'icon' => 'layui-icon layui-icon-template-1', 'node' => "{$code}/article/index"], + ['name' => '轮播图列表', 'icon' => 'layui-icon layui-icon-template-1', 'node' => "{$code}/banner/index"], + ] + ] + ]; + } +} \ No newline at end of file diff --git a/plugs/think-plugs-cms/src/controller/Article.php b/plugs/think-plugs-cms/src/controller/Article.php new file mode 100644 index 0000000..14f0d1f --- /dev/null +++ b/plugs/think-plugs-cms/src/controller/Article.php @@ -0,0 +1,143 @@ +title = '文章管理'; + CmsArticle::mQuery()->layTable(function () { + }, static function (QueryHelper $query) { + $query->where('is_deleted', 0); + $query->with(['category']); + $query->equal('status')->like('title'); + $query->timeBetween('create_at'); + }); + } + + public function _index_page_filter(&$list) + { + foreach ($list as &$item) { + $cate_list = $item['category']; + $item['cate_name'] = join(',', array_column($cate_list, 'name')); + } + } + + /** + * 添加文章 + * @auth true + * @menu true + * @login true + * @return void + */ + public function add() + { + $this->title = '添加文章'; + $this->cates = CmsCategory::getList(); + $this->cate_ids = []; + CmsArticle::mForm('form'); + } + + /** + * 编辑文章 + * @auth true + * @menu true + * @login true + * @return void + */ + public function edit() + { + $this->title = '编辑文章'; + $this->cates = CmsCategory::getList(); + $this->id = $this->request->param('id'); + $this->cate_ids = CmsCateArticle::where(['aid' => $this->id])->column('cid'); + CmsArticle::mForm('form', "id"); + } + + public function _form_filter(&$data) + { + unset($data['cate_ids']); + } + + public function _form_result($state, $data) + { + if (isset($data['id'])) { + CmsCateArticle::where(['aid' => $data['id']])->delete(); + $cate_ids = $this->request->param('cate_ids', []); + foreach ($cate_ids as $cid) { + CmsCateArticle::create(['aid' => $data['id'], 'cid' => $cid]); + } + } + } + + /** + * 删除文章 + * @auth true + * @menu true + * @login true + * @return void + */ + public function remove() + { + CmsArticle::mDelete('id'); + } + + /** + * 修改文章状态 + * @auth true + * @menu true + * @login true + * @return void + */ + public function status() + { + CmsArticle::mSave($this->_vali([ + 'id.require' => '文章ID不能为空', + 'status.in:0,1' => '状态值范围异常!', + 'status.require' => '状态值不能为空!', + ]), 'id'); + } + + public function _status_save_result($state, $data) + { + if ($state) { + $status = $this->request->param('status'); + $id = $this->request->param('id'); + if ($status == 1) { + CmsArticle::mk()->where('id', $id)->save([ + 'publish_at' => date('Y-m-d H:i:s') + ]); + } + } + } + + public function sort() + { + CmsArticle::mSave($this->_vali([ + 'id.require' => '文章ID不能为空', + 'sort.require' => '排序值不能为空!', + 'sort.number' => '排序必须为数字!', + 'sort.between:0,9999' => '排序值必须为0~9999之间!', + ]), 'id'); + } +} \ No newline at end of file diff --git a/plugs/think-plugs-cms/src/controller/Banner.php b/plugs/think-plugs-cms/src/controller/Banner.php new file mode 100644 index 0000000..a3c4f67 --- /dev/null +++ b/plugs/think-plugs-cms/src/controller/Banner.php @@ -0,0 +1,97 @@ +title = '轮播图管理'; + CmsBanner::mQuery()->layTable(function () { + }, static function (QueryHelper $query) { + $query->equal('status')->like('title'); + $query->timeBetween('create_at'); + }); + } + + /** + * 添加轮播图 + * @auth true + * @menu true + * @login true + * @return void + */ + public function add() + { + $this->title = '添加栏目'; + $this->_applyFormToken(); + CmsBanner::mForm('form'); + } + + /** + * 编辑轮播图 + * @auth true + * @menu true + * @login true + * @return void + */ + public function edit() + { + $this->title = '编辑栏目'; + $this->id = $this->request->param('id', 0, 'intval'); //当前栏目ID + $this->_applyFormToken(); + CmsBanner::mForm('form'); + } + + /** + * 删除轮播图 + * @auth true + * @menu true + * @login true + * @return void + */ + public function remove() + { + CmsBanner::mDelete('id'); + } + + /** + * 状态切换 + * @auth true + * @menu true + * @login true + * @return void + */ + public function status() + { + CmsBanner::mSave($this->_vali([ + 'id.require' => '栏目ID不能为空', + 'status.in:0,1' => '状态值范围异常!', + 'status.require' => '状态值不能为空!', + ]), 'id'); + } + + public function sort() + { + CmsBanner::mSave($this->_vali([ + 'id.require' => '栏目ID不能为空', + 'sort.require' => '排序值不能为空!', + 'sort.number' => '排序必须为数字!', + 'sort.between:0,9999' => '排序值必须为0~9999之间!', + ]), 'id'); + } +} \ No newline at end of file diff --git a/plugs/think-plugs-cms/src/controller/Category.php b/plugs/think-plugs-cms/src/controller/Category.php new file mode 100644 index 0000000..72d9bb6 --- /dev/null +++ b/plugs/think-plugs-cms/src/controller/Category.php @@ -0,0 +1,111 @@ +title = '栏目列表'; + CmsCategory::mQuery()->layTable(function () { + }, static function (QueryHelper $query) { + $query->equal('status')->like('name'); + }); + } + + /** + * 添加栏目 + * @auth true + * @menu true + * @login true + * @return void + */ + public function add() + { + $this->title = '添加栏目'; + $this->_applyFormToken(); + CmsCategory::mForm('form'); + } + + /** + * 编辑栏目 + * @auth true + * @menu true + * @login true + * @return void + */ + public function edit() + { + $this->title = '编辑栏目'; + $this->id = $this->request->param('id', 0, 'intval'); //当前栏目ID + $this->_applyFormToken(); + CmsCategory::mForm('form'); + } + + /** + * 删除栏目 + * @auth true + * @menu true + * @login true + * @return void + */ + public function remove() + { + CmsCategory::mDelete('id'); + } + + public function _delete_filter() + { + $id = $this->request->post('id'); + $children_count = CmsCategory::where('pid', $id)->count(); + if ($children_count > 0) { + $this->error("该栏目下有子栏目,不能删除!"); + } + $articles_count = CmsCateArticle::where('cid', $id)->count(); + if ($articles_count > 0) { + $this->error("该栏目下有文章,不能删除!"); + } + return true; + } + + /** + * 状态切换 + * @auth true + * @menu true + * @login true + * @return void + */ + public function status() + { + CmsCategory::mSave($this->_vali([ + 'id.require' => '栏目ID不能为空', + 'status.in:0,1' => '状态值范围异常!', + 'status.require' => '状态值不能为空!', + ]), 'id'); + } + + public function sort() + { + CmsCategory::mSave($this->_vali([ + 'id.require' => '栏目ID不能为空', + 'sort.require' => '排序值不能为空!', + 'sort.number' => '排序必须为数字!', + 'sort.between:0,9999' => '排序值必须为0~9999之间!', + ]), 'id'); + } +} \ No newline at end of file diff --git a/plugs/think-plugs-cms/src/controller/Index.php b/plugs/think-plugs-cms/src/controller/Index.php new file mode 100644 index 0000000..2d7e9bc --- /dev/null +++ b/plugs/think-plugs-cms/src/controller/Index.php @@ -0,0 +1,12 @@ +request->get('cid'); + $query = CmsArticle::mk()->where('status', 1); + if (is_numeric($categoryId)) { + $query->hasWhere('cateids', function ($subQuery) use ($categoryId) { + $subQuery->where('cid', $categoryId); + }); + } + $articles = $query->field('id,title,thumb,author,from,view_count,publish_at')->order('sort asc,id desc')->paginate(); + $this->success('获取文章列表', $articles); + } + + public function info() { + $id = $this->request->get('id'); + CmsArticle::mk()->where('id', $id)->inc('view_count'); + $article = CmsArticle::mk()->where('id', $id)->find(); + if (empty($article)) { + $this->error('文章不存在'); + } + $this->success('获取文章详情', $article); + } +} \ No newline at end of file diff --git a/plugs/think-plugs-cms/src/controller/api/Banner.php b/plugs/think-plugs-cms/src/controller/api/Banner.php new file mode 100644 index 0000000..b7fdf4a --- /dev/null +++ b/plugs/think-plugs-cms/src/controller/api/Banner.php @@ -0,0 +1,14 @@ +where('status', '=', 1)->field("id, image")->order('sort asc,id desc')->select(); + $this->success('获取轮播图列表', $banners); + } +} \ No newline at end of file diff --git a/plugs/think-plugs-cms/src/controller/api/Category.php b/plugs/think-plugs-cms/src/controller/api/Category.php new file mode 100644 index 0000000..2e937a9 --- /dev/null +++ b/plugs/think-plugs-cms/src/controller/api/Category.php @@ -0,0 +1,14 @@ +where('status', 1)->order('sort asc,id desc')->field("id, name")->select(); + $this->success('获取分类成功', $categories); + } +} \ No newline at end of file diff --git a/plugs/think-plugs-cms/src/model/CmsArticle.php b/plugs/think-plugs-cms/src/model/CmsArticle.php new file mode 100644 index 0000000..49de9ff --- /dev/null +++ b/plugs/think-plugs-cms/src/model/CmsArticle.php @@ -0,0 +1,24 @@ +belongsToMany(CmsCategory::class, CmsCateArticle::class, + 'cid', 'aid'); + } + + public function cateids() + { + return $this->hasMany(CmsCateArticle::class, 'aid'); + } + + public function getCateIdsAttr() + { + return $this->cateids->column('cid'); + } +} \ No newline at end of file diff --git a/plugs/think-plugs-cms/src/model/CmsBanner.php b/plugs/think-plugs-cms/src/model/CmsBanner.php new file mode 100644 index 0000000..ecb9203 --- /dev/null +++ b/plugs/think-plugs-cms/src/model/CmsBanner.php @@ -0,0 +1,10 @@ +belongsTo('CmsCategory', 'cid', 'id'); + } + public function article() + { + return $this->belongsTo('CmsArtical', 'aid', 'id'); + } +} \ No newline at end of file diff --git a/plugs/think-plugs-cms/src/model/CmsCategory.php b/plugs/think-plugs-cms/src/model/CmsCategory.php new file mode 100644 index 0000000..03720c5 --- /dev/null +++ b/plugs/think-plugs-cms/src/model/CmsCategory.php @@ -0,0 +1,29 @@ +order('sort asc')->field('id,name')->where('status', 1)->select()->toArray(); + } + + public function articles() + { + return $this->hasManyThrough(CmsArticle::class, CmsCateArticle::class, + 'cid', 'id', 'id', 'aid'); + } + + public function children() + { + return $this->hasMany(CmsCategory::class, 'pid', 'id'); + } + + public function parent() + { + return $this->belongsTo(CmsCategory::class, 'pid', 'id'); + } +} \ No newline at end of file diff --git a/plugs/think-plugs-cms/src/view/article/form.html b/plugs/think-plugs-cms/src/view/article/form.html new file mode 100644 index 0000000..121e1e2 --- /dev/null +++ b/plugs/think-plugs-cms/src/view/article/form.html @@ -0,0 +1,88 @@ +
+
+
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+
+
+ +
+ + + image +
+
+
+ +
+ {foreach $cates as $cate} + + {/foreach} +
+
+
+ +
+ +
+
+
+ {notempty name='id'}{/notempty} +
+ + +
+
+ diff --git a/plugs/think-plugs-cms/src/view/article/index.html b/plugs/think-plugs-cms/src/view/article/index.html new file mode 100644 index 0000000..af1d865 --- /dev/null +++ b/plugs/think-plugs-cms/src/view/article/index.html @@ -0,0 +1,108 @@ +{extend name="table"} + +{block name="button"} + + + +{/block} + +{block name="content"} +
+
+
+
+ {include file='article/index_search'} +
+
+
+
+
+ +{/block} + +{block name='style'} + +{/block} + +{block name='script'} + +{/block} \ No newline at end of file diff --git a/plugs/think-plugs-cms/src/view/article/index_search.html b/plugs/think-plugs-cms/src/view/article/index_search.html new file mode 100644 index 0000000..634793a --- /dev/null +++ b/plugs/think-plugs-cms/src/view/article/index_search.html @@ -0,0 +1,23 @@ +
+ 条件搜索 + + +
diff --git a/plugs/think-plugs-cms/src/view/banner/form.html b/plugs/think-plugs-cms/src/view/banner/form.html new file mode 100644 index 0000000..a4cf4d7 --- /dev/null +++ b/plugs/think-plugs-cms/src/view/banner/form.html @@ -0,0 +1,33 @@ +
+
+
+ +
+ +
仅用于后台展示
+
+
+
+ +
+ +
建议尺寸:750*300
+
+
+
+ {notempty name='id'}{/notempty} +
+ + +
+
+ diff --git a/plugs/think-plugs-cms/src/view/banner/index.html b/plugs/think-plugs-cms/src/view/banner/index.html new file mode 100644 index 0000000..280589d --- /dev/null +++ b/plugs/think-plugs-cms/src/view/banner/index.html @@ -0,0 +1,87 @@ +{extend name="table"} + +{block name="button"} + + + +{/block} + +{block name="content"} +
+
+ {include file='banner/index_search'} +
+
+
+ + + +{/block} + +{block name='style'} + +{/block} + +{block name='script'} + +{/block} \ No newline at end of file diff --git a/plugs/think-plugs-cms/src/view/banner/index_search.html b/plugs/think-plugs-cms/src/view/banner/index_search.html new file mode 100644 index 0000000..e547414 --- /dev/null +++ b/plugs/think-plugs-cms/src/view/banner/index_search.html @@ -0,0 +1,16 @@ +
+ 条件搜索 + + +
diff --git a/plugs/think-plugs-cms/src/view/category/form.html b/plugs/think-plugs-cms/src/view/category/form.html new file mode 100644 index 0000000..abe7dd6 --- /dev/null +++ b/plugs/think-plugs-cms/src/view/category/form.html @@ -0,0 +1,99 @@ +
+
+
+ + +
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+ +
+
+
+ {foreach $_YES_OR_NO as $k=>$v} + + + + + + {/foreach} +
+ +
+
+
+
+
+ {notempty name='vo.id'}{/notempty} +
+ + +
+
+
+ + + diff --git a/plugs/think-plugs-cms/src/view/category/index.html b/plugs/think-plugs-cms/src/view/category/index.html new file mode 100644 index 0000000..e9495bc --- /dev/null +++ b/plugs/think-plugs-cms/src/view/category/index.html @@ -0,0 +1,84 @@ +{extend name="table"} + +{block name="button"} + + + +{/block} + +{block name="content"} +
+
+ {include file='category/index_search'} +
+
+
+ + +{/block} + +{block name='style'} + +{/block} + +{block name='script'} + +{/block} \ No newline at end of file diff --git a/plugs/think-plugs-cms/src/view/category/index_search.html b/plugs/think-plugs-cms/src/view/category/index_search.html new file mode 100644 index 0000000..ba5bed8 --- /dev/null +++ b/plugs/think-plugs-cms/src/view/category/index_search.html @@ -0,0 +1,16 @@ +
+ 条件搜索 + + +
diff --git a/plugs/think-plugs-cms/src/view/main.html b/plugs/think-plugs-cms/src/view/main.html new file mode 100644 index 0000000..2ff0f5e --- /dev/null +++ b/plugs/think-plugs-cms/src/view/main.html @@ -0,0 +1,11 @@ +
+ {block name='style'}{/block} + {notempty name='title'} +
+ {$title|default=''} +
{block name='button'}{/block}
+
+ {/notempty} +
{block name='content'}{/block}
+ {block name='script'}{/block} +
\ No newline at end of file diff --git a/plugs/think-plugs-cms/src/view/table.html b/plugs/think-plugs-cms/src/view/table.html new file mode 100644 index 0000000..290b1b6 --- /dev/null +++ b/plugs/think-plugs-cms/src/view/table.html @@ -0,0 +1,23 @@ +
+ {block name='style'}{/block} + {block name='header'} + {notempty name='title'} +
+ {$title|lang} +
{block name='button'}{/block}
+
+ {/notempty} + {/block} +
+
+
+ {notempty name='showErrorMessage'} +
+ 系统提示:{$showErrorMessage|raw} +
+ {/notempty} + {block name='content'}{/block} +
+
+ {block name='script'}{/block} +
\ No newline at end of file diff --git a/plugs/think-plugs-points-mall/composer.json b/plugs/think-plugs-points-mall/composer.json new file mode 100644 index 0000000..106be4d --- /dev/null +++ b/plugs/think-plugs-points-mall/composer.json @@ -0,0 +1,41 @@ +{ + "type": "think-admin-plugin", + "name": "jerryyan/think-plugs-points-mall", + "license": "WTFPL", + "homepage": "https://thinkadmin.top", + "description": "Points Mall Plugin for ThinkAdmin", + "authors": [ + { + "name": "Jerry Yan", + "email": "jerryyan0912@qq.com" + } + ], + "require": { + "php": ">7.1" + }, + "autoload": { + "psr-4": { + "plugin\\points_mall\\": "src" + } + }, + "extra": { + "config": { + "type": "module", + "name": "积分商城", + "document": "https://thinkadmin.top/plugin/think-plugs-wechat.html", + "description": "积分商城" + }, + "think": { + "services": [ + "plugin\\points_mall\\Service" + ] + } + }, + "minimum-stability": "dev", + "config": { + "sort-packages": true, + "allow-plugins": { + "zoujingli/think-install": true + } + } +} diff --git a/plugs/think-plugs-points-mall/src/Service.php b/plugs/think-plugs-points-mall/src/Service.php new file mode 100644 index 0000000..65a27b2 --- /dev/null +++ b/plugs/think-plugs-points-mall/src/Service.php @@ -0,0 +1,36 @@ + '是', + '0' => '否' + ]); + } + + public static function menu(): array + { + $code = app(static::class)->appCode; + return [ + [ + 'name' => '积分商城', + 'subs' => [ + ['name' => '商品管理', 'icon' => 'layui-icon layui-icon-template-1', 'node' => "{$code}/goods/index"], + ['name' => '订单管理', 'icon' => 'layui-icon layui-icon-template-1', 'node' => "{$code}/order/index"], + ['name' => '用户积分', 'icon' => 'layui-icon layui-icon-template-1', 'node' => "{$code}/point/index"], + ] + ] + ]; + } +} \ No newline at end of file diff --git a/plugs/think-plugs-points-mall/src/controller/Goods.php b/plugs/think-plugs-points-mall/src/controller/Goods.php new file mode 100644 index 0000000..0b90465 --- /dev/null +++ b/plugs/think-plugs-points-mall/src/controller/Goods.php @@ -0,0 +1,22 @@ +title = '商品管理'; + } +} \ No newline at end of file diff --git a/plugs/think-plugs-points-mall/src/controller/Point.php b/plugs/think-plugs-points-mall/src/controller/Point.php new file mode 100644 index 0000000..2b8949b --- /dev/null +++ b/plugs/think-plugs-points-mall/src/controller/Point.php @@ -0,0 +1,22 @@ +checkUserStatus(false); + } catch (HttpResponseException $exception) { + throw $exception; + } catch (\Exception $exception) { + $this->error($exception->getMessage()); + } + } +} \ No newline at end of file diff --git a/plugs/think-plugs-points-mall/src/controller/api/auth/UserPoint.php b/plugs/think-plugs-points-mall/src/controller/api/auth/UserPoint.php new file mode 100644 index 0000000..46b39ff --- /dev/null +++ b/plugs/think-plugs-points-mall/src/controller/api/auth/UserPoint.php @@ -0,0 +1,22 @@ +usid); + $this->success('获取用户积分', [ + 'point' => $point + ]); + } + + public function myPointLog() { + $page = PointsMallUserPointLog::mk()->where('uid', $this->usid)->order('create_at desc')->paginate(); + $this->success('获取积分记录', $page); + } +} \ No newline at end of file diff --git a/plugs/think-plugs-points-mall/src/model/PointsMallUserPoint.php b/plugs/think-plugs-points-mall/src/model/PointsMallUserPoint.php new file mode 100644 index 0000000..e8b1cfd --- /dev/null +++ b/plugs/think-plugs-points-mall/src/model/PointsMallUserPoint.php @@ -0,0 +1,21 @@ +hasMany(PointsMallUserPointLog::class, 'uid'); + } + + public function user() + { + return $this->belongsTo(PluginAccountBind::class, 'uid'); + } +} \ No newline at end of file diff --git a/plugs/think-plugs-points-mall/src/model/PointsMallUserPointLog.php b/plugs/think-plugs-points-mall/src/model/PointsMallUserPointLog.php new file mode 100644 index 0000000..b61b271 --- /dev/null +++ b/plugs/think-plugs-points-mall/src/model/PointsMallUserPointLog.php @@ -0,0 +1,10 @@ +where('uid', $uid)->value('point'); + if ($point === null) { + $point = 0; + PointsMallUserPoint::mk()->save(['uid' => $uid, 'point' => $point]); + } + return $point; + } + + public static function addUserPoint($uid, $point, $reason) + { + $userPoint = PointsMallUserPoint::mk()->where('uid', $uid)->find(); + if (empty($userPoint)) { + $userPoint = PointsMallUserPoint::mk()->create(['uid' => $uid, 'point' => 0]); + } + $userPoint->startTrans(); + $userPoint->inc('point', $point); + $userPoint->log()->save([ + 'point' => $point, + 'reason' => $reason, + ]); + $userPoint->save(); + $userPoint->commit(); + } +} \ No newline at end of file diff --git a/plugs/think-plugs-points-mall/src/view/main.html b/plugs/think-plugs-points-mall/src/view/main.html new file mode 100644 index 0000000..2ff0f5e --- /dev/null +++ b/plugs/think-plugs-points-mall/src/view/main.html @@ -0,0 +1,11 @@ +
+ {block name='style'}{/block} + {notempty name='title'} +
+ {$title|default=''} +
{block name='button'}{/block}
+
+ {/notempty} +
{block name='content'}{/block}
+ {block name='script'}{/block} +
\ No newline at end of file diff --git a/plugs/think-plugs-points-mall/src/view/table.html b/plugs/think-plugs-points-mall/src/view/table.html new file mode 100644 index 0000000..290b1b6 --- /dev/null +++ b/plugs/think-plugs-points-mall/src/view/table.html @@ -0,0 +1,23 @@ +
+ {block name='style'}{/block} + {block name='header'} + {notempty name='title'} +
+ {$title|lang} +
{block name='button'}{/block}
+
+ {/notempty} + {/block} +
+
+
+ {notempty name='showErrorMessage'} +
+ 系统提示:{$showErrorMessage|raw} +
+ {/notempty} + {block name='content'}{/block} +
+
+ {block name='script'}{/block} +
\ No newline at end of file diff --git a/plugs/think-plugs-ticket/composer.json b/plugs/think-plugs-ticket/composer.json new file mode 100644 index 0000000..02e9c77 --- /dev/null +++ b/plugs/think-plugs-ticket/composer.json @@ -0,0 +1,41 @@ +{ + "type": "think-admin-plugin", + "name": "jerryyan/think-plugs-ticket", + "license": "WTFPL", + "homepage": "https://thinkadmin.top", + "description": "Ticket Plugin for ThinkAdmin", + "authors": [ + { + "name": "Jerry Yan", + "email": "jerryyan0912@qq.com" + } + ], + "require": { + "php": ">7.1" + }, + "autoload": { + "psr-4": { + "plugin\\ticket\\": "src" + } + }, + "extra": { + "config": { + "type": "module", + "name": "工单管理", + "document": "https://thinkadmin.top/plugin/think-plugs-wechat.html", + "description": "工单管理" + }, + "think": { + "services": [ + "plugin\\ticket\\Service" + ] + } + }, + "minimum-stability": "dev", + "config": { + "sort-packages": true, + "allow-plugins": { + "zoujingli/think-install": true + } + } +} diff --git a/plugs/think-plugs-ticket/src/Service.php b/plugs/think-plugs-ticket/src/Service.php new file mode 100644 index 0000000..8549b45 --- /dev/null +++ b/plugs/think-plugs-ticket/src/Service.php @@ -0,0 +1,30 @@ +appCode; + return [ + [ + 'name' => '工单管理', + 'subs' => [ + ['name' => '工单列表', 'icon' => 'layui-icon layui-icon-template-1', 'node' => "{$code}/ticket/index"], + ['name' => '工单分类', 'icon' => 'layui-icon layui-icon-template-1', 'node' => "{$code}/type/index"], + ] + ] + ]; + } +} \ No newline at end of file diff --git a/plugs/think-plugs-ticket/src/controller/Ticket.php b/plugs/think-plugs-ticket/src/controller/Ticket.php new file mode 100644 index 0000000..cc95daf --- /dev/null +++ b/plugs/think-plugs-ticket/src/controller/Ticket.php @@ -0,0 +1,130 @@ +title = '工单中心'; + $this->type_list = TicketType::getList(); + $this->user_id = $this->request->session('user')['id']; + TicketTicket::mQuery()->layTable(function () { + + }, function (QueryHelper $query) { + $query->like(['title|content|contact_name|ticket_address|contact_phone#keyword']) + ->dateBetween(['create_at', 'last_activity_at']) + ->equal(['status', 'type_id']); + $query->with(['user'])->append(['imgs_arr', 'status_text', 'type_name', 'last_reply']); + }); + } + + /** + * 添加工单 + * @auth true + * @menu true + * @return void + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function add() + { + $this->title = '添加工单'; + $this->types = TicketType::mk()->scope('active')->select(); + TicketTicket::mForm('form'); + } + + public function _form_filter(&$data) + { + if ($this->request->isPost()) { + $data['uid'] = 0; + } + $data['status'] = 0; + } + + /** + * 查看工单 + * @auth true + * @menu true + * @return void + */ + public function detail() + { + $this->title = '工单详情'; + ['id' => $id] = $this->_vali(['id.require' => '请指定工单ID!']); + $this->vo = TicketTicket::mk()->with(['user', 'type', 'reply'])->append(['imgs_arr', 'status_text', 'type_name', 'last_reply'])->find($id); + $this->fetch(); + } + + /** + * 编辑工单 + * @auth true + * @menu true + * @return void + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function edit() + { + $this->title = '编辑工单'; + $this->types = TicketType::mk()->scope('active')->select(); + TicketTicket::mForm('form'); + } + + /** + * 删除工单 + * @auth true + * @menu true + * @return void + */ + public function remove() + { + TicketTicket::mDelete(); + } + + public function reply() + { + $this->title = '回复工单'; + [ + 'ticket_id'=>$ticket_id, + 'id'=>$id + ] = $this->_vali([ + 'ticket_id.require'=>'请指定工单ID!', + 'id.require'=>'请指定回复ID!' + ]); + $this->vo = TicketTicket::mk()->with(['user', 'type'])->append(['imgs_arr', 'status_text', 'type_name'])->find($ticket_id); + TicketReply::mForm('reply'); + } + + public function _reply_form_filter(&$data) + { + if ($this->request->isPost()) { + $this->_applyFormToken(); + $data['type'] = 1; + $adminInfo = $this->request->session('user'); + $data['user_id'] = $adminInfo['id']; + $data['username'] = $adminInfo['nickname']; + $data['contact'] = $adminInfo['contact_phone']; + } + } +} \ No newline at end of file diff --git a/plugs/think-plugs-ticket/src/controller/Type.php b/plugs/think-plugs-ticket/src/controller/Type.php new file mode 100644 index 0000000..14808f9 --- /dev/null +++ b/plugs/think-plugs-ticket/src/controller/Type.php @@ -0,0 +1,90 @@ +title = '工单类型'; + TicketType::mQuery()->layTable(function () { + + }, function (QueryHelper $query) { + $query->withCount(['tickets']); + $query->like(['name'])->equal(['status']); + }); + } + + /** + * 添加工单类型 + * @return void + */ + public function add() + { + TicketType::mForm('form'); + } + + /** + * 编辑工单类型 + * @return void + */ + public function edit() + { + TicketType::mForm('form'); + } + + /** + * 修改工单类型状态 + * @return void + */ + public function status() + { + TicketType::mSave($this->_vali([ + 'id.require' => '类型ID不能为空', + 'status.in:0,1' => '状态值范围异常!', + 'status.require' => '状态值不能为空!', + ]), 'id'); + } + + /** + * 修改工单类型排序 + * @return void + */ + public function sort() + { + TicketType::mSave($this->_vali([ + 'id.require' => '文章ID不能为空', + 'sort.require' => '排序值不能为空!', + 'sort.number' => '排序必须为数字!', + 'sort.between:0,9999' => '排序值必须为0~9999之间!', + ]), 'id'); + } + /** + * 删除工单类型 + * @return void + */ + public function remove() + { + ['id' => $id] = $this->_vali(['id.require' => '请指定工单类型ID!']); + $count = TicketTicket::mk()->scope('avail')->where('type_id', '=', $id)->count(); + if ($count > 0) { + $this->error('工单类型删除失败,请先删除该类型下的工单!'); + } + TicketType::mDelete(); + } +} \ No newline at end of file diff --git a/plugs/think-plugs-ticket/src/model/TicketReply.php b/plugs/think-plugs-ticket/src/model/TicketReply.php new file mode 100644 index 0000000..ce0ea44 --- /dev/null +++ b/plugs/think-plugs-ticket/src/model/TicketReply.php @@ -0,0 +1,31 @@ +belongsTo(TicketTicket::class, 'ticket_id'); + } + + public function user() + { + return $this->belongsTo(SystemUser::class, 'user_id'); + } + + public function getTypeNameAttr($value, $data) + { + switch ($data['type']) { + case 0: return '流转'; + case 1: return '回复'; + case 9: return '退回'; + default: return '其他'; + } + } + +} \ No newline at end of file diff --git a/plugs/think-plugs-ticket/src/model/TicketTicket.php b/plugs/think-plugs-ticket/src/model/TicketTicket.php new file mode 100644 index 0000000..98e7eb9 --- /dev/null +++ b/plugs/think-plugs-ticket/src/model/TicketTicket.php @@ -0,0 +1,68 @@ +belongsTo(TicketType::class, 'type_id'); + } + + public function user() + { + return $this->belongsTo(PluginAccountBind::class, 'uid'); + } + + public function reply() + { + return $this->hasMany(TicketReply::class, 'ticket_id')->order("create_at", 'asc'); + } + + public function getImgsArrAttr($value, $data) + { + return str2arr($data['imgs'] ?: '', '|'); + } + + public function getLastReplyAttr($value, $data) + { + return $this->reply()->order('create_at', 'desc')->find(); + } + + public function getTypeNameAttr($value, $data) + { + $type = $this->type()->find(); + if (!empty($type)) { + return $type['name']; + } else { + return '未知'; + } + } + + public function getStatusTextAttr($value, $data) + { + if (!empty($this->getStatusList()[$data['status']])) { + return $this->getStatusList()[$data['status']]; + } else { + return '未知'; + } + } + + private function getStatusList() + { + return [ + -1 => '已关闭', + 0 => '待处理', + 1 => '已作处理', + ]; + } + + public function scopeAvail($query) + { + return $query->where('status', '>=', '0'); + } +} \ No newline at end of file diff --git a/plugs/think-plugs-ticket/src/model/TicketType.php b/plugs/think-plugs-ticket/src/model/TicketType.php new file mode 100644 index 0000000..a3c9cd1 --- /dev/null +++ b/plugs/think-plugs-ticket/src/model/TicketType.php @@ -0,0 +1,23 @@ +scope('active')->order('sort', 'asc')->field('name, id')->select(); + } + public function tickets() + { + return $this->hasMany(TicketTicket::class, 'type_id'); + } + + public function scopeActive($query) + { + return $query->where('status', '=', '1'); + } + +} \ No newline at end of file diff --git a/plugs/think-plugs-ticket/src/view/main.html b/plugs/think-plugs-ticket/src/view/main.html new file mode 100644 index 0000000..2ff0f5e --- /dev/null +++ b/plugs/think-plugs-ticket/src/view/main.html @@ -0,0 +1,11 @@ +
+ {block name='style'}{/block} + {notempty name='title'} +
+ {$title|default=''} +
{block name='button'}{/block}
+
+ {/notempty} +
{block name='content'}{/block}
+ {block name='script'}{/block} +
\ No newline at end of file diff --git a/plugs/think-plugs-ticket/src/view/table.html b/plugs/think-plugs-ticket/src/view/table.html new file mode 100644 index 0000000..290b1b6 --- /dev/null +++ b/plugs/think-plugs-ticket/src/view/table.html @@ -0,0 +1,23 @@ +
+ {block name='style'}{/block} + {block name='header'} + {notempty name='title'} +
+ {$title|lang} +
{block name='button'}{/block}
+
+ {/notempty} + {/block} +
+
+
+ {notempty name='showErrorMessage'} +
+ 系统提示:{$showErrorMessage|raw} +
+ {/notempty} + {block name='content'}{/block} +
+
+ {block name='script'}{/block} +
\ No newline at end of file diff --git a/plugs/think-plugs-ticket/src/view/ticket/detail.html b/plugs/think-plugs-ticket/src/view/ticket/detail.html new file mode 100644 index 0000000..6abddab --- /dev/null +++ b/plugs/think-plugs-ticket/src/view/ticket/detail.html @@ -0,0 +1,65 @@ +
+
工单内容
+
+
+ 工单编号:{$vo.id|default=""} +
+
+ 工单标题:{$vo.title|default=""} +
+
+ 反馈人信息:{$vo.contact_name|default="未填写名称"}, + 联系方式:{$vo.contact_phone|default="未填写联系方式"}, + 联系地址:{$vo.contact_address|default="未填写地址"} +
+
+ 工单类型:{$vo.type_name|default=""} +
+
+ 工单地址:{$vo.ticket_address|default=""} +
+
+ 工单内容:{$vo.content|default=""} +
+
+ 工单图片: +
+ {foreach $vo.imgs_arr as $img} + image +   + {/foreach} +
+
+
+
+
+
工单流转详情
+
+ + + + + + + + + + + {notempty name='vo.reply'} + {foreach $vo.reply as $reply} + + + + + + + {/foreach} + {else} + + + + {/notempty} + +
工单处理人处理类型工单处理时间处理内容
{$reply.username|default=""}{$reply.type_name|default=""}{$reply.create_at|default=""}{$reply.content|default=""}
暂无工单流转记录
+
+
\ No newline at end of file diff --git a/plugs/think-plugs-ticket/src/view/ticket/form.html b/plugs/think-plugs-ticket/src/view/ticket/form.html new file mode 100644 index 0000000..22f6be5 --- /dev/null +++ b/plugs/think-plugs-ticket/src/view/ticket/form.html @@ -0,0 +1,44 @@ +
+

+ 原则上不允许私自创建或修改工单!!! +

+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+ +
+ +
+ +
+
+
+ {notempty name='id'}{/notempty} +
+ + +
+
+ diff --git a/plugs/think-plugs-ticket/src/view/ticket/index.html b/plugs/think-plugs-ticket/src/view/ticket/index.html new file mode 100644 index 0000000..d314bc0 --- /dev/null +++ b/plugs/think-plugs-ticket/src/view/ticket/index.html @@ -0,0 +1,85 @@ +{extend name="table"} + +{block name="button"} + + + +{/block} + +{block name="content"} +
+
+
+
+ {include file='ticket/index_search'} +
+
+
+
+
+ +{/block} + +{block name='style'} + +{/block} + +{block name='script'} + +{/block} \ No newline at end of file diff --git a/plugs/think-plugs-ticket/src/view/ticket/index_search.html b/plugs/think-plugs-ticket/src/view/ticket/index_search.html new file mode 100644 index 0000000..648cafb --- /dev/null +++ b/plugs/think-plugs-ticket/src/view/ticket/index_search.html @@ -0,0 +1,50 @@ +
+ 条件搜索 + + +
diff --git a/plugs/think-plugs-ticket/src/view/ticket/reply.html b/plugs/think-plugs-ticket/src/view/ticket/reply.html new file mode 100644 index 0000000..03e62e3 --- /dev/null +++ b/plugs/think-plugs-ticket/src/view/ticket/reply.html @@ -0,0 +1,43 @@ +
+ + + +
+ +
+ +
此回复对外可见,请认真回复。
+
+
+
+ +
+ +
此图片对外可见,请认真回复。
+
+
+
+
+ +
+ +
此回复仅系统内部可见。
+
+
+
+ +
+ +
此图片仅系统内部可见。
+
+
+
+ + +
+
+ +{include file="ticket/detail"} \ No newline at end of file diff --git a/plugs/think-plugs-ticket/src/view/type/form.html b/plugs/think-plugs-ticket/src/view/type/form.html new file mode 100644 index 0000000..7946f86 --- /dev/null +++ b/plugs/think-plugs-ticket/src/view/type/form.html @@ -0,0 +1,63 @@ +
+
+
+
+ +
+ +
+
+
+
+ {notempty name='vo.id'}{/notempty} +
+ + +
+
+
+ + + diff --git a/plugs/think-plugs-ticket/src/view/type/index.html b/plugs/think-plugs-ticket/src/view/type/index.html new file mode 100644 index 0000000..cb4d604 --- /dev/null +++ b/plugs/think-plugs-ticket/src/view/type/index.html @@ -0,0 +1,83 @@ +{extend name="table"} + +{block name="button"} + + + +{/block} + +{block name="content"} +
+
+ {include file='type/index_search'} +
+
+
+ + +{/block} + +{block name='style'} + +{/block} + +{block name='script'} + +{/block} \ No newline at end of file diff --git a/plugs/think-plugs-ticket/src/view/type/index_search.html b/plugs/think-plugs-ticket/src/view/type/index_search.html new file mode 100644 index 0000000..ba5bed8 --- /dev/null +++ b/plugs/think-plugs-ticket/src/view/type/index_search.html @@ -0,0 +1,16 @@ +
+ 条件搜索 + + +
diff --git a/public/index.php b/public/index.php new file mode 100644 index 0000000..7bc9d30 --- /dev/null +++ b/public/index.php @@ -0,0 +1,23 @@ + **A. 测试或体验环境** +> +> 系统默认使用`Sqlite`数据库,不需要配置任何参数,特别要注意使用`Sqlite` +> 数据库时是没有密码的,容易造成数据丢失或泄露。执行上面的安装操作初始化并安装系统依赖组件, +> 并自动安装数据库并初始化数据;执行`php think run`启动系统内置的`WEB`服务,用浏览器访问 +> `http://127.0.0.1:8000`进入后台登录界面后,使用系统默认的账号`admin`和密码`admin`登录管理后台;也可以使用其他`Web` +> 服务软件方案实现。 + +> **B. 开发或线上环境** +> +> 执行上面的安装操作初始化并安装系统依赖组件,通过数据库管理工具创建空数据库,并将数据库参数配置到`config/database.php`; +> 然后执行`php think migrate:run`完成数据库初始化安装;线上环境还需要安装`Nginx`或`Apache`等`Web`服务 ( +> 推荐使用[宝塔](https://www.bt.cn/?invite_code=MV90a3Z6dmI=)集成环境 ),并按照`ThinkPHP6`系统要求配置网站参数。 + +## 数据管理 + +> **A. 注意事项** +> +> 数据库是使用 `Phinx` 工具管理的,在未配置数据库时默认使用 `Sqlite`,数据库文件位于 `database/sqlite.db`,使用 `Sqlite` +> 数据库时仅限用于体验与测试,建议不要用于生产环境,生产环境建议使用开源免费的 `MySQL` 数据库; + +> **B. 数据库初始化安装** +> +> 使用 `MySql`, `SqlServer`, `Postgres` 等服务型数据库时,需要先创建空的数据库并将参数配置到 `config/database.php` +> ,然后执行 `composer update` 或 `php think migrate:run` +> 安装并初始化数据库;开发部署系统时,如果要对数据库添加数据表或修改数据表,可以直接修改数据库或创建 `Phinx` +> 脚本后执行 `php think migrate:run` 进行数据库更新升级。另外系统提供 `php think xadmin:package` 指令可以把现有 `MySQl` +> 数据库打包为 `Phinx` 脚本,迁移系统时只需要执行前面的安装步骤即可。 + +## 注解权限 + +注解权限是指通过方法注释来实现后台 RBAC 授权管理,用注解来管理功能节点。 + +开发人员只需要写好注释,RBAC 的节点会自动生成,只需要配置角色及用户就可以使用RBAC权限。 + +* 此版本的权限使用注解实现 +* 注释必须标准的块注释,如下案例 +* 其中`@auth true`表示访问需要权限验证 +* 其中`@menu true`菜单编辑显示可选节点 +* 其中`@login true`需要强制登录才可访问 + +```php +/** +* 操作的名称 +* @auth true # 表示访问需要权限验证 +* @menu true # 菜单编辑显示可选节点 +* @login true # 需要强制登录才可访问 +*/ +public function index(){ + // @todo +} +``` + +## 代码仓库 + +主仓库放置于`Gitee`, `Github`为镜像仓库。 + +部分代码来自互联网,若有异议可以联系作者进行删除。 + +* 在线体验地址:https://v6.thinkadmin.top (账号和密码都是 admin ) +* Gitee仓库地址:https://gitee.com/zoujingli/ThinkAdmin/tree/v6.1 +* GitHub仓库地址:https://github.com/zoujingli/ThinkAdmin/tree/v6.1 + +## 技术支持 + +开发前请认真阅读 ThinkPHP 官方文档,会对您有帮助哦! + +本地开发请使用 `php think run` 运行服务,访问 `http://127.0.0.1:8000` 即可进入项目。 + +官方地址及开发指南:https://doc.thinkadmin.top ,如果实在无法解决问题,可以加入官方群免费交流。 + +**1.官方QQ交流群:** 513350915 + +**2.官方QQ交流群:** 866345568 + +**3.官方微信交流群** + + + +## 框架指令 + +* 执行 `php think run` 启用本地开发环境,访问 `http://127.0.0.1:8000` +* 执行 `php think xadmin:package` 将现有 `MySQL` 数据库打包为 `Phinx` 数据库脚本 +* 执行 `php think xadmin:sysmenu` 重写系统菜单并生成新编号,同时会清理已禁用的菜单数据 +* 执行 `php think xadmin:fansall` 同步微信粉丝数据,依赖于 `ThinkPlugsWechat` 应用插件 +* 执行 `php think xadmin:replace` 可以批量替换数据库指定字符字段内容,通常用于文件地址替换 +* 执行 `php think xadmin:database` 对数据库的所有表 `repair|optimize` 操作,优化并整理数据库碎片 +* 执行 `php think xadmin:publish` 可自动安装现在模块或已安装应用插件,参数 `--migrate` 执行数据库脚本 + +#### 1. 守护进程管理(可自建定时任务去守护监听主进程) + +* 执行 `php think xadmin:queue listen` [监听]启动异步任务监听服务 +* 执行 `php think xadmin:queue start` [控制]检查创建任务监听服务(建议定时任务执行) +* 执行 `php think xadmin:queue query` [控制]查询当前任务相关的进程 +* 执行 `php think xadmin:queue status` [控制]查看异步任务监听状态 +* 执行 `php think xadmin:queue stop` [控制]平滑停止所有任务进程 + +#### 2. 本地调试管理(可自建定时任务去守护监听主进程) + +* 执行 `php think xadmin:queue webstop` [调试]停止本地调试服务 +* 执行 `php think xadmin:queue webstart` [调试]开启本地调试服务(建议定时任务执行) +* 执行 `php think xadmin:queue webstatus` [调试]查看本地调试状态 + +## 问题修复 + +* 增加 `CORS` 跨域规则配置,配置参数置放于 `config/app.php`,需要更新 `ThinkLibrary`。 +* 修复 `layui.table` 导致基于 `ThinkPHP` 模板输出自动转义 `XSS` 过滤机制失效,需要更新 `ThinkLibrary`。 +* 修复在模板中使用 `{:input(NAME)}` 取值而产生的 `XSS` 问题,模板取值更换为 `{$get.NAME|default=''}`。 +* 修复 `CKEDITOR` 配置文件,禁用所有标签的 `on` 事件,阻止 `xss` 脚本注入,需要更新 `ckeditor/config.js`。 +* 修复文件上传入口的后缀验证,读取真实文件后缀与配置对比,阻止不合法的文件上传并存储到本地服务器。 +* 修改 `JsonRpc` 接口异常处理机制,当服务端绑定 `Exception` 时,客户端将能收到 `error` 消息及异常数据。 +* 修改 `location.hash` 访问机制,禁止直接访问外部 `URL` 资源链接,防止外部 `XSS` 攻击读取本地缓存数据。 +* 增加后台主题样式配置,支持全局默认+用户个性配置,需要更新 `admin`, `static`, `ThinkLibrary` 组件及模块。 +* 后台行政区域数据更新,由原来的腾讯地图数据切换为百度地图最新数据,需要更新`static`,数据库版需另行更新。 +* 增加`Phinx`数据库迁移脚本支持,可根据自己的需求安装对应模块,其中 `admin` 为改选模块! +* 从分离 `SystemService` 分离出 `RuntimeService` 服务,精减服务启动入口,优化性能! +* 增加插件模式,支持独立封装应用,可以通过 `composer` 管理并自动安装应用模块! + +## 版权信息 + +[**ThinkAdmin**](https://thinkadmin.top) 遵循 [**MIT**](license) 开源协议发布,并免费提供使用。 + +本项目包含的第三方源码和二进制文件的版权信息另行标注。 + +版权所有 Copyright © 2014-2023 by ThinkAdmin (https://thinkadmin.top) All rights reserved。 + +更多细节参阅 [`LISENSE`](license) 文件 + +## 系统版本 + +以下系统的体验账号及密码都是 admin + +### ThinkAdmin v6 基于 ThinkPHP6 开发(后台权限基于注解实现) + +* 在线体验地址:https://v6.thinkadmin.top (运行中) +* Gitee 代码地址:https://gitee.com/zoujingli/ThinkAdmin/tree/v6 +* Github 代码地址:https://github.com/zoujingli/ThinkAdmin/tree/v6 + +### ThinkAdmin v5 基于 ThinkPHP 5.1 开发(后台权限基于注解实现) + +* 在线体验地址:https://v5.thinkadmin.top (已停用) +* Gitee 代码地址:https://gitee.com/zoujingli/ThinkAdmin/tree/v5 +* Github 代码地址:https://github.com/zoujingli/ThinkAdmin/tree/v5 + +### ThinkAdmin v4 基于 ThinkPHP 5.1 开发(不建议继续使用) + +* 在线体验地址:https://v4.thinkadmin.top (已停用) +* Gitee 代码地址:https://gitee.com/zoujingli/ThinkAdmin/tree/v4 +* Github 代码地址:https://github.com/zoujingli/ThinkAdmin/tree/v4 + +### ThinkAdmin v3 基于 ThinkPHP 5.1 开发(不建议继续使用) + +* 在线体验地址:https://v3.thinkadmin.top (已停用) +* Gitee 代码地址:https://gitee.com/zoujingli/ThinkAdmin/tree/v3 +* Github 代码地址:https://github.com/zoujingli/ThinkAdmin/tree/v3 + +### ThinkAdmin v2 基于 ThinkPHP 5.0 开发(不建议继续使用) + +* 在线体验地址:https://v2.thinkadmin.top (已停用) +* Gitee 代码地址:https://gitee.com/zoujingli/ThinkAdmin/tree/v2 +* Github 代码地址:https://github.com/zoujingli/ThinkAdmin/tree/v2 + +### ThinkAdmin v1 基于 ThinkPHP 5.0 开发(不建议继续使用) + +* 在线体验地址:https://v1.thinkadmin.top (已停用) +* Gitee 代码地址:https://gitee.com/zoujingli/ThinkAdmin/tree/v1 +* Github 代码地址:https://github.com/zoujingli/ThinkAdmin/tree/v1 diff --git a/think b/think new file mode 100644 index 0000000..3daf561 --- /dev/null +++ b/think @@ -0,0 +1,24 @@ +#!/usr/bin/env php +