初始化
						commit
						82f5a8f3f5
					
				|  | @ -0,0 +1,19 @@ | |||
| APP_DEBUG = true | ||||
| APP_TRACE = true | ||||
| 
 | ||||
| [APP] | ||||
| DEFAULT_TIMEZONE = Asia/Shanghai | ||||
| 
 | ||||
| [DATABASE] | ||||
| TYPE = mysql | ||||
| HOSTNAME = 211.149.245.223 | ||||
| DATABASE = dev_bee_cms | ||||
| USERNAME = dev_bee_cms | ||||
| PASSWORD = dT7yH5fmd28JG6ER | ||||
| HOSTPORT = 3306 | ||||
| CHARSET = utf8mb4 | ||||
| DEBUG = true | ||||
| PREFIX = bee_ | ||||
| 
 | ||||
| [LANG] | ||||
| default_lang = zh-cn | ||||
|  | @ -0,0 +1,14 @@ | |||
| .env | ||||
| /.idea | ||||
| /.vscode | ||||
| backup/data/* | ||||
| /config/extra | ||||
| *.log | ||||
| runtime/* | ||||
| storage/* | ||||
| public/storage/* | ||||
| .DS_Store | ||||
| /Test.php | ||||
| nginx.htaccess | ||||
| dump.rdb | ||||
| /app/controller/api/Test.php | ||||
|  | @ -0,0 +1,32 @@ | |||
| 
 | ||||
| ThinkPHP遵循Apache2开源协议发布,并提供免费使用。 | ||||
| 版权所有Copyright © 2006-2016 by ThinkPHP (http://thinkphp.cn) | ||||
| All rights reserved。 | ||||
| ThinkPHP® 商标和著作权所有者为上海顶想信息科技有限公司。 | ||||
| 
 | ||||
| Apache Licence是著名的非盈利开源组织Apache采用的协议。 | ||||
| 该协议和BSD类似,鼓励代码共享和尊重原作者的著作权, | ||||
| 允许代码修改,再作为开源或商业软件发布。需要满足 | ||||
| 的条件:  | ||||
| 1. 需要给代码的用户一份Apache Licence ; | ||||
| 2. 如果你修改了代码,需要在被修改的文件中说明; | ||||
| 3. 在延伸的代码中(修改和有源代码衍生的代码中)需要 | ||||
| 带有原来代码中的协议,商标,专利声明和其他原来作者规 | ||||
| 定需要包含的说明; | ||||
| 4. 如果再发布的产品中包含一个Notice文件,则在Notice文 | ||||
| 件中需要带有本协议内容。你可以在Notice中增加自己的 | ||||
| 许可,但不可以表现为对Apache Licence构成更改。  | ||||
| 具体的协议参考:http://www.apache.org/licenses/LICENSE-2.0 | ||||
| 
 | ||||
| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||||
| "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||||
| LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | ||||
| FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | ||||
| COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | ||||
| INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | ||||
| BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||||
| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | ||||
| CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||||
| LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN | ||||
| ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||||
| POSSIBILITY OF SUCH DAMAGE. | ||||
|  | @ -0,0 +1,31 @@ | |||
| ## 本CMS基于ThinkPHP 6.0.9开发 | ||||
| 
 | ||||
| > - 运行环境要求 PHP7.4+ | ||||
| > - MySql版本限制 5.7.*(需要支持json函数) | ||||
| > - [富文本编辑器选择wangEditorv3.1.1](https://github.com/wangfupeng1988/wangEditor) | ||||
| > - [上传插件选择filepond4.7.1](https://github.com/pqina/filepond) | ||||
| > - 默认上传插件修改为使用layui组件库自带的 | ||||
| >  | ||||
| 
 | ||||
| <hr /><br /> | ||||
| 
 | ||||
| **PHP扩展依赖列表** | ||||
| 
 | ||||
| > - fileinfo | ||||
| > - exif 需要安装在mbsting扩展之后 | ||||
| > - gd | ||||
| 
 | ||||
| <hr /><br /> | ||||
| 
 | ||||
| **PHP组件列表** | ||||
| 
 | ||||
| > - | ||||
| 
 | ||||
| <hr /><br /> | ||||
| 
 | ||||
| **前端组件列表** | ||||
| 
 | ||||
| > - | ||||
| 
 | ||||
| <hr /><br /> | ||||
| 
 | ||||
|  | @ -0,0 +1 @@ | |||
| deny from all | ||||
|  | @ -0,0 +1,645 @@ | |||
| <?php | ||||
| // +----------------------------------------------------------------------
 | ||||
| // | ThinkPHP [ WE CAN DO IT JUST THINK ]
 | ||||
| // +----------------------------------------------------------------------
 | ||||
| // | Copyright (c) 2006-2016 http://thinkphp.cn All rights reserved.
 | ||||
| // +----------------------------------------------------------------------
 | ||||
| // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
 | ||||
| // +----------------------------------------------------------------------
 | ||||
| // | Author: 流年 <liu21st@gmail.com>
 | ||||
| // +----------------------------------------------------------------------
 | ||||
| 
 | ||||
| use think\Collection; | ||||
| use think\db\exception\DbException; | ||||
| use think\exception\ClassNotFoundException; | ||||
| use think\Model; | ||||
| use think\Paginator; | ||||
| 
 | ||||
| // 应用公共文件
 | ||||
| 
 | ||||
| if (!function_exists('widget')) { | ||||
|     /** | ||||
|      * 渲染输出Widget | ||||
|      * @param string $name Widget名称 | ||||
|      * @param array $data 传入的参数 | ||||
|      * @return mixed | ||||
|      * milo 2019-05-08 从TP5.1代码中拿来修改的 | ||||
|      */ | ||||
|     function widget($name, $data = []) | ||||
|     { | ||||
|         return action($name, $data, 'widget'); | ||||
|     } | ||||
| } | ||||
| if (!function_exists('action')) { | ||||
|     /** | ||||
|      * 调用模块的操作方法 参数格式 [模块/控制器/]操作 | ||||
|      * @param string $url 调用地址 | ||||
|      * @param string|array $vars 调用参数 支持字符串和数组 | ||||
|      * @param string $layer 要调用的控制层名称 | ||||
|      * @param bool $appendSuffix 是否添加类名后缀 | ||||
|      * @return mixed | ||||
|      * milo 2019-05-08 从TP5.1代码中拿来修改的 | ||||
|      */ | ||||
|     function action($url, $vars = [], $layer = 'controller', $appendSuffix = false) | ||||
|     { | ||||
|         $info = pathinfo($url); | ||||
|         $action = $info['basename']; | ||||
|         $module = '.' != $info['dirname'] ? $info['dirname'] : request()->controller(); | ||||
|         $class = controller($module, $layer); | ||||
|         if (is_scalar($vars)) { | ||||
|             if (strpos($vars, '=')) { | ||||
|                 parse_str($vars, $vars); | ||||
|             } else { | ||||
|                 $vars = [$vars]; | ||||
|             } | ||||
|         } | ||||
|         return app()->invokeMethod([$class, $action . config('route.action_suffix')], $vars); | ||||
|     } | ||||
| } | ||||
| if (!function_exists('controller')) { | ||||
|     /** | ||||
|      * 实例化(分层)控制器 格式:[模块名/]控制器名 | ||||
|      * @access public | ||||
|      * @param string $name 资源地址 | ||||
|      * @param string $layer 控制层名称 | ||||
|      * @param bool $appendSuffix 是否添加类名后缀 | ||||
|      * @param string $empty 空控制器名称 | ||||
|      * @return object | ||||
|      * @throws ClassNotFoundException | ||||
|      * | ||||
|      * milo 2019-05-08 从TP5.1代码中拿来修改的 | ||||
|      */ | ||||
|     function controller($name, $layer = 'controller', $empty = '') | ||||
|     { | ||||
|         $class = parseClass($name, $layer); | ||||
|         if (class_exists($class)) { | ||||
|             return app()->make($class); | ||||
|         } elseif ($empty && class_exists($emptyClass = app()->parseClass($layer, $empty))) { | ||||
|             return app()->make($emptyClass); | ||||
|         } | ||||
| 
 | ||||
|         throw new ClassNotFoundException('class not exists:' . $class, $class); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| if (!function_exists('parseClass')) { | ||||
|     /** | ||||
|      * 解析模块和类名 | ||||
|      * @access protected | ||||
|      * @param string $name 资源地址 | ||||
|      * @param string $layer 验证层名称 | ||||
|      * @param bool $appendSuffix 是否添加类名后缀 | ||||
|      * @return array | ||||
|      * | ||||
|      * milo 2019-05-08 从TP5.1代码中拿来修改的 | ||||
|      */ | ||||
|     function parseClass($name, $layer) | ||||
|     { | ||||
|         if (false !== strpos($name, '\\')) { | ||||
|             $class = $name; | ||||
|         } else { | ||||
|             if (strpos($name, '/')) { | ||||
|                 $names = explode('/', $name, 2); | ||||
|                 $name = $names[1]; | ||||
|             } | ||||
|             $class = app()->parseClass($layer, $name); | ||||
|         } | ||||
|         return $class; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| if (!function_exists('randomStr')) { | ||||
|     /** | ||||
|      * 获取随机字符串 | ||||
|      * @param int $type 0:数字(默认);1:全部;2:小写字母;3:大写字母;4:字母; | ||||
|      * @param int $len 字符串长度 | ||||
|      * @return string | ||||
|      */ | ||||
|     function randomStr($type = 0, $len = 5) | ||||
|     { | ||||
|         $strPol = "0123456789"; | ||||
|         if ($type == 1) { | ||||
|             $strPol = "ABCDEFGHIJKLMOPQRSTUVWYZ0123456789abcdefghijklmopqrstuvwyz"; | ||||
|         } elseif ($type == 2) { | ||||
|             $strPol = "abcdefghijklmopqrstuvwyz"; | ||||
|         } elseif ($type == 3) { | ||||
|             $strPol = "ABCDEFGHIJKLMOPQRSTUVWYZ"; | ||||
|         } elseif ($type == 4) { | ||||
|             $strPol = "ABCDEFGHIJKLMOPQRSTUVWYZabcdefghijklmopqrstuvwyz"; | ||||
|         } | ||||
|         $max = strlen($strPol) - 1; | ||||
|         $str = ''; | ||||
|         for ($i = 0; $i < $len; $i++) { | ||||
|             $str .= $strPol[rand(0, $max)]; | ||||
|         } | ||||
|         return $str; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| if (!function_exists('isMobile')) { | ||||
|     //判断访问终端是否为移动端
 | ||||
|     function isMobile() | ||||
|     { | ||||
|         // 如果有HTTP_X_WAP_PROFILE则一定是移动设备
 | ||||
|         if (isset($_SERVER['HTTP_X_WAP_PROFILE'])) { | ||||
|             return true; | ||||
|         } | ||||
|         // 如果via信息含有wap则一定是移动设备,部分服务商会屏蔽该信息
 | ||||
|         if (isset($_SERVER['HTTP_VIA'])) { | ||||
|             // 找不到为flase,否则为true
 | ||||
|             return stristr($_SERVER['HTTP_VIA'], "wap") ? true : false; | ||||
|         } | ||||
|         // 脑残法,判断手机发送的客户端标志,兼容性有待提高。其中'MicroMessenger'是电脑微信
 | ||||
|         if (isset($_SERVER['HTTP_USER_AGENT'])) { | ||||
|             $clientkeywords = [ | ||||
|                 'nokia', 'sony', 'ericsson', 'mot', 'samsung', 'htc', 'sgh', 'lg', 'sharp', 'sie-', 'philips', | ||||
|                 'panasonic', 'alcatel', 'lenovo', 'iphone', 'ipod', 'blackberry', 'meizu', 'android', 'netfront', | ||||
|                 'symbian', 'ucweb', 'windowsce', 'palm', 'operamini', 'operamobi', 'openwave', 'nexusone', 'cldc', | ||||
|                 'midp', 'wap', 'mobile', 'MicroMessenger' | ||||
|             ]; | ||||
|             // 从HTTP_USER_AGENT中查找手机浏览器的关键字
 | ||||
|             if (preg_match("/(" . implode('|', $clientkeywords) . ")/i", strtolower($_SERVER['HTTP_USER_AGENT']))) { | ||||
|                 return true; | ||||
|             } | ||||
|         } | ||||
|         // 协议法,因为有可能不准确,放到最后判断
 | ||||
|         if (isset ($_SERVER['HTTP_ACCEPT'])) { | ||||
|             // 如果只支持wml并且不支持html那一定是移动设备
 | ||||
|             // 如果支持wml和html但是wml在html之前则是移动设备
 | ||||
|             if ((strpos($_SERVER['HTTP_ACCEPT'], 'vnd.wap.wml') !== false) && (strpos($_SERVER['HTTP_ACCEPT'], | ||||
|                         'text/html') === false || (strpos($_SERVER['HTTP_ACCEPT'], | ||||
|                             'vnd.wap.wml') < strpos($_SERVER['HTTP_ACCEPT'], 'text/html')))) { | ||||
|                 return true; | ||||
|             } | ||||
|         } | ||||
|         return false; | ||||
|     } | ||||
| } | ||||
| //根据栏目获取路径
 | ||||
| if (!function_exists('getUri')) { | ||||
|     function getUri($cate) | ||||
|     { | ||||
|         $url = ''; | ||||
|         if (!empty($cate)) { | ||||
|             if ($cate['is_index']) { | ||||
|                 $url = '/'; | ||||
|             } elseif (!empty($cate['url'])) { | ||||
|                 $url = $cate['url']; | ||||
|             } else { | ||||
|                 $url = url($cate['template'] . '/index', ['category_id' => $cate['id']]); | ||||
|             } | ||||
|         } | ||||
|         return $url; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| //根据文件大小转换为文字
 | ||||
| if (!function_exists('sizeToStr')) { | ||||
|     function sizeToStr($size) | ||||
|     { | ||||
|         if (!is_numeric($size) || $size <= 0) { | ||||
|             return ''; | ||||
|         } | ||||
|         $size = $size / 1024; | ||||
|         if ($size < 1024) { | ||||
|             return sprintf("%.2fK", $size); | ||||
|         } | ||||
|         $size = $size / 1024; | ||||
|         if ($size < 1024) { | ||||
|             return sprintf("%.2fM", $size); | ||||
|         } | ||||
|         $size = $size / 1024; | ||||
|         return sprintf("%.2fG", $size); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| //根据路径获取文件名
 | ||||
| if (!function_exists('getKeyByPath')) { | ||||
|     function getKeyByPath($path) | ||||
|     { | ||||
|         return substr($path, strrpos($path, '/') + 1); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| //富文本中提取图片路径
 | ||||
| if (!function_exists('getImageUrlFromText')) { | ||||
|     function getImageUrlFromText($content) | ||||
|     { | ||||
|         preg_match_all('/<img.*?src="(.*?)".*?>/is', $content, $imgs); | ||||
|         $data = []; | ||||
|         if (!empty($imgs) && !empty($imgs[1])) { | ||||
|             foreach ($imgs[1] as $img) { | ||||
|                 if (substr($img, 0, 4) != 'http') { | ||||
|                     $key = getKeyByPath($img); | ||||
|                     $data[$key] = $img; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         return $data; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| //富文本中提取视频路径
 | ||||
| if (!function_exists('getVideoUrlFromText')) { | ||||
|     function getVideoUrlFromText($content) | ||||
|     { | ||||
|         preg_match_all('/<video.*?src="(.*?)".*?>/is', $content, $videos); | ||||
|         $data = []; | ||||
|         if (!empty($videos) && !empty($videos[1])) { | ||||
|             foreach ($videos[1] as $video) { | ||||
|                 if (substr($video, 0, 4) != 'http') { | ||||
|                     $key = getKeyByPath($video); | ||||
|                     $data[$key] = $video; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         return $data; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| //获取目录下的所有文件
 | ||||
| if (!function_exists('getAllFilesByPath')) { | ||||
|     function getAllFilesByPath($path, $rootPath) | ||||
|     { | ||||
|         if (is_dir($path) && file_exists($path)) { | ||||
|             $items = scandir($path); | ||||
|             $files = []; | ||||
|             foreach ($items as $item) { | ||||
|                 if (substr($item, 0, 1) != '.' && strpos($item, '_') == false) { | ||||
|                     $itemPath = $path . '/' . $item; | ||||
|                     if (is_file($itemPath)) { | ||||
|                         $size = filesize($itemPath); | ||||
|                         $files[$item] = [ | ||||
|                             'path' => str_replace($rootPath, '/', $itemPath), | ||||
|                             'realPath' => $itemPath, | ||||
|                             'size' => $size, | ||||
|                             'sizeStr' => sizeToStr($size), | ||||
|                             'suffix' => strtolower(substr($item, strrpos($item, '.') + 1))    //后缀
 | ||||
|                         ]; | ||||
|                     } elseif (is_dir($itemPath)) { | ||||
|                         $childFiles = getAllFilesByPath($itemPath, $rootPath); | ||||
|                         if (!empty($childFiles)) { | ||||
|                             $files = array_merge($files, $childFiles); | ||||
|                         } else { | ||||
|                             rmdir($itemPath); | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|             return $files; | ||||
|         } | ||||
|         return []; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| //过滤get输入
 | ||||
| if (!function_exists('getFilter')) { | ||||
|     function getFilter($value) | ||||
|     { | ||||
|         $getFilter = "'|(and|or)\b.+?(>|<|=|in|like)|\/\*.+?\*\/|<\s*script\b|\bEXEC\b|UNION.+?SELECT|UPDATE.+?SET|INSERT\s+INTO.+?VALUES|(SELECT|DELETE).+?FROM|(CREATE|ALTER|DROP|TRUNCATE)\s+(TABLE|DATABASE)"; | ||||
|         $forArray = false; | ||||
|         if (is_array($value)) { | ||||
|             $forFilter = implode($value); | ||||
|             $forArray = true; | ||||
|         } else { | ||||
|             $forFilter = $value; | ||||
|         } | ||||
|         if (preg_match("/" . $getFilter . "/is", $forFilter) == 1) { | ||||
|             $value = $forArray ? [] : ''; | ||||
|         } | ||||
|         return filterExp($value); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| //过滤post录入
 | ||||
| if (!function_exists('postFilter')) { | ||||
|     function postFilter($value) | ||||
|     { | ||||
|         $postFilter = "\b(and|or)\b.{1,6}?(=|>|<|\bin\b|\blike\b)|\/\*.+?\*\/|<\s*script\b|\bEXEC\b|UNION.+?SELECT|UPDATE.+?SET|INSERT\s+INTO.+?VALUES|(SELECT|DELETE).+?FROM|(CREATE|ALTER|DROP|TRUNCATE)\s+(TABLE|DATABASE)"; | ||||
|         $forArray = false; | ||||
|         if (is_array($value)) { | ||||
|             $forFilter = implode($value); | ||||
|             $forArray = true; | ||||
|         } else { | ||||
|             $forFilter = $value; | ||||
|         } | ||||
|         if (preg_match("/" . $postFilter . "/is", $forFilter) == 1) { | ||||
|             $value = $forArray ? [] : ''; | ||||
|         } | ||||
|         return filterExp($value); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| //过滤cookie数据
 | ||||
| if (!function_exists('cookieFilter')) { | ||||
|     function cookieFilter($value) | ||||
|     { | ||||
|         $cookieFilter = "\b(and|or)\b.{1,6}?(=|>|<|\bin\b|\blike\b)|\/\*.+?\*\/|<\s*script\b|\bEXEC\b|UNION.+?SELECT|UPDATE.+?SET|INSERT\s+INTO.+?VALUES|(SELECT|DELETE).+?FROM|(CREATE|ALTER|DROP|TRUNCATE)\s+(TABLE|DATABASE)"; | ||||
|         $forArray = false; | ||||
|         if (is_array($value)) { | ||||
|             $forFilter = implode($value); | ||||
|             $forArray = true; | ||||
|         } else { | ||||
|             $forFilter = $value; | ||||
|         } | ||||
|         if (preg_match("/" . $cookieFilter . "/is", $forFilter) == 1) { | ||||
|             $value = $forArray ? [] : ''; | ||||
|         } | ||||
|         return filterExp($value); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| if (!function_exists('filterExp')) { | ||||
|     function filterExp($value) | ||||
|     { | ||||
|         $filter = '/^(\s)+(EXP|NEQ|GT|EGT|LT|ELT|OR|XOR|LIKE|NOTLIKE|NOT LIKE|NOT BETWEEN|NOTBETWEEN|BETWEEN|NOTIN|NOT IN|IN)(\s)+$/i'; | ||||
|         $forArray = false; | ||||
|         if (is_array($value)) { | ||||
|             $forFilter = implode($value); | ||||
|             $forArray = true; | ||||
|         } else { | ||||
|             $forFilter = $value; | ||||
|         } | ||||
|         if (preg_match($filter, $forFilter) == 1) { | ||||
|             $value = $forArray ? [] : ''; | ||||
|         } | ||||
|         return $value; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| if (!function_exists('arrayHtmlFilter')) { | ||||
|     function arrayHtmlFilter($arr) | ||||
|     { | ||||
|         foreach ($arr as $k => $one) { | ||||
|             if (is_array($one)) { | ||||
|                 $arr[$k] = arrayHtmlFilter($one); | ||||
|             } else { | ||||
|                 $one = trim($one); | ||||
|                 $arr[$k] = strip_tags($one); | ||||
|             } | ||||
|         } | ||||
|         return $arr; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| if (!function_exists('toCamelString')) { | ||||
|     /** | ||||
|      * 转驼峰 | ||||
|      * | ||||
|      * @param string $string | ||||
|      * @param false $small 默认false 为true首字母小写 | ||||
|      * @return string | ||||
|      */ | ||||
|     function toCamelString(string $string, bool $small = false): string | ||||
|     { | ||||
|         //例: xxx_yYy_zzZ 和 xxX-yyy-Zzz
 | ||||
|         //1. 字符串转小写 xxx_yyy_zzz xxx-yyy-zzz
 | ||||
|         //2. -和_转空格 xxx yyy zzz
 | ||||
|         //3. 单词首字母大写 Xxx Yyy Zzz
 | ||||
|         //4. 清除空格 XxxYyyZzz
 | ||||
|         //处理下划线、减号 统统专程大驼峰 如xxx_yyy_zzz xxx-yyy-zzz 均转为 XxxYyyZzz
 | ||||
|         $string = strtolower($string); | ||||
|         $string = str_replace('-', ' ', $string); | ||||
|         $string = str_replace('_', ' ', $string); | ||||
|         $string = str_replace(' ', '', ucwords($string)); | ||||
|         if ($small) { | ||||
|             $string = lcfirst($string); | ||||
|         } | ||||
|         return $string; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| if (!function_exists('unCamelize')) { | ||||
|     /** | ||||
|      * 驼峰命名转特定分隔符[如下划线]命名 | ||||
|      * @param string $camelCaps | ||||
|      * @param string $separator | ||||
|      * @return string | ||||
|      */ | ||||
|     function unCamelize(string $camelCaps, string $separator = '-'): string | ||||
|     { | ||||
|         return strtolower(preg_replace('/([a-z])([A-Z])/', "$1" . $separator . "$2", $camelCaps)); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| if (!function_exists('generateRand')) { | ||||
|     /** | ||||
|      * 生成随机数 | ||||
|      * | ||||
|      * @param int $length 长度 | ||||
|      * @param string $type 模式 默认mix混合 number纯数字 alpha字母 | ||||
|      * @return string | ||||
|      */ | ||||
|     function generateRand(int $length = 8, string $type = 'mix'): string | ||||
|     { | ||||
|         $alphabet = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; | ||||
|         $number = '0123456789'; | ||||
|         $alphabetLen = strlen($alphabet) - 1; | ||||
|         $numberLen = 9; | ||||
| 
 | ||||
|         switch ($type) { | ||||
|             case 'number': | ||||
|                 $str = $number; | ||||
|                 $len = $numberLen; | ||||
|                 break; | ||||
|             case 'alpha': | ||||
|                 $str = $alphabet; | ||||
|                 $len = $alphabetLen; | ||||
|                 break; | ||||
|             default: | ||||
|                 $str = $alphabet . $number; | ||||
|                 $len = $alphabetLen + $numberLen; | ||||
|         } | ||||
| 
 | ||||
|         $randStr = ''; | ||||
|         $str = str_shuffle($str); | ||||
|         for ($i = 0; $i < $length; $i++) { | ||||
|             $num = mt_rand(0, $len); | ||||
|             $randStr .= $str[$num]; | ||||
|         } | ||||
|         return $randStr; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| if (!function_exists('generateCode')) { | ||||
|     /** | ||||
|      * 生成特定编码 | ||||
|      * | ||||
|      * @param string $type 类型 默认mix混合 number纯数字 alpha字母 | ||||
|      * @param int $len 随机数长度 | ||||
|      * @return string | ||||
|      */ | ||||
|     function generateCode(string $type = 'number', int $len = 6): string | ||||
|     { | ||||
|         //#时间戳+微秒+6位随机数
 | ||||
|         $time = microtime(true); | ||||
|         $timeStr = str_replace('.', '', $time); | ||||
|         return sprintf("%s%s", $timeStr, generateRand($len, $type)); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| if (!function_exists('checkMobile')) { | ||||
|     /** | ||||
|      * 检测手机号 | ||||
|      * | ||||
|      * @param string $mobile | ||||
|      * @return bool | ||||
|      */ | ||||
|     function checkMobile(string $mobile): bool | ||||
|     { | ||||
|         if (preg_match("/^1[3456789]{1}\d{9}$/", $mobile)) { | ||||
|             return true; | ||||
|         } else { | ||||
|             return false; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| if (!function_exists('arrayKeysFilter')) { | ||||
|     /** | ||||
|      * 数组键名过滤 | ||||
|      * | ||||
|      * @param array $data | ||||
|      * @param array $allowKeys | ||||
|      * @return array | ||||
|      */ | ||||
|     function arrayKeysFilter(array $data, array $allowKeys): array | ||||
|     { | ||||
|         $list = []; | ||||
|         foreach ($data as $key => $val) { | ||||
|             if (in_array($key, $allowKeys)) { | ||||
|                 $list[$key] = $val; | ||||
|             } | ||||
|         } | ||||
|         return $list; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| if (!function_exists('getFilesize')) { | ||||
|     /** | ||||
|      * 尺寸单位转换 | ||||
|      * | ||||
|      * @param $num | ||||
|      * @return string | ||||
|      */ | ||||
|     function getFilesize($num): string | ||||
|     { | ||||
|         $p = 0; | ||||
|         $format = 'B'; | ||||
|         if ($num > 0 && $num < 1024) { | ||||
|             return number_format($num) . ' ' . $format; | ||||
|         } | ||||
|         if ($num >= 1024 && $num < pow(1024, 2)) { | ||||
|             $p = 1; | ||||
|             $format = 'KB'; | ||||
|         } | ||||
|         if ($num >= pow(1024, 2) && $num < pow(1024, 3)) { | ||||
|             $p = 2; | ||||
|             $format = 'MB'; | ||||
|         } | ||||
|         if ($num >= pow(1024, 3) && $num < pow(1024, 4)) { | ||||
|             $p = 3; | ||||
|             $format = 'GB'; | ||||
|         } | ||||
|         if ($num >= pow(1024, 4) && $num < pow(1024, 5)) { | ||||
|             $p = 3; | ||||
|             $format = 'TB'; | ||||
|         } | ||||
|         $num /= pow(1024, $p); | ||||
|         return number_format($num, 3) . ' ' . $format; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| if (!function_exists('arrayNullToString')) { | ||||
|     /** | ||||
|      * 数组中null值转为空字符串 | ||||
|      * | ||||
|      * @param array $data | ||||
|      * @return array | ||||
|      */ | ||||
|     function arrayNullToString(array $data): array | ||||
|     { | ||||
|         foreach ($data as $key => $val) { | ||||
|             if (is_array($val)) { | ||||
|                 $data[$key] = arrayNullToString($val); | ||||
|             } elseif ($val === null) { | ||||
|                 $data[$key] = ''; | ||||
|             } | ||||
|         } | ||||
|         return $data; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| if (!function_exists('arrayKeysExcludeFilter')) { | ||||
|     /** | ||||
|      * 数组键名排除过滤 | ||||
|      * | ||||
|      * @param array $data | ||||
|      * @param array $excludeKeys 排除的字段 | ||||
|      * @return array | ||||
|      */ | ||||
|     function arrayKeysExcludeFilter(array $data, array $excludeKeys): array | ||||
|     { | ||||
|         foreach ($data as $key => $val) { | ||||
|             if (in_array($key, $excludeKeys)) { | ||||
|                 unset($data[$key]); | ||||
|             } | ||||
|         } | ||||
|         return $data; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| if (!function_exists('getLatelyWeekDate')) { | ||||
|     /** | ||||
|      * 获取本周的周一 到周日的日期 | ||||
|      */ | ||||
|     function getLatelyWeekDate() | ||||
|     { | ||||
|         //本周一
 | ||||
|         $oneDate = date('Y-m-d 00:00:00', (time() - ((date('w') == 0 ? 7 : date('w')) - 1) * 86400)); //w为星期几的数字形式,这里0为周日
 | ||||
|         $oneDateTime = strtotime($oneDate); | ||||
|         //返回周一到周天  1-7
 | ||||
|         return [ | ||||
|             "1" => ["date"=>$oneDate], | ||||
|             "2" => ["date"=>date('Y-m-d 00:00:00', $oneDateTime + ((86400 * 1)))], | ||||
|             "3" => ["date"=>date('Y-m-d 00:00:00', $oneDateTime + ((86400 * 2)))], | ||||
|             "4" => ["date"=>date('Y-m-d 00:00:00', $oneDateTime + ((86400 * 3)))], | ||||
|             "5" => ["date"=>date('Y-m-d 00:00:00', $oneDateTime + ((86400 * 4)))], | ||||
|             "6" => ["date"=>date('Y-m-d 00:00:00', $oneDateTime + ((86400 * 5)))], | ||||
|             "7" => ["date"=>date('Y-m-d 00:00:00', $oneDateTime + ((86400 * 6)))], | ||||
|         ]; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| if (!function_exists('stringDesensitization')) { | ||||
|     /** | ||||
|      * 字符串脱敏 默认给手机号脱敏 其他未兼容 | ||||
|      * | ||||
|      * @param  string  $string | ||||
|      * @param  string  $s | ||||
|      * @param  int  $start | ||||
|      * @param  int  $len | ||||
|      * @return string | ||||
|      */ | ||||
|     function stringDesensitization(string $string, string $s = '****', int $start = 3, int $len = 4): string | ||||
|     { | ||||
|         return substr_replace($string, $s, $start, $len); | ||||
|     } | ||||
| } | ||||
| /** | ||||
|  * UUID | ||||
|  */ | ||||
| if(!function_exists("createUuid")){ | ||||
|     function createUuid($prefix = "") | ||||
|     { | ||||
|         $chars = md5(uniqid(mt_rand(), true)); | ||||
|         $uuid = substr($chars, 0, 8) . '-' | ||||
|             . substr($chars, 8, 4) . '-' | ||||
|             . substr($chars, 12, 4) . '-' | ||||
|             . substr($chars, 16, 4) . '-' | ||||
|             . substr($chars, 20, 12); | ||||
|         return $prefix . str_replace("-", "", $uuid); | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,35 @@ | |||
| <?php | ||||
| 
 | ||||
| namespace app\controller; | ||||
| 
 | ||||
| use app\repository\OperationRepository; | ||||
| use Exception; | ||||
| use think\response\View; | ||||
| use think\response\Redirect; | ||||
| use app\repository\CmsRepository; | ||||
| use app\repository\BlockRepository; | ||||
| use think\db\exception\DbException; | ||||
| use think\db\exception\DataNotFoundException; | ||||
| use think\db\exception\ModelNotFoundException; | ||||
| 
 | ||||
| class About extends Base | ||||
| { | ||||
|     /** | ||||
|      * 列表页 | ||||
|      * | ||||
|      * @return Redirect|View | ||||
|      * @throws DataNotFoundException | ||||
|      * @throws DbException | ||||
|      * @throws ModelNotFoundException | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public function index() | ||||
|     { | ||||
|         $this->setSeo(); | ||||
|         $about                  = CmsRepository::getInstance()->getAbout($this->aboutCategory['id']); | ||||
|         $this->data['about']    = $about; | ||||
|         $this->data['category'] = $this->aboutCategory; | ||||
| 
 | ||||
|         return $this->view(); | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,513 @@ | |||
| <?php | ||||
| 
 | ||||
| namespace app\controller; | ||||
| 
 | ||||
| use app\exception\RepositoryException; | ||||
| use app\repository\AccountRepository; | ||||
| use app\repository\CommonRepository; | ||||
| use app\repository\GoodsRepository; | ||||
| use app\service\Kd100; | ||||
| use app\validate\Account as VAccount; | ||||
| use app\repository\OrderRepository; | ||||
| use Exception; | ||||
| use GuzzleHttp\Exception\GuzzleException; | ||||
| use think\db\exception\DataNotFoundException; | ||||
| use think\db\exception\DbException; | ||||
| use think\db\exception\ModelNotFoundException; | ||||
| use think\facade\Db; | ||||
| use think\response\Json; | ||||
| use think\response\View; | ||||
| 
 | ||||
| class Account extends Base | ||||
| { | ||||
|     protected $middleware = ['login']; | ||||
| 
 | ||||
|     /** | ||||
|      * 个人中心 | ||||
|      * | ||||
|      * @return View | ||||
|      * @throws DbException | ||||
|      */ | ||||
|     public function index(): View | ||||
|     { | ||||
|         $this->data['countList']   = OrderRepository::getInstance()->findOrderCount($this->authId); | ||||
|         $this->data['markList']    = OrderRepository::getInstance()->auctionMarkList('', [$this->authId]); | ||||
|         $this->data['biddingList'] = GoodsRepository::getInstance()->auctionBiddingList($this->authId); | ||||
|         return $this->view(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 个人资料 | ||||
|      * | ||||
|      * @return View|Json | ||||
|      * @throws RepositoryException | ||||
|      */ | ||||
|     public function profile() | ||||
|     { | ||||
|         $repo = AccountRepository::getInstance(); | ||||
|         $item = $repo->findById($this->authId); | ||||
|         if ($this->request->isPost()) { | ||||
|             $post                 = input('post.'); | ||||
|             $update               = []; | ||||
|             $update['headimgurl'] = $post['headimgurl'] ?? ''; | ||||
|             $update['sex']        = $post['sex']; | ||||
|             $update['nickname']   = $post['nickname']; | ||||
|             if (!empty($post['nickname']) && $item['nickname'] !== $post['nickname']) { | ||||
|                 if ($item['nickname_time'] > 0) { | ||||
|                     return $this->json(4001, '每人仅先修改一次昵称,您已修改过了。'); | ||||
|                 } | ||||
|                 $update['nickname_time'] = $item['nickname_time'] + 1; | ||||
|             } | ||||
|             $item->save($update); | ||||
|             return $this->json(); | ||||
|         } | ||||
|         $this->data['item'] = $item; | ||||
|         return $this->view(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 我的订单 | ||||
|      * | ||||
|      * @return View | ||||
|      */ | ||||
|     public function order(): View | ||||
|     { | ||||
|         $accountId = $this->auth['id'] ?? 0; | ||||
|         $tag       = input('get.tag/s', 'waiting'); | ||||
| 
 | ||||
|         $this->data['items'] = OrderRepository::getInstance()->getOrderGoods($accountId, $tag); | ||||
|         $this->data['tag']   = $tag; | ||||
|         return $this->view(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 保证金 | ||||
|      * | ||||
|      * @return View | ||||
|      * @throws RepositoryException | ||||
|      */ | ||||
|     public function deposit(): View | ||||
|     { | ||||
|         $accountId = $this->auth['id'] ?? 0; | ||||
|         if (!$accountId) { | ||||
|             $this->error('请先登录'); | ||||
|         } | ||||
| 
 | ||||
|         $item = AccountRepository::getInstance()->findById($accountId, ['quota', 'id', 'deposit']); | ||||
| 
 | ||||
|         $this->data['item'] = $item; | ||||
|         return $this->view(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 实名认证 | ||||
|      * | ||||
|      * @return View|Json | ||||
|      * @throws RepositoryException | ||||
|      */ | ||||
|     public function realName() | ||||
|     { | ||||
|         $accountId = $this->auth['id'] ?? 0; | ||||
|         $account   = AccountRepository::getInstance()->findById($accountId); | ||||
|         if ($this->request->isPost()) { | ||||
|             if (!$account) { | ||||
|                 return $this->json(4001, '请先登录'); | ||||
|             } | ||||
| 
 | ||||
|             if ($account['is_real_name']) { | ||||
|                 return $this->json(4002, '您已通过认证'); | ||||
|             } | ||||
| 
 | ||||
|             $post     = input('post.'); | ||||
|             $validate = new VAccount(); | ||||
|             if (!$validate->scene('real_name')->check($post)) { | ||||
|                 return $this->json(4003, $validate->getError()); | ||||
|             } | ||||
| 
 | ||||
|             $post['is_real_name'] = 1; | ||||
|             $account->save($post); | ||||
|             return $this->json(); | ||||
|         } | ||||
| 
 | ||||
|         $this->data['item'] = $account; | ||||
|         return $this->view(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 个人账户 | ||||
|      * | ||||
|      * @return View | ||||
|      * @throws RepositoryException | ||||
|      */ | ||||
|     public function info(): View | ||||
|     { | ||||
|         $accountId      = $this->auth['id'] ?? 0; | ||||
|         $item           = AccountRepository::getInstance()->findById($accountId); | ||||
|         $rechargeList   = AccountRepository::getInstance()->fetchRechargeList($accountId); | ||||
|         $withdrawalList = AccountRepository::getInstance()->fetchWithdrawalList($accountId); | ||||
| 
 | ||||
|         $this->data['item']           = $item; | ||||
|         $this->data['rechargeList']   = $rechargeList['list']; | ||||
|         $this->data['withdrawalList'] = $withdrawalList['list']; | ||||
|         return $this->view(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 中标清单 | ||||
|      * | ||||
|      * @return View | ||||
|      * @throws DbException | ||||
|      */ | ||||
|     public function biddingList(): View | ||||
|     { | ||||
|         $accountId           = $this->auth['id'] ?? 0; | ||||
|         $pageParams['query'] = input('get.'); | ||||
|         $list                = OrderRepository::getInstance()->auctionMarkList('', [$accountId], $pageParams); | ||||
| 
 | ||||
|         $this->data['list'] = $list; | ||||
|         return $this->view(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 竞价清单 | ||||
|      * | ||||
|      * @return View | ||||
|      */ | ||||
|     public function biddingLog(): View | ||||
|     { | ||||
|         $list = GoodsRepository::getInstance()->auctionBiddingList($this->authId); | ||||
| 
 | ||||
|         $this->data['items'] = $list; | ||||
|         return $this->view(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 关注的拍品 | ||||
|      * | ||||
|      * @return View | ||||
|      * @throws DataNotFoundException | ||||
|      * @throws DbException | ||||
|      * @throws ModelNotFoundException | ||||
|      */ | ||||
|     public function auctionCollection(): View | ||||
|     { | ||||
|         $accountId           = $this->auth['id'] ?? 0; | ||||
|         $items               = AccountRepository::getInstance()->fetchCollection($accountId, GoodsRepository::TYPE_AUCTION); | ||||
|         $this->data['items'] = $items; | ||||
|         return $this->view(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 商品收藏 | ||||
|      * | ||||
|      * @return View | ||||
|      * @throws DataNotFoundException | ||||
|      * @throws DbException | ||||
|      * @throws ModelNotFoundException | ||||
|      */ | ||||
|     public function goodsCollection(): View | ||||
|     { | ||||
|         $accountId           = $this->auth['id'] ?? 0; | ||||
|         $items               = AccountRepository::getInstance()->fetchCollection($accountId, GoodsRepository::TYPE_GOODS); | ||||
|         $this->data['items'] = $items; | ||||
|         return $this->view(); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     /** | ||||
|      * 地址管理 | ||||
|      * | ||||
|      * @return View | ||||
|      * @throws DataNotFoundException | ||||
|      * @throws DbException | ||||
|      * @throws ModelNotFoundException | ||||
|      */ | ||||
|     public function address(): View | ||||
|     { | ||||
|         $accountId = $this->auth['id'] ?? 0; | ||||
|         //地址列表
 | ||||
|         $addressList = AccountRepository::getInstance()->findAddressByUid($accountId); | ||||
| 
 | ||||
|         $this->data['addressList'] = $addressList; | ||||
|         return $this->view(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 地址详情 | ||||
|      * | ||||
|      * @return Json|View | ||||
|      * @throws DataNotFoundException | ||||
|      * @throws DbException | ||||
|      * @throws ModelNotFoundException | ||||
|      */ | ||||
|     public function addressDetail() | ||||
|     { | ||||
|         $resp      = AccountRepository::getInstance(); | ||||
|         $accountId = $this->auth['id'] ?? 0; | ||||
|         $id        = input('param.id/d', 0); | ||||
|         $item      = $resp->findAddressById($id); | ||||
|         if ($this->request->isPost()) { | ||||
|             $postItem            = input('post.'); | ||||
|             $postItem['user_id'] = $postItem['user_id'] ?? $accountId; | ||||
|             $resp->saveAddress($postItem); | ||||
|             return $this->json(); | ||||
|         } | ||||
| 
 | ||||
|         $this->data['item'] = $item; | ||||
|         return $this->view(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 地址删除 | ||||
|      * | ||||
|      * @return Json | ||||
|      */ | ||||
|     public function addressDel(): Json | ||||
|     { | ||||
|         if ($this->request->isPost()) { | ||||
|             $id = input('post.id/d', 0); | ||||
|             AccountRepository::getInstance()->delAddress($id); | ||||
|             return $this->json(); | ||||
|         } | ||||
| 
 | ||||
|         return $this->json(4002, '请求方式错误'); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 修改密码 | ||||
|      * | ||||
|      * @return Json | ||||
|      */ | ||||
|     public function editPwd(): Json | ||||
|     { | ||||
|         $post      = input('post.'); | ||||
|         $accountId = $this->auth['id'] ?? 0; | ||||
|         $validate  = new VAccount(); | ||||
|         if (!$validate->scene('edit_password')->check($post)) { | ||||
|             return $this->json(4002, $validate->getError()); | ||||
|         } | ||||
| 
 | ||||
|         try { | ||||
|             AccountRepository::getInstance()->modifyPwd($accountId, $post['old_password'], $post['password']); | ||||
|         } catch (Exception $e) { | ||||
|             $this->json(4003, $e->getMessage()); | ||||
|         } | ||||
| 
 | ||||
|         return $this->json(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 取消收藏|关注 | ||||
|      * | ||||
|      * @return Json | ||||
|      * @throws DataNotFoundException | ||||
|      * @throws DbException | ||||
|      * @throws ModelNotFoundException | ||||
|      */ | ||||
|     public function unCollect(): Json | ||||
|     { | ||||
|         $accountId = $this->auth['id'] ?? 0; | ||||
|         $goodsId   = input('post.id/d'); | ||||
|         AccountRepository::getInstance()->unCollectGoods($accountId, $goodsId); | ||||
|         return $this->json(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 操作保证金  充值|退回   相应改变额度 | ||||
|      * | ||||
|      * @return Json | ||||
|      * @throws RepositoryException | ||||
|      */ | ||||
|     public function operateDeposit(): Json | ||||
|     { | ||||
|         if ($this->request->isPost()) { | ||||
|             $accountId = $this->auth['id'] ?? 0; | ||||
|             $amount    = input('post.value', 0); | ||||
|             $type      = input('post.type/s', 'recharge'); | ||||
|             if (!AccountRepository::getInstance()->isEnough($accountId, $amount, 'deposit')) { | ||||
|                 return $this->json(4000, '余额不足'); | ||||
|             } | ||||
|             try { | ||||
|                 AccountRepository::getInstance()->operateDeposit($accountId, $amount, $type); | ||||
|             } catch (RepositoryException $e) { | ||||
|                 return $this->json(4002, $e->getMessage()); | ||||
|             } catch (Exception $e) { | ||||
|                 CommonRepository::log('保证金充值失败', $e); | ||||
|                 return $this->json(5001, '充值失败'); | ||||
|             } | ||||
|             return $this->json(); | ||||
|         } | ||||
| 
 | ||||
|         return $this->json(4002, '请求方式错误'); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 充值 | ||||
|      * | ||||
|      * @return Json | ||||
|      * @throws GuzzleException | ||||
|      */ | ||||
|     public function rechargeAmount(): Json | ||||
|     { | ||||
|         if ($this->request->isPost()) { | ||||
|             $accountId = $this->auth['id'] ?? 0; | ||||
|             $amount    = input('post.amount', 0); | ||||
|             $type      = input('post.type/s'); | ||||
|             if (!$accountId) { | ||||
|                 return $this->json(4001, '请先登录'); | ||||
|             } | ||||
| 
 | ||||
|             try { | ||||
|                 $qr = AccountRepository::getInstance()->recharge($accountId, (float) $amount, $type); | ||||
|                 return $this->json(0, 'success', ['payment_order_number' => $qr['order_id'], 'code_url' => $qr['qr']]); | ||||
|             } catch (Exception $e) { | ||||
|                 CommonRepository::log('充值失败', $e); | ||||
|                 return $this->json(5001, '充值失败:'.$e->getMessage()); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         return $this->json(4002, '请求方式错误'); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 重新充值 | ||||
|      * | ||||
|      * @return Json | ||||
|      * @throws GuzzleException | ||||
|      */ | ||||
|     public function rechargeAgain(): Json | ||||
|     { | ||||
|         if ($this->request->isPost()) { | ||||
|             $accountId = $this->auth['id'] ?? 0; | ||||
|             $orderId   = input('post.order_id', 0); | ||||
|             $type      = input('post.type/s'); | ||||
|             if (!$accountId) { | ||||
|                 return $this->json(4001, '请先登录'); | ||||
|             } | ||||
| 
 | ||||
|             try { | ||||
|                 $qr = AccountRepository::getInstance()->rechargeAgain($accountId, $orderId, $type); | ||||
|                 return $this->json(0, 'success', ['payment_order_number' => $qr['order_id'], 'code_url' => $qr['qr']]); | ||||
|             } catch (Exception $e) { | ||||
|                 CommonRepository::log('充值失败', $e); | ||||
|                 return $this->json(5001, '充值失败:'.$e->getMessage()); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         return $this->json(4002, '请求方式错误'); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 查询订单 | ||||
|      * | ||||
|      * @return array|Json | ||||
|      * @throws DataNotFoundException | ||||
|      * @throws DbException | ||||
|      * @throws ModelNotFoundException | ||||
|      */ | ||||
|     public function checkPayment() | ||||
|     { | ||||
|         if ($this->request->isPost()) { | ||||
|             $res['code']         = 0; | ||||
|             $res['msg']          = 'success'; | ||||
|             $res['data']['paid'] = true; | ||||
|             $orderId             = input('post.order_id/s', '');    //订单ID
 | ||||
|             $type                = input('post.type/s', 'all');        //支付方式
 | ||||
| 
 | ||||
|             if (!$orderId || !$type) { | ||||
|                 $res['code'] = 1; | ||||
|                 $res['msg']  = '参数错误'; | ||||
|                 return $res; | ||||
|             } | ||||
| 
 | ||||
|             //根据支付类型 请求接口查询订单
 | ||||
|             $hasPaid = AccountRepository::getInstance()->hasPaid($orderId, $type); | ||||
|             if ($hasPaid) { | ||||
|                 AccountRepository::getInstance()->paymentLogPaid($orderId, $type); | ||||
|             } | ||||
|             $res['data']['paid'] = $hasPaid; | ||||
|             return $res; | ||||
|         } | ||||
| 
 | ||||
|         return $this->json(1, '非法请求!'); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 提现 | ||||
|      * | ||||
|      * @return Json | ||||
|      */ | ||||
|     public function withdrawal(): Json | ||||
|     { | ||||
|         if ($this->request->isPost()) { | ||||
|             $amount    = input('post.amount', ''); | ||||
|             $accountId = $this->auth['id'] ?? 0; | ||||
| 
 | ||||
|             try { | ||||
|                 AccountRepository::getInstance()->withdrawal($accountId, $amount); | ||||
|                 return $this->json(); | ||||
|             } catch (Exception $e) { | ||||
|                 CommonRepository::log('提现失败', $e); | ||||
|                 return $this->json(5001, '提现失败'); | ||||
|             } | ||||
| 
 | ||||
|         } | ||||
| 
 | ||||
|         return $this->json(1, '非法请求!'); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 获取已有订单号的支付二维码 | ||||
|      * | ||||
|      * @return Json | ||||
|      * @throws GuzzleException | ||||
|      */ | ||||
|     public function getPaymentQr(): Json | ||||
|     { | ||||
|         if ($this->request->isPost()) { | ||||
|             $type    = input('post.type', ''); | ||||
|             $orderId = input('post.order_id', ''); | ||||
| 
 | ||||
|             try { | ||||
|                 $codeQr = OrderRepository::getInstance()->generatePaymentQrCode($type, $orderId); | ||||
|                 return $this->json(0, 'success', ['payment_order_number' => $orderId, 'code_url' => $codeQr]); | ||||
|             } catch (Exception $e) { | ||||
|                 CommonRepository::log('获取支付二维码', $e); | ||||
|                 return $this->json(5001, '获取支付二维码'); | ||||
|             } | ||||
| 
 | ||||
|         } | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 物流查询 | ||||
|      * | ||||
|      * @return Json | ||||
|      * @throws DataNotFoundException | ||||
|      * @throws DbException | ||||
|      * @throws ModelNotFoundException | ||||
|      */ | ||||
|     public function logistics(): Json | ||||
|     { | ||||
|         $orderId = input('post.order_id'); | ||||
|         $type    = input('post.type', 'goods'); | ||||
| 
 | ||||
|         //        $com = 'shunfeng';
 | ||||
|         //        $num = 'SF1980860132707';
 | ||||
| 
 | ||||
|         if ($type == 'goods') { | ||||
|             if (!$delivery = OrderRepository::getInstance()->findExpressByOrder($orderId)) { | ||||
|                 return $this->json(4001, '物流信息不存在'); | ||||
|             } | ||||
|         } else { | ||||
|             if (!$delivery = OrderRepository::getInstance()->findExpressByAuction($orderId)) { | ||||
|                 return $this->json(4001, '物流信息不存在'); | ||||
|             } | ||||
|         } | ||||
|         $com = $delivery['express_code']; | ||||
|         $num = $delivery['express_number']; | ||||
| 
 | ||||
|         return $this->json(0, 'success', ['res' => Kd100::query($com, $num)]); | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,99 @@ | |||
| <?php | ||||
| 
 | ||||
| namespace app\controller; | ||||
| 
 | ||||
| use app\model\{Archives as MArticle, Category}; | ||||
| use think\facade\View; | ||||
| 
 | ||||
| class Article extends Base | ||||
| { | ||||
|     //详情
 | ||||
|     public function detail($id = 0) | ||||
|     { | ||||
| 
 | ||||
|         if ($id <= 0) { | ||||
|             return $this->error('错误页面'); | ||||
|         } | ||||
|         $article = MArticle::getById($id); | ||||
|         if (empty($article)) { | ||||
|             return $this->error('无此文章'); | ||||
|         } | ||||
|         MArticle::updateById($id, ['views' => $article['views'] + 1]); | ||||
|         $category = Category::getById($article['category_id']); | ||||
|         $prev = MArticle::getPrevArticleByIdAndCategoryId($id, $article['category_id']); | ||||
|         $next = MArticle::getNextArticleByIdAndCategoryId($id, $article['category_id']); | ||||
| 
 | ||||
|         $keywords = $article['seo_keywords'] ?: $this->system['seo_keywords']; | ||||
|         $description = $article['seo_description'] ?: $this->system['seo_description']; | ||||
|         $this->setSeo($article['title'], $keywords, $description); | ||||
|         $this->data['article'] = $article; | ||||
|         $this->data['category'] = $category; | ||||
|         $this->data['categoryId'] = $category['id']; | ||||
|         $this->data['prev'] = $prev; | ||||
|         $this->data['next'] = $next; | ||||
|         return $this->view($category['template_detail'] ?? ''); | ||||
|     } | ||||
| 
 | ||||
|     //列表页
 | ||||
|     public function index() | ||||
|     { | ||||
|         $categoryId = input('category_id/d', 0); | ||||
|         if ($categoryId <= 0) { | ||||
|             return $this->error('错误页面'); | ||||
|         } | ||||
|         $category = Category::getById($categoryId); | ||||
|         $page_size = 20; | ||||
|         if( $category['number'])$page_size= $category['number']; | ||||
| 
 | ||||
|         if( $this->request->param("page_size/d")){ | ||||
|             $page_size= $this->request->param("page_size/d"); | ||||
|             cookie("article_page_size",$this->request->param("page_size/d")); | ||||
|         }else{ | ||||
|             if( cookie("?article_page_size"))$page_size=  cookie("article_page_size"); | ||||
|         } | ||||
| 
 | ||||
|         if (empty($category)) { | ||||
|             return $this->error('错误页面'); | ||||
|         } | ||||
|         $description = $category['description'] ?: $this->system['seo_description']; | ||||
|         $this->setSeo($category['title'], $this->system['seo_keywords'], $description); | ||||
|         $this->data['items'] = MArticle::getListPageByCategory($categoryId, $page_size); | ||||
|         $this->data['category'] = $category; | ||||
|         $this->data['categoryId'] = $categoryId; | ||||
|         $this->data['page_size'] = $page_size; | ||||
|         $this->data['article_count'] = MArticle::getListCount($categoryId); | ||||
| 
 | ||||
|         return $this->view($category['template_list'] ?? ''); | ||||
|     } | ||||
| 
 | ||||
|     //查询
 | ||||
|     public function query(): \think\response\View | ||||
|     { | ||||
|         $keyword = $this->request->param("keyword/s"); | ||||
|         //无key值跳转到产品
 | ||||
|         if (!$keyword) $this->redirect((string)url('/articles/12.html')); | ||||
| 
 | ||||
|         $where = [ | ||||
|             ['category_id', 'in', [5, 12, 13, 14, 15]], | ||||
|             ['status', '=', 1], | ||||
|         ]; | ||||
| 
 | ||||
|         $where[] = ['title', 'like', '%' . $keyword . '%']; | ||||
|         $param['keyword'] = $keyword; | ||||
| 
 | ||||
|         $paginate = [ | ||||
|             'list_rows' => 20, | ||||
|             'query' => $param | ||||
|         ]; | ||||
|         $data = MArticle::where($where) | ||||
|             ->order("sort desc") | ||||
|             ->paginate($paginate, false); | ||||
| 
 | ||||
|         View::assign("items", $data); | ||||
|         View::assign("keyword", $keyword); | ||||
|         $this->data['category'] = Category::getById(5); | ||||
|         $this->data['categoryId'] = 5; | ||||
|         return $this->view("/article/product_query"); | ||||
|     } | ||||
| 
 | ||||
| } | ||||
|  | @ -0,0 +1,48 @@ | |||
| <?php | ||||
| 
 | ||||
| namespace app\controller; | ||||
| 
 | ||||
| use app\model\Category; | ||||
| use app\model\Link; | ||||
| use app\model\System; | ||||
| use app\repository\BlockRepository; | ||||
| use app\repository\CmsRepository; | ||||
| 
 | ||||
| /** | ||||
|  * 控制器基础类 | ||||
|  */ | ||||
| class Base extends BaseController | ||||
| { | ||||
|     //需要向模板传递的值
 | ||||
|     protected $data = []; | ||||
|     //系统配置信息
 | ||||
|     protected $system = []; | ||||
| 
 | ||||
|     protected $auth = []; | ||||
| 
 | ||||
|     protected $authId = 0; | ||||
| 
 | ||||
|     protected $aboutCategory = []; | ||||
| 
 | ||||
|     // 初始化
 | ||||
|     protected function initialize() | ||||
|     { | ||||
|         $this->auth                = session('frontend_auth') ?? []; | ||||
|         $this->data['auth']        = $this->auth; | ||||
|         $this->authId              = $this->auth['id'] ?? 0; | ||||
|     } | ||||
| 
 | ||||
|     //设置SEO信息
 | ||||
|     protected function setSeo($title = '', $keywords = '', $description = '') | ||||
|     { | ||||
|         $this->data['seoTitle']       = $title ?: $this->system['seo_title'] ?? ''; | ||||
|         $this->data['seoKeywords']    = $keywords ?: $this->system['seo_keywords'] ?? ''; | ||||
|         $this->data['seoDescription'] = $description ?: $this->system['seo_description'] ?? ''; | ||||
|     } | ||||
| 
 | ||||
|     //模板
 | ||||
|     protected function view($template = '') | ||||
|     { | ||||
|         return view($template)->assign($this->data); | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,254 @@ | |||
| <?php | ||||
| declare (strict_types=1); | ||||
| 
 | ||||
| namespace app\controller; | ||||
| 
 | ||||
| use think\{App, Request, response\Json, response\Redirect, response\View, Validate}; | ||||
| use Exception; | ||||
| use think\exception\ValidateException; | ||||
| 
 | ||||
| /** | ||||
|  * 控制器基础类 | ||||
|  */ | ||||
| abstract class BaseController | ||||
| { | ||||
|     /** | ||||
|      * 无需登录的方法,同时也就不需要鉴权了 | ||||
|      * | ||||
|      * @var array | ||||
|      */ | ||||
|     protected $noNeedLogin = []; | ||||
| 
 | ||||
|     /** | ||||
|      * 无需鉴权的方法,但需要登录 | ||||
|      * | ||||
|      * @var array | ||||
|      */ | ||||
|     protected $noNeedRight = []; | ||||
| 
 | ||||
|     /** | ||||
|      * Request实例 | ||||
|      * @var Request | ||||
|      */ | ||||
|     protected $request; | ||||
| 
 | ||||
|     /** | ||||
|      * 应用实例 | ||||
|      * @var App | ||||
|      */ | ||||
|     protected $app; | ||||
| 
 | ||||
|     /** | ||||
|      * 是否批量验证 | ||||
|      * @var bool | ||||
|      */ | ||||
|     protected $batchValidate = false; | ||||
| 
 | ||||
|     /** | ||||
|      * 控制器中间件 | ||||
|      * @var array | ||||
|      */ | ||||
|     protected $middleware = []; | ||||
| 
 | ||||
|     /** | ||||
|      * 构造方法 | ||||
|      * @access public | ||||
|      * @param  App  $app  应用对象 | ||||
|      */ | ||||
|     public function __construct(App $app) | ||||
|     { | ||||
|         $this->app     = $app; | ||||
|         $this->request = $this->app->request; | ||||
| 
 | ||||
|         // 控制器初始化
 | ||||
|         $this->initialize(); | ||||
|     } | ||||
| 
 | ||||
|     // 初始化
 | ||||
|     protected function initialize() | ||||
|     { | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 验证数据 | ||||
|      * @access protected | ||||
|      * @param  array  $data  数据 | ||||
|      * @param  string|array  $validate  验证器名或者验证规则数组 | ||||
|      * @param  array  $message  提示信息 | ||||
|      * @param  bool  $batch  是否批量验证 | ||||
|      * @return array|string|true | ||||
|      * @throws ValidateException | ||||
|      */ | ||||
|     protected function validate(array $data, $validate, array $message = [], bool $batch = false) | ||||
|     { | ||||
|         if (is_array($validate)) { | ||||
|             $v = new Validate(); | ||||
|             $v->rule($validate); | ||||
|         } else { | ||||
|             if (strpos($validate, '.')) { | ||||
|                 // 支持场景
 | ||||
|                 list($validate, $scene) = explode('.', $validate); | ||||
|             } | ||||
|             $class = false !== strpos($validate, '\\') ? $validate : $this->app->parseClass('validate', $validate); | ||||
|             $v     = new $class(); | ||||
|             if (!empty($scene)) { | ||||
|                 $v->scene($scene); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         $v->message($message); | ||||
| 
 | ||||
|         // 是否批量验证
 | ||||
|         if ($batch || $this->batchValidate) { | ||||
|             $v->batch(true); | ||||
|         } | ||||
| 
 | ||||
|         return $v->failException(true)->check($data); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 验证器 | ||||
|      * | ||||
|      * @param  array  $data | ||||
|      * @param $validate | ||||
|      * @param  array  $message | ||||
|      * @param  bool  $batch | ||||
|      * @return Json|bool | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     protected function validateByApi(array $data, $validate, array $message = [], bool $batch = false) | ||||
|     { | ||||
|         try { | ||||
|             $this->validate($data, $validate, $message, $batch); | ||||
|             return true; | ||||
|         } catch (ValidateException $e) { | ||||
|             $msg = $e->getMessage(); | ||||
|             if ($batch) { | ||||
|                 $msg = implode(',', $e->getError()); | ||||
|             } | ||||
| 
 | ||||
|             return $this->json(4000, $msg); | ||||
|         } catch (Exception $e) { | ||||
|             throw $e; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 验证器 | ||||
|      * | ||||
|      * @param  array  $data | ||||
|      * @param $validate | ||||
|      * @param  array  $message | ||||
|      * @param  bool  $batch | ||||
|      * @return Redirect | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     protected function validateByView(array $data, $validate, array $message = [], bool $batch = false): Redirect | ||||
|     { | ||||
|         try { | ||||
|             $this->validate($data, $validate, $message, $batch); | ||||
|         } catch (ValidateException $e) { | ||||
|             $msg = $e->getMessage(); | ||||
|             if ($batch) { | ||||
|                 $msg = implode(',', $e->getError()); | ||||
|             } | ||||
| 
 | ||||
|             return $this->error( $msg); | ||||
|         } catch (Exception $e) { | ||||
|             throw $e; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 操作成功跳转的快捷方法 | ||||
|      * @access protected | ||||
|      * @param  mixed  $msg  提示信息 | ||||
|      * @param  string|null  $url  跳转的URL地址 | ||||
|      * @param  mixed  $data  返回的数据 | ||||
|      * @param  integer  $wait  跳转等待时间 | ||||
|      * @param  array  $header  发送的Header信息 | ||||
|      * @return Redirect | ||||
|      */ | ||||
|     protected function success($msg = '', string $url = null, $data = '', int $wait = 3, array $header = []): Redirect | ||||
|     { | ||||
|         if (is_null($url) && isset($_SERVER["HTTP_REFERER"])) { | ||||
|             $url = $_SERVER["HTTP_REFERER"]; | ||||
|         } elseif ($url) { | ||||
|             $url = (strpos($url, '://') || 0 === strpos($url, '/')) ? $url : $this->app->route->buildUrl($url); | ||||
|         } | ||||
| 
 | ||||
|         $result = [ | ||||
|             'code' => 1, | ||||
|             'msg'  => $msg, | ||||
|             'data' => $data, | ||||
|             'url'  => $url, | ||||
|             'wait' => $wait, | ||||
|         ]; | ||||
|         return $this->redirect(url('error/404', $result)); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 操作错误跳转的快捷方法 | ||||
|      * @access protected | ||||
|      * @param  mixed  $msg  提示信息 | ||||
|      * @param  string|null  $url  跳转的URL地址 | ||||
|      * @param  mixed  $data  返回的数据 | ||||
|      * @param  integer  $wait  跳转等待时间 | ||||
|      * @return Redirect | ||||
|      */ | ||||
|     protected function error($msg = '', string $url = null, $data = '', int $wait = 3): Redirect | ||||
|     { | ||||
|         if (is_null($url)) { | ||||
|             $referer = $_SERVER['HTTP_REFERER'] ?? null; | ||||
|             if (empty($referer)) { | ||||
|                 $url = $this->request->isAjax() ? '' : '/'; | ||||
|             } else { | ||||
|                 $url = $this->request->isAjax() ? '' : 'javascript:history.back(-1);'; | ||||
|             } | ||||
|         } elseif ($url) { | ||||
|             $url = (strpos($url, '://') || 0 === strpos($url, '/')) ? $url : $this->app->route->buildUrl($url); | ||||
|         } | ||||
|         $result = [ | ||||
|             'code' => 0, | ||||
|             'msg'  => $msg, | ||||
|             'data' => $data, | ||||
|             'url'  => $url, | ||||
|             'wait' => $wait, | ||||
|         ]; | ||||
| 
 | ||||
|         return $this->redirect(url('error/404', $result)); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 返回封装后的API数据到客户端 | ||||
|      * 以json格式抛出异常 | ||||
|      * @access protected | ||||
|      * @param  integer  $code  返回的code | ||||
|      * @param  mixed  $msg  提示信息 | ||||
|      * @param  mixed  $data  要返回的数据 | ||||
|      * @return Json | ||||
|      */ | ||||
|     protected function json(int $code = 0, $msg = '操作成功', $data = []): Json | ||||
|     { | ||||
|         $result = [ | ||||
|             'code' => $code, | ||||
|             'msg'  => $msg, | ||||
|             'data' => $data | ||||
|         ]; | ||||
|         return json($result); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * URL重定向 | ||||
|      * @access protected | ||||
|      * @param  string  $url  跳转的URL表达式 | ||||
|      * @return Redirect | ||||
|      */ | ||||
|     protected function redirect($url): Redirect | ||||
|     { | ||||
|         if (!is_string($url)) { | ||||
|             $url = $url->__toString(); | ||||
|         } | ||||
|         return redirect($url); | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,26 @@ | |||
| <?php | ||||
| 
 | ||||
| namespace app\controller; | ||||
| 
 | ||||
| use app\repository\BlockRepository; | ||||
| use Exception; | ||||
| use think\response\View; | ||||
| use app\repository\OperationRepository; | ||||
| 
 | ||||
| class Contact extends Base | ||||
| { | ||||
|     /** | ||||
|      * @return View | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public function index(): View | ||||
|     { | ||||
|         $position = ['contact_banner']; | ||||
|         $slides   = OperationRepository::getInstance()->slideListByPosition($position); | ||||
| 
 | ||||
|         $this->data['blocks'] = BlockRepository::getInstance()->getByCateName(BlockRepository::CATEGORY_CONTACT); | ||||
|         $this->data['slide']  = $slides; | ||||
|         $this->setSeo(); | ||||
|         return $this->view(); | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,48 @@ | |||
| <?php | ||||
| 
 | ||||
| 
 | ||||
| namespace app\controller; | ||||
| 
 | ||||
| 
 | ||||
| class Error extends BaseController | ||||
| { | ||||
|     public function __call($method, $args) | ||||
|     { | ||||
|         if(request()->isAjax()) { | ||||
|             return $this->json(4004, 'error request!'); | ||||
|         } else { | ||||
|             $referer = $_SERVER['HTTP_REFERER'] ?? null; | ||||
|             if (empty($referer)) { | ||||
|                 $url = '/'; | ||||
|             } else { | ||||
|                 $domain = $this->request->domain(); | ||||
|                 $urlInfo = parse_url($referer); | ||||
|                 $scheme = $urlInfo['scheme'] ?? ''; | ||||
|                 $requestSrc = ''; | ||||
|                 if (!empty($scheme)) { | ||||
|                     $requestSrc = $scheme.'://'.($urlInfo['host'] ?? ''); | ||||
|                 } | ||||
|                 if($domain != $requestSrc) { | ||||
|                     $url = '/'; | ||||
|                 } else { | ||||
|                     $url = 'javascript:history.back(-1);'; | ||||
|                 } | ||||
|             } | ||||
|             $result = [ | ||||
|                 'code' => 404, | ||||
|                 'msg'  => '无效请求! 没有找到相关资源', | ||||
|                 'data' => [], | ||||
|                 'url'  => $url, | ||||
|                 'wait' => 5, | ||||
|             ]; | ||||
|             return view('/manager/error/jump')->assign($result); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     public function jump() | ||||
|     { | ||||
|         $param = request()->param(); | ||||
|         return view()->assign($param); | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,101 @@ | |||
| <?php | ||||
| 
 | ||||
| namespace app\controller; | ||||
| 
 | ||||
| use app\repository\OrderRepository; | ||||
| use app\service\wx\WechatPay; | ||||
| use Exception; | ||||
| use think\facade\Log; | ||||
| use think\response\Redirect; | ||||
| 
 | ||||
| class Index extends Base | ||||
| { | ||||
|     /** | ||||
|      * @return Redirect | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public function index(): Redirect | ||||
|     { | ||||
|         return $this->redirect('/manager'); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 退出 | ||||
|      * | ||||
|      * @return Redirect | ||||
|      */ | ||||
|     public function logout(): Redirect | ||||
|     { | ||||
|         session('frontend_auth', null); | ||||
|         $req = $this->request->header('referer'); | ||||
|         return $this->redirect($req); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 微信的回调 | ||||
|      * | ||||
|      * @throws \EasyWeChat\Kernel\Exceptions\Exception | ||||
|      */ | ||||
|     public function callback() | ||||
|     { | ||||
|         if ($this->request->isPost()) { | ||||
|             $app      = WechatPay::getInstance(); | ||||
|             $response = $app->handlePaidNotify(function ($message, $fail) { | ||||
|                 //                $aa = '{"appid":"wxa02e44170bc722cd","bank_type":"OTHERS","cash_fee":"1","fee_type":"CNY","is_subscribe":"N","mch_id":"1605090111","nonce_str":"60f7d8a1e4ac8","openid":"oKrEm0ehgsy2ZTWzEva4tbLuUgFw","out_trade_no":"16268555858753004863","result_code":"SUCCESS","return_code":"SUCCESS","sign":"DB3F6CDCB7FBB3B9DDF7C0CC8BBD5AAD","time_end":"20210721162000","total_fee":"1","trade_type":"JSAPI","transaction_id":"4200001200202107217942681078"}';
 | ||||
|                 //                $message = json_decode($aa, true);
 | ||||
|                 $m     = json_encode($message, JSON_UNESCAPED_UNICODE); | ||||
|                 if (!$order = OrderRepository::getInstance()->findOneByWhere(['coding' => $message['out_trade_no']])) { | ||||
|                     $this->log(sprintf("[微信支付回调][%s][%s]订单支付成功,但系统查无此订单 info:%s", date('Y-m-d H:i:s'), $message['out_trade_no'], $m), 'error'); | ||||
|                     return true;//订单不存在
 | ||||
|                 } | ||||
| 
 | ||||
|                 //记录日志
 | ||||
|                 $this->log(sprintf("[微信支付回调][%s][%s]订单支付成功 info:%s", date('Y-m-d H:i:s'), $message['out_trade_no'], $m), 'info'); | ||||
| 
 | ||||
|                 if ($message['return_code'] === 'SUCCESS') { // return_code 表示通信状态,不代表支付状态
 | ||||
|                     //更改订单状态
 | ||||
|                     try { | ||||
|                         $res = false; | ||||
|                         // 用户是否支付成功
 | ||||
|                         if (isset($message['result_code']) && $message['result_code'] === 'SUCCESS') { | ||||
|                             //记录日志
 | ||||
|                             $res = OrderRepository::getInstance()->setPaid($order['coding']); | ||||
| 
 | ||||
|                             $this->log(sprintf("[微信支付回调][%s][%s]订单支付成功 修改订单状态为%s", date('Y-m-d H:i:s'), $message['out_trade_no'], $res), 'info'); | ||||
| 
 | ||||
|                             // 用户支付失败
 | ||||
|                         } elseif (isset($message['result_code']) && $message['result_code'] === 'FAIL') { | ||||
|                             //记录日志
 | ||||
|                             $this->log(sprintf("[微信支付回调][%s][%s]订单支付失败 修改订单状态为%s", date('Y-m-d H:i:s'), $message['out_trade_no'], $res), 'info'); | ||||
|                         } | ||||
| 
 | ||||
|                         if (!$res) { | ||||
|                             return $fail('Order status edit failed.'); | ||||
|                         } | ||||
|                     } catch (Exception $e) { | ||||
|                         $this->log(sprintf("[微信支付回调][%s][%s]订单支付失败 失败原因:%s", date('Y-m-d H:i:s'), $message['out_trade_no'], $e->getMessage()), 'info'); | ||||
|                         //错误信息 触发
 | ||||
|                         return $fail('Order error.'); | ||||
|                     } | ||||
|                 } else { | ||||
|                     return $fail('通信失败,请稍后再通知我'); | ||||
|                 } | ||||
| 
 | ||||
|                 return true; | ||||
|             }); | ||||
| 
 | ||||
|             $response->send(); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 记录订单日志 | ||||
|      * | ||||
|      * @param string $message | ||||
|      * @param string $type | ||||
|      */ | ||||
|     private function log(string $message, string $type = 'info'): void | ||||
|     { | ||||
|         Log::channel('order')->write($message, $type); | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,283 @@ | |||
| <?php | ||||
| 
 | ||||
| namespace app\controller; | ||||
| 
 | ||||
| use app\exception\RepositoryException; | ||||
| use app\repository\CommonRepository; | ||||
| use app\validate\Account as VAccount; | ||||
| use app\repository\AccountRepository; | ||||
| use Exception; | ||||
| use Overtrue\Socialite\SocialiteManager; | ||||
| use think\db\exception\DataNotFoundException; | ||||
| use think\db\exception\DbException; | ||||
| use think\db\exception\ModelNotFoundException; | ||||
| use think\facade\Config; | ||||
| use think\facade\Log; | ||||
| use think\response\Json; | ||||
| use think\response\Redirect; | ||||
| use think\response\View; | ||||
| 
 | ||||
| class Login extends Base | ||||
| { | ||||
|     protected $middleware = ['csrf']; | ||||
| 
 | ||||
|     public function index() | ||||
|     { | ||||
|         $referer = input('param.url/s', '/'); | ||||
|         $referer = urldecode($referer); | ||||
|         $auth    = session('frontend_auth'); | ||||
|         if ($auth) { | ||||
|             return $this->redirect($referer); | ||||
|         } | ||||
|         session('login_return', $referer); | ||||
|         if ($this->request->isPost()) { | ||||
|             $username = input('post.username/s'); | ||||
|             $password = input('post.password/s'); | ||||
|             if (empty($username) || empty($password)) { | ||||
|                 return $this->json(4001, '参数错误'); | ||||
|             } | ||||
| 
 | ||||
|             $user = AccountRepository::getInstance()->infoByPhone($username); | ||||
|             if (!$user) { | ||||
|                 if (!$user = AccountRepository::getInstance()->infoByUsername($username)) { | ||||
|                     return $this->json(4002, '账号或密码错误'); | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             if ($user['password'] !== md5($password)) { | ||||
|                 return $this->json(4003, '密码错误!若手机验证码方式注册,初始密码为手机号后6位!'); | ||||
|             } | ||||
| 
 | ||||
|             unset($user['password']); | ||||
|             session('frontend_auth', $user->toArray()); | ||||
|             $referer = session('login_return') ?? '/'; | ||||
|             return $this->json(0, 'success', ['login_return' => $referer]); | ||||
|         } | ||||
| 
 | ||||
|         return $this->view(); | ||||
|     } | ||||
| 
 | ||||
|     public function phone() | ||||
|     { | ||||
|         $referer = input('param.url/s', '/'); | ||||
|         $referer = urldecode($referer); | ||||
|         $auth    = session('frontend_auth'); | ||||
|         if ($auth) { | ||||
|             return $this->redirect($referer); | ||||
|         } | ||||
|         session('login_return', $referer); | ||||
|         if ($this->request->isPost()) { | ||||
|             $phone = input('post.phone/s'); | ||||
|             $code  = input('post.code/s'); | ||||
|             if (empty($phone) || empty($code)) { | ||||
|                 return $this->json(4001, '参数错误'); | ||||
|             } | ||||
| 
 | ||||
|             if (!CommonRepository::getInstance()->checkSms($phone, $code, CommonRepository::SMS_TYPE_LOGIN)) { | ||||
|                 return $this->json(4002, '短信验证码错误'); | ||||
|             } | ||||
| 
 | ||||
|             $user = AccountRepository::getInstance()->infoByPhone($phone); | ||||
|             if (!$user) { | ||||
|                 $password           = substr(trim($phone), -6); | ||||
|                 $data['mobile']     = $phone; | ||||
|                 $data['password']   = md5($password); | ||||
|                 $data['nickname']   = trim($phone); | ||||
|                 $data['status']     = 'normal'; | ||||
|                 $data['created_at'] = date('Y-m-d H:i:s'); | ||||
|                 $user               = AccountRepository::getInstance()->create($data); | ||||
|             } | ||||
| 
 | ||||
|             session('frontend_auth', $user); | ||||
|             $referer = session('login_return') ?? '/'; | ||||
|             return $this->json(0, 'success', ['login_return' => $referer]); | ||||
|         } | ||||
| 
 | ||||
|         return $this->view(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 微信登录 | ||||
|      * | ||||
|      * @return Redirect|View | ||||
|      * @throws DataNotFoundException | ||||
|      * @throws DbException | ||||
|      * @throws ModelNotFoundException | ||||
|      * @throws RepositoryException | ||||
|      */ | ||||
|     public function wechat() | ||||
|     { | ||||
|         $code = input('code/s'); | ||||
|         Config::load('extra/wechat', 'wechat'); | ||||
|         $wechatConfig = config('wechat'); | ||||
| 
 | ||||
|         $referer = session('login_return') ?? '/'; | ||||
|         if ($this->auth) { | ||||
|             return $this->redirect($referer); | ||||
|         } else { | ||||
|             if ($code) { | ||||
|                 $config = [ | ||||
|                     'wechat' => [ | ||||
|                         'client_id'     => $wechatConfig['openAppId'], | ||||
|                         'client_secret' => $wechatConfig['openAppSecret'], | ||||
|                         'redirect'      => $wechatConfig['open_notify_url'], | ||||
|                     ], | ||||
|                 ]; | ||||
| 
 | ||||
|                 $socialite = new SocialiteManager($config); | ||||
| 
 | ||||
|                 $user = $socialite->driver('wechat')->user(); | ||||
| 
 | ||||
|                 $wechatUser = $user->getOriginal(); | ||||
|                 //                $wechatUser = [
 | ||||
|                 //                    'openid'     => 'o05Qy6rt1l7NOjrZsViC2bvS75j0',
 | ||||
|                 //                    'nickname'   => '拙言',
 | ||||
|                 //                    'sex'        => '1',
 | ||||
|                 //                    'language'   => 'language',
 | ||||
|                 //                    'city'       => 'chengdu ',
 | ||||
|                 //                    'province'   => '四川',
 | ||||
|                 //                    'country'    => '中国',
 | ||||
|                 //                    'headimgurl' => 'https://thirdwx.qlogo.cn/mmopen/vi_32/Q0j4TwGTfTIZib13lH3Sicc1BO189ibaqohRtXr3OuHw3xSHibn611kaGmmLvppOD5hHyE5IJmicTDpdwCEDw4LF9Xw/132',
 | ||||
|                 //                    'unionid'    => 'oIrzJv6Vk8s8Hg_rJuNB8muquziw',
 | ||||
|                 //                ];
 | ||||
|                 if (empty($wechatUser)) { | ||||
| 
 | ||||
|                 } | ||||
|                 $account = AccountRepository::getInstance()->findOneByWhere(['unionid' => $wechatUser['unionid']]); | ||||
|                 $data    = []; | ||||
|                 $now     = date('Y-m-d H:i:s'); | ||||
|                 if (!$account) { | ||||
|                     //无账号 新建账号
 | ||||
|                     $data               = $wechatUser; | ||||
|                     $data['created_at'] = $now; | ||||
|                     $data['status']     = AccountRepository::STATUS_NORMAL; | ||||
|                     $account            = AccountRepository::getInstance()->create($wechatUser); | ||||
|                 } | ||||
| 
 | ||||
|                 $data['login_ip']   = $this->request->ip(); | ||||
|                 $data['last_login'] = $now; | ||||
|                 session('frontend_auth', $account->toArray()); | ||||
|                 $account->save($data); | ||||
|                 if (empty($account['mobile'])) { | ||||
|                     //没有手机号 跳转绑定
 | ||||
|                     return $this->redirect('/login/binding'); | ||||
|                 } | ||||
|                 return $this->redirect($referer); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         $openAppId = $wechatConfig['openAppId'] ?? ''; | ||||
|         $redirect  = $wechatConfig['open_notify_url'] ?? ''; | ||||
| 
 | ||||
|         $this->data['redirect']  = urlencode($redirect); | ||||
|         $this->data['openAppId'] = $openAppId; | ||||
|         return $this->view(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 常规注册 | ||||
|      * | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public function register(): Json | ||||
|     { | ||||
|         if ($this->request->isPost()) { | ||||
|             $post     = input('post.'); | ||||
|             $validate = new VAccount(); | ||||
|             if (!$validate->scene('register')->check($post)) { | ||||
|                 return $this->json(4001, $validate->getError()); | ||||
|             } | ||||
| 
 | ||||
|             if (!CommonRepository::getInstance()->checkSms($post['phone'], $post['code'], CommonRepository::SMS_TYPE_REGISTER)) { | ||||
|                 return $this->json(4002, '验证码错误'); | ||||
|             } | ||||
| 
 | ||||
|             try { | ||||
|                 AccountRepository::getInstance()->registerByNormal($post); | ||||
|             } catch (RepositoryException $e) { | ||||
|                 return $this->json(4003, $e->getMessage()); | ||||
|             } catch (Exception $e) { | ||||
|                 Log::error(sprintf("[注册失败]%s:%s %s", $e->getFile(), $e->getLine(), $e->getMessage())); | ||||
|                 return $this->json(5001, '注册失败'); | ||||
|             } | ||||
| 
 | ||||
|             return $this->json(); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 发送注册验证码 | ||||
|      * | ||||
|      * @return Json | ||||
|      */ | ||||
|     public function sms(): Json | ||||
|     { | ||||
|         $post     = input('post.'); | ||||
|         $validate = new VAccount(); | ||||
|         if (!$validate->scene('send_sms')->check($post)) { | ||||
|             return $this->json(4001, $validate->getError()); | ||||
|         } | ||||
| 
 | ||||
|         if (CommonRepository::getInstance()->sendSms($post['phone'], $post['type'])) { | ||||
|             return $this->json(); | ||||
|         } | ||||
| 
 | ||||
|         return $this->json(4002, '验证码发送失败'); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 绑定手机号 | ||||
|      * | ||||
|      * @return Redirect|Json|View | ||||
|      * @throws DataNotFoundException | ||||
|      * @throws DbException | ||||
|      * @throws ModelNotFoundException | ||||
|      * @throws RepositoryException | ||||
|      */ | ||||
|     public function binding() | ||||
|     { | ||||
|         if ($this->request->isPost()) { | ||||
|             $post     = input('post.'); | ||||
|             $validate = new VAccount(); | ||||
|             if (!$validate->scene('binding')->check($post)) { | ||||
|                 return $this->json(4001, $validate->getError()); | ||||
|             } | ||||
| 
 | ||||
|             if (!$account = AccountRepository::getInstance()->info($this->auth['id'] ?? 0)) { | ||||
|                 return $this->json(4006, '请先登录'); | ||||
|             } | ||||
| 
 | ||||
|             if (!empty($account['mobile'])) { | ||||
|                 return $this->json(4007, '您已绑定手机号,无需重复绑定!'); | ||||
|             } | ||||
| 
 | ||||
|             if (AccountRepository::getInstance()->infoByPhone($post['phone'])) { | ||||
|                 return $this->json(4005, '该手机已绑定账号'); | ||||
|             } | ||||
| 
 | ||||
|             if (!CommonRepository::getInstance()->checkSms($post['phone'], $post['code'], CommonRepository::SMS_TYPE_BINDING)) { | ||||
|                 return $this->json(4002, '验证码错误'); | ||||
|             } | ||||
| 
 | ||||
|             try { | ||||
|                 $account->save(['mobile' => $post['phone']]); | ||||
|             } catch (RepositoryException $e) { | ||||
|                 return $this->json(4003, $e->getMessage()); | ||||
|             } catch (Exception $e) { | ||||
|                 CommonRepository::log('绑定手机号失败', $e, 'error'); | ||||
|                 return $this->json(5001, '绑定手机号失败'); | ||||
|             } | ||||
| 
 | ||||
|             return $this->json(); | ||||
|         } else { | ||||
|             if (!$account = AccountRepository::getInstance()->info($this->auth['id'] ?? 0)) { | ||||
|                 return $this->redirect('/login'); | ||||
|             } | ||||
| 
 | ||||
|             if (!empty($account['mobile'])) { | ||||
|                 return $this->redirect('/'); | ||||
|             } | ||||
|         } | ||||
|         return $this->view(); | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,28 @@ | |||
| <?php | ||||
| namespace app\controller; | ||||
| 
 | ||||
| use app\model\{Category, Block}; | ||||
| 
 | ||||
| class Page extends Base | ||||
| { | ||||
|     public function index() | ||||
|     { | ||||
| 
 | ||||
|         $categoryId=$this->request->param("category_id"); | ||||
|         $category = Category::getById($this->request->param("category_id")); | ||||
| 
 | ||||
|         if ($category) { | ||||
|             $description = $category['description'] ?: $this->system['seo_description']; | ||||
|             $this->setSeo($category['title'], $this->system['seo_keywords'], $description); | ||||
|         } else { | ||||
|             return $this->error('错误页面'); | ||||
|         } | ||||
|         $childCategory = Category::getChildrenByParentId($categoryId); | ||||
| 
 | ||||
|         $this->data['categoryId'] = $categoryId; | ||||
|         $this->data['category'] = $category; | ||||
|         $this->data['childCategory'] = $childCategory; | ||||
|         $this->data['blocks'] = Block::getByCategoryId($categoryId); | ||||
|         return $this->view($category['template_detail']); | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,40 @@ | |||
| <?php | ||||
| 
 | ||||
| namespace app\controller; | ||||
| 
 | ||||
| use app\repository\AccountRepository; | ||||
| use app\repository\GoodsRepository; | ||||
| use app\repository\OperationRepository; | ||||
| use Exception; | ||||
| use think\response\View; | ||||
| 
 | ||||
| class Search extends Base | ||||
| { | ||||
|     /** | ||||
|      * 搜索 | ||||
|      * | ||||
|      * @return View | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public function index(): View | ||||
|     { | ||||
|         $tag                   = input('get.tag/s', 'goods'); | ||||
|         $keyword               = input('get.keyword/s', ''); | ||||
|         $pageParams['query'][] = input('get.'); | ||||
|         $where['size']         = 50; | ||||
|         $where['where'][]      = ['type', '=', $tag]; | ||||
|         $where['where'][]      = ['status', '=', GoodsRepository::STATUS_ON]; | ||||
|         $where['where'][]      = ['stock', '>', 0]; | ||||
|         $where['where'][]      = ['title', 'like', '%'.$keyword.'%']; | ||||
|         $items                 = GoodsRepository::getInstance()->findListWithPaginate($where, $pageParams); | ||||
| 
 | ||||
|         $position     = ['search_banner']; | ||||
|         $slides       = OperationRepository::getInstance()->slideListByPosition($position); | ||||
|         $collectedIds = $this->authId ? AccountRepository::getInstance()->getCollectedIds($this->authId, $tag) : []; | ||||
| 
 | ||||
|         $this->data['items']        = $items; | ||||
|         $this->data['collectedIds'] = $collectedIds; | ||||
|         $this->data['slide']        = $slides; | ||||
|         return $this->view(); | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,272 @@ | |||
| <?php | ||||
| 
 | ||||
| namespace app\controller\api; | ||||
| 
 | ||||
| use app\model\AccountRecord; | ||||
| use app\model\Disease; | ||||
| use app\repository\ArchivesRepository; | ||||
| use Exception; | ||||
| use think\db\exception\DataNotFoundException; | ||||
| use think\db\exception\DbException; | ||||
| use think\db\exception\ModelNotFoundException; | ||||
| use think\response\Json; | ||||
| use app\exception\RepositoryException; | ||||
| 
 | ||||
| class Archives extends Base | ||||
| { | ||||
|     protected $noNeedLogin = ['course', 'detail']; | ||||
| 
 | ||||
|     /** | ||||
|      * 病种列表 | ||||
|      * | ||||
|      * @return Json | ||||
|      * @throws DataNotFoundException | ||||
|      * @throws DbException | ||||
|      * @throws ModelNotFoundException | ||||
|      */ | ||||
|     public function disease(): Json | ||||
|     { | ||||
|         $data = Disease::getListByPid(); | ||||
| 
 | ||||
|         return $this->json(0, 'success', $data); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 病种问题文章列表 分类问题 | ||||
|      * | ||||
|      * @return Json | ||||
|      */ | ||||
|     public function diseaseQuestion(): Json | ||||
|     { | ||||
|         $diseaseId = input('disease_id/d', 0); | ||||
| 
 | ||||
|         try { | ||||
|             $data = ArchivesRepository::getInstance()->diseaseQuestion($diseaseId); | ||||
| 
 | ||||
|             return $this->json(0, 'success', $data); | ||||
|         } catch (RepositoryException $e) { | ||||
|             return $this->json(4001, $e->getMessage()); | ||||
|         } catch (Exception $e) { | ||||
|             ArchivesRepository::log($e->getMessage(), $e); | ||||
|             return $this->json(5000, '操作失败'); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 恒美小课堂 | ||||
|      * | ||||
|      * @return Json | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public function course(): Json | ||||
|     { | ||||
|         $accountId = $this->request->user['user_id'] ?? 0; | ||||
|         $courseId  = input('course_id/d', 0); | ||||
|         $page      = input('page/d', 1); | ||||
|         $size      = input('size/d', 20); | ||||
| 
 | ||||
|         try { | ||||
|             $data = ArchivesRepository::getInstance()->course($accountId, $courseId, $page, $size); | ||||
| 
 | ||||
|             return $this->json(0, 'success', $data); | ||||
|         } catch (RepositoryException $e) { | ||||
|             return $this->json(4001, $e->getMessage()); | ||||
|         } catch (Exception $e) { | ||||
|             ArchivesRepository::log($e->getMessage(), $e); | ||||
|             return $this->json(5000, '操作失败'); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 热门推荐 | ||||
|      * | ||||
|      * @return Json | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public function hot(): Json | ||||
|     { | ||||
|         $categoryId = input('category_id/d', 0); | ||||
|         $page       = input('page/d', 1); | ||||
|         $size       = input('size/d', 20); | ||||
|         $keyword    = input('keyword/s', ''); | ||||
|         $accountId  = $this->request->user['user_id'] ?? 0; | ||||
| 
 | ||||
|         try { | ||||
|             $where[] = ['hot', '=', 1]; | ||||
|             if (!empty($keyword)) { | ||||
| 
 | ||||
|                 $keyword = trim($keyword); | ||||
|                 $where[] = ['title|subtitle|disease_name|doctor_name', 'like', '%'.$keyword.'%']; | ||||
|                 AccountRecord::saveSearch($accountId, $keyword); | ||||
|             } | ||||
|             $data = ArchivesRepository::getInstance()->category($accountId, $categoryId, $where, $page, $size); | ||||
| 
 | ||||
|             return $this->json(0, 'success', $data); | ||||
|         } catch (RepositoryException $e) { | ||||
|             return $this->json(4001, $e->getMessage()); | ||||
|         } catch (Exception $e) { | ||||
|             ArchivesRepository::log($e->getMessage(), $e); | ||||
|             return $this->json(5000, '操作失败'); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 获取指定栏目内容列表 | ||||
|      * | ||||
|      * @return Json | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public function category(): Json | ||||
|     { | ||||
|         $categoryId = input('category_id/d', 0); | ||||
|         $page       = input('page/d', 1); | ||||
|         $size       = input('size/d', 20); | ||||
|         $keyword    = input('keyword/s', ''); | ||||
|         $diseaseIds = input('disease_id/s', '');//病种 多个用逗号分隔
 | ||||
|         $accountId  = $this->request->user['user_id'] ?? 0; | ||||
| 
 | ||||
|         try { | ||||
|             $where = []; | ||||
|             if (!empty($keyword)) { | ||||
|                 $keyword = trim($keyword); | ||||
|                 $where[] = ['title|subtitle|disease_name|doctor_name', 'like', '%'.$keyword.'%']; | ||||
|                 AccountRecord::saveSearch($accountId, $keyword); | ||||
|             } | ||||
| 
 | ||||
|             if (!empty($diseaseIds)) { | ||||
|                 $where[] = ['disease_id', 'in', explode(',', $diseaseIds)]; | ||||
|             } | ||||
| 
 | ||||
|             $data = ArchivesRepository::getInstance()->category($accountId, $categoryId, $where, $page, $size); | ||||
|             return $this->json(0, 'success', $data); | ||||
|         } catch (RepositoryException $e) { | ||||
|             return $this->json(4001, $e->getMessage()); | ||||
|         } catch (Exception $e) { | ||||
|             ArchivesRepository::log($e->getMessage(), $e); | ||||
|             return $this->json(5000, '操作失败'); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 获取关于我们栏目内容列表 | ||||
|      * | ||||
|      * @return Json | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public function about(): Json | ||||
|     { | ||||
|         $categoryId = input('category_id/d', 0); | ||||
|         $page       = input('page/d', 1); | ||||
|         $size       = input('size/d', 20); | ||||
|         $exceptId   = input('except_id/d', 0); | ||||
|         $keyword    = input('keyword/s', ''); | ||||
|         $accountId  = $this->request->user['user_id'] ?? 0; | ||||
| 
 | ||||
|         try { | ||||
|             $where = []; | ||||
|             if (!empty($keyword)) { | ||||
|                 $keyword = trim($keyword); | ||||
|                 $where[] = ['title|subtitle|disease_name|doctor_name', 'like', '%'.$keyword.'%']; | ||||
|                 AccountRecord::saveSearch($accountId, $keyword); | ||||
|             } | ||||
| 
 | ||||
|             if ($exceptId > 0) { | ||||
|                 $where[] = ['id', '<>', $exceptId]; | ||||
|             } | ||||
| 
 | ||||
|             $order = ['published_at' => 'desc']; | ||||
| 
 | ||||
|             $data = ArchivesRepository::getInstance()->about($accountId, $categoryId, $where, $page, $size, $order); | ||||
|             return $this->json(0, 'success', $data); | ||||
|         } catch (RepositoryException $e) { | ||||
|             return $this->json(4001, $e->getMessage()); | ||||
|         } catch (Exception $e) { | ||||
|             ArchivesRepository::log($e->getMessage(), $e); | ||||
|             return $this->json(5000, '操作失败'); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 内容详情 | ||||
|      * | ||||
|      * @return Json | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public function detail(): Json | ||||
|     { | ||||
|         $id        = input('id/d', 0); | ||||
|         $shareId   = input('share_id/d', 0);//分享人ID
 | ||||
|         $accountId = $this->request->user['user_id'] ?? 0; | ||||
| 
 | ||||
|         try { | ||||
|             $data = ArchivesRepository::getInstance()->detail($id, $accountId, $shareId); | ||||
|             return $this->json(0, 'success', $data); | ||||
|         } catch (RepositoryException $e) { | ||||
|             return $this->json(4001, $e->getMessage()); | ||||
|         } catch (Exception $e) { | ||||
|             ArchivesRepository::log($e->getMessage(), $e); | ||||
|             return $this->json(5000, '获取详情失败'); | ||||
|         } | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 点赞、收藏 | ||||
|      */ | ||||
|     public function record(): Json | ||||
|     { | ||||
|         if (!$this->request->isPost()) { | ||||
|             return $this->json(4000, '无效请求'); | ||||
|         } | ||||
| 
 | ||||
|         $accountId = $this->request->user['user_id'] ?? 0; | ||||
|         $archiveId = $this->request->param('archive_id/d', 0); | ||||
|         $action    = $this->request->param('action/s', ''); | ||||
| 
 | ||||
|         try { | ||||
|             ArchivesRepository::getInstance()->record($accountId, $archiveId, $action); | ||||
|         } catch (RepositoryException $e) { | ||||
|             return $this->json(4001, $e->getMessage()); | ||||
|         } | ||||
| 
 | ||||
|         return $this->json(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 取消 点赞、收藏 | ||||
|      */ | ||||
|     public function unRecord(): Json | ||||
|     { | ||||
|         if (!$this->request->isPost()) { | ||||
|             return $this->json(4000, '无效请求'); | ||||
|         } | ||||
| 
 | ||||
|         $accountId = $this->request->user['user_id'] ?? 0; | ||||
|         $archiveId = $this->request->param('archive_id/d', 0); | ||||
|         $action    = $this->request->param('action/s', ''); | ||||
| 
 | ||||
|         try { | ||||
|             ArchivesRepository::getInstance()->unRecord($accountId, $archiveId, $action); | ||||
|         } catch (RepositoryException $e) { | ||||
|             return $this->json(4001, $e->getMessage()); | ||||
|         } | ||||
| 
 | ||||
|         return $this->json(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 用户内容收藏列表 | ||||
|      */ | ||||
|     public function collects(): Json | ||||
|     { | ||||
|         $accountId  = $this->request->user['user_id'] ?? 0; | ||||
|         $categoryId = $this->request->param('category_id/d', 0); | ||||
|         $page       = $this->request->param('page/d', 1); | ||||
|         $size       = $this->request->param('size/d', 10); | ||||
| 
 | ||||
|         $page = $page <= 0 ? 1 : $page; | ||||
|         $size = $size <= 0 ? 10 : $size; | ||||
|         $data = ArchivesRepository::getInstance()->accountCollects($accountId, $categoryId, $page, $size); | ||||
|         return $this->json(0, 'success', $data); | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,30 @@ | |||
| <?php | ||||
| 
 | ||||
| namespace app\controller\api; | ||||
| 
 | ||||
| use app\controller\BaseController; | ||||
| 
 | ||||
| /** | ||||
|  * API控制器基础类 | ||||
|  */ | ||||
| class Base extends BaseController | ||||
| { | ||||
|     // 布尔值数字关系
 | ||||
|     public const BOOL_FALSE = 0; | ||||
|     public const BOOL_TRUE  = 1; | ||||
| 
 | ||||
|     protected function initialize() | ||||
|     { | ||||
|         parent::initialize(); | ||||
| 
 | ||||
|         $this->middleware = [ | ||||
|             'jwt', | ||||
|             'apiLogin' => ['except' => $this->noNeedLogin] | ||||
|         ]; | ||||
|     } | ||||
| 
 | ||||
|     public function __call($method, $args) | ||||
|     { | ||||
|         return $this->json(4004, 'error request!'); | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,94 @@ | |||
| <?php | ||||
| 
 | ||||
| namespace app\controller\api; | ||||
| 
 | ||||
| use app\exception\RepositoryException; | ||||
| use app\repository\AccountRepository; | ||||
| use app\repository\CommonRepository; | ||||
| use app\repository\OperationRepository; | ||||
| use app\repository\OrderRepository; | ||||
| use app\service\Sms; | ||||
| use app\validate\CommonValidate; | ||||
| use think\Collection; | ||||
| use think\db\exception\DataNotFoundException; | ||||
| use think\db\exception\DbException; | ||||
| use think\db\exception\ModelNotFoundException; | ||||
| use think\response\Json; | ||||
| 
 | ||||
| class Common extends Base | ||||
| { | ||||
|     protected $noNeedLogin = [ | ||||
|         'slidePositions', | ||||
|         'slides', | ||||
|     ]; | ||||
| 
 | ||||
|     /** | ||||
|      * 发送短信验证码 | ||||
|      * | ||||
|      * @OA\Post( | ||||
|      *     path="/common/send-code", | ||||
|      *     tags={"common"}, | ||||
|      *     operationId="sendCode", | ||||
|      * ) | ||||
|      */ | ||||
|     public function sendCode(): Json | ||||
|     { | ||||
|         $input    = input('post.'); | ||||
|         $validate = new CommonValidate(); | ||||
|         if (!$validate->scene('send_sms')->check($input)) { | ||||
|             return $this->json(4001, '参数错误'); | ||||
|         } | ||||
|         if (!in_array($input['type'], ['register', 'login', 'binding'])) { | ||||
|             return $this->json(4002, '参数错误'); | ||||
|         } | ||||
| 
 | ||||
|         CommonRepository::getInstance()->sendSms($input['phone'], $input['type']); | ||||
|         return $this->json(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 查看轮播图可视位置配置信息 | ||||
|      */ | ||||
|     public function slidePositions(): Json | ||||
|     { | ||||
|         $repo = OperationRepository::getInstance(); | ||||
|         $list = $repo->slidePositions(); | ||||
|         return $this->json(0, 'success', $list); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     /** | ||||
|      * 轮播图 | ||||
|      */ | ||||
|     public function slides(): Json | ||||
|     { | ||||
|         $size     = $this->request->param('size/d', 0); | ||||
|         $position = trim($this->request->param('position/s', '')); | ||||
|         if (empty($position)) { | ||||
|             return $this->json(); | ||||
|         } | ||||
| 
 | ||||
|         try { | ||||
|             $repo = OperationRepository::getInstance(); | ||||
|             $list = $repo->slideListByPosition($position, $size); | ||||
|         } catch (\Exception $e) { | ||||
|             $list = new Collection(); | ||||
|         } | ||||
| 
 | ||||
|         return $this->json(0, 'success', $list); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 获取快递公司列表 | ||||
|      * | ||||
|      * @throws ModelNotFoundException | ||||
|      * @throws DbException | ||||
|      * @throws DataNotFoundException | ||||
|      */ | ||||
|     public function expressList(): Json | ||||
|     { | ||||
|         $list = OrderRepository::getInstance()->allExpress(); | ||||
|         return $this->json(0, 'success', $list); | ||||
|     } | ||||
| 
 | ||||
| } | ||||
|  | @ -0,0 +1,63 @@ | |||
| <?php | ||||
| 
 | ||||
| namespace app\controller\api; | ||||
| 
 | ||||
| use app\exception\RepositoryException; | ||||
| use app\repository\GoodsRepository; | ||||
| use app\validate\Goods as GoodsValidate; | ||||
| use Exception; | ||||
| use think\response\Json; | ||||
| 
 | ||||
| /** | ||||
|  * 测试用 | ||||
|  * | ||||
|  * Class DepartmentGoodsListLog | ||||
|  * @package app\controller\api | ||||
|  */ | ||||
| class DepartmentGoodsListLog extends Base | ||||
| { | ||||
|     /** | ||||
|      * @return Json | ||||
|      * @throws RepositoryException | ||||
|      */ | ||||
|     public function list() | ||||
|     { | ||||
|         $params   = $this->request->param(); | ||||
|         $validate = new GoodsValidate(); | ||||
|         if (!$validate->scene('base')->check($params)) { | ||||
|             return $this->json(4001, $validate->getError()); | ||||
|         } | ||||
| 
 | ||||
|         $data = GoodsRepository::getInstance()->list(); | ||||
| 
 | ||||
|         return $this->json(0, 'success', $data); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 获取分类列表 | ||||
|      * | ||||
|      * @return Json | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public function category() | ||||
|     { | ||||
|         $params   = $this->request->param(); | ||||
|         $validate = new GoodsValidate(); | ||||
|         if (!$validate->scene('base')->check($params)) { | ||||
|             return $this->json(4001, $validate->getError()); | ||||
|         } | ||||
| 
 | ||||
|         $data = GoodsRepository::getInstance()->categoryList(); | ||||
| 
 | ||||
|         return $this->json(0, 'success', $data); | ||||
|     } | ||||
| 
 | ||||
|     public function testApiClassMethod() | ||||
|     { | ||||
|         $header = $this->request->header(); | ||||
|         $all = $this->request->param(); | ||||
|         $get    = input('get.'); | ||||
|         $post   = input('post.'); | ||||
|         return $this->json(0, 'success', ['cost'=>$cost ?? 0]); | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,100 @@ | |||
| <?php | ||||
| 
 | ||||
| namespace app\controller\api; | ||||
| 
 | ||||
| use app\exception\RepositoryException; | ||||
| use app\job\NotifySms; | ||||
| use app\model\AccountFootmarks; | ||||
| use app\model\HotKeyword; | ||||
| use app\repository\AccountRepository; | ||||
| use app\service\ExtraConfig; | ||||
| use think\Collection; | ||||
| use think\facade\Queue; | ||||
| use think\response\Json; | ||||
| 
 | ||||
| class Index extends Base | ||||
| { | ||||
|     protected $noNeedLogin = [ | ||||
|         'miniProgramSetting', | ||||
|         'clearFootmarks', | ||||
|         'hotKeywords' | ||||
|     ]; | ||||
| 
 | ||||
|     public function index(): Json | ||||
|     { | ||||
|         return json(['code' => 0, 'msg' => 'I am index']); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 测试用 | ||||
|      * | ||||
|      * @return Json | ||||
|      * @throws RepositoryException | ||||
|      */ | ||||
|     public function test(): Json | ||||
|     { | ||||
|         $userId = $this->request->middleware('userInfo')['user_id'] ?? 0; | ||||
|         $user   = AccountRepository::getInstance()->info($userId, []); | ||||
| 
 | ||||
|         return json(['code' => 0, 'msg' => 'I am test ', 'data' => $user]); | ||||
|     } | ||||
| 
 | ||||
|     public function login(): Json | ||||
|     { | ||||
|         $userId = $this->request->middleware('userInfo')['user_id'] ?? 0; | ||||
|         return json(['code' => 0, 'msg' => 'I am login '.$userId]); | ||||
|     } | ||||
| 
 | ||||
|     public function notify() | ||||
|     { | ||||
|         $beginNotifyList = AccountRepository::getInstance()->getBeginNotifyList(); | ||||
|         //        $res = Queue::later(3, NotifySms::class, $beginNotifyList);
 | ||||
|         //        $getSuccessList = AccountRepository::getInstance()->getSuccessList();
 | ||||
|         return $this->json(0, 'success', $beginNotifyList); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     /** | ||||
|      * 小程序个性装修配置 | ||||
|      */ | ||||
|     public function miniProgramSetting(): Json | ||||
|     { | ||||
|         $conf = ExtraConfig::miniProgram(); | ||||
|         return $this->json(0, 'success', $conf); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 推荐显示的热搜词 | ||||
|      */ | ||||
|     public function hotKeywords(): Json | ||||
|     { | ||||
|         try { | ||||
|             $type = input('type/s',""); | ||||
|             $list = HotKeyword::allRecommends($type); | ||||
|         } catch (\Exception $e) { | ||||
|             $list = new Collection(); | ||||
|         } | ||||
| 
 | ||||
|         return $this->json(0, 'success', $list); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 清理过期足迹 | ||||
|      * | ||||
|      * @return Json | ||||
|      */ | ||||
|     public function clearFootmarks(): Json | ||||
|     { | ||||
|         try { | ||||
|             //清理N天以前的数据
 | ||||
|             $day   = 30; | ||||
|             $time  = date('Y-m-d H:i:s', time() - $day * 86400); | ||||
|             $count = AccountFootmarks::where('created_at', '<', $time)->count(); | ||||
|             AccountFootmarks::where('created_at', '<', $time)->delete(); | ||||
|             return $this->json(0, '成功清理足迹(条):'.$count); | ||||
|         } catch (\Exception $e) { | ||||
|             return $this->json(5000, '清理足迹失败'); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| } | ||||
|  | @ -0,0 +1,39 @@ | |||
| <?php | ||||
| 
 | ||||
| namespace app\controller\api; | ||||
| 
 | ||||
| 
 | ||||
| use app\model\Account; | ||||
| use app\model\AccountLevel; | ||||
| use app\repository\AccountRepository; | ||||
| use think\response\Json; | ||||
| 
 | ||||
| class Level extends Base | ||||
| { | ||||
|     protected $noNeedLogin = [ | ||||
| 
 | ||||
|     ]; | ||||
| 
 | ||||
|     public function index(): Json | ||||
|     { | ||||
|         $userId = $this->request->user['user_id'] ?? 0; | ||||
|         $user = Account::findById($userId); | ||||
|         if (empty($user)) { | ||||
|             return json(['code' => 6001, 'msg' => '未登录']); | ||||
|         } | ||||
|         $level = AccountRepository::getInstance()->getUserLevel($user["coin_total"]); | ||||
|         $nextLevel = AccountRepository::getInstance()->getUserNextLevel($level["value"]); | ||||
| 
 | ||||
|         if (!empty($nextLevel)) { | ||||
|             $nextLevel["disparity"] = ( $nextLevel["value"] - $user['coin_total']); | ||||
|         } | ||||
|         return $this->json(0, "ok", [ | ||||
|             "level" => $level, | ||||
|             "nextLevel" => $nextLevel, | ||||
|             "nickname" => $user['nickname'], | ||||
|             "headimgurl" => $user['headimgurl'], | ||||
|         ]); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
| } | ||||
|  | @ -0,0 +1,406 @@ | |||
| <?php | ||||
| 
 | ||||
| namespace app\controller\api; | ||||
| 
 | ||||
| use app\exception\RepositoryException; | ||||
| use app\repository\OrderRepository; | ||||
| use app\validate\OrderValidate; | ||||
| use app\model\Order as OrderModel; | ||||
| use Exception; | ||||
| use GuzzleHttp\Exception\GuzzleException; | ||||
| use think\db\exception\DataNotFoundException; | ||||
| use think\db\exception\DbException; | ||||
| use think\db\exception\ModelNotFoundException; | ||||
| use think\response\Json; | ||||
| 
 | ||||
| /** | ||||
|  * 订单 | ||||
|  * | ||||
|  * Class Order | ||||
|  * @package app\controller\api | ||||
|  */ | ||||
| class Order extends Base | ||||
| { | ||||
|     /** | ||||
|      * 创建订单 | ||||
|      * | ||||
|      * @return Json | ||||
|      * @throws GuzzleException | ||||
|      */ | ||||
|     public function create(): Json | ||||
|     { | ||||
|         if ($this->request->isPost()) { | ||||
|             $params    = $this->request->param(); | ||||
|             $accountId = $this->request->user['user_id'] ?? 0; | ||||
| 
 | ||||
|             try { | ||||
|                 $data = OrderRepository::getInstance()->createOrder($accountId, $params); | ||||
|                 OrderRepository::getInstance()->updateSpuStock([]); | ||||
|                 return $this->json(0, 'success', $data); | ||||
|             } catch (RepositoryException $e) { | ||||
|                 return $this->json(4000, $e->getMessage()); | ||||
|             } catch (Exception $e) { | ||||
|                 OrderRepository::log('订单创建失败', $e, 'error', 'order'); | ||||
|                 return $this->json(5000, '订单创建失败'); | ||||
|             } | ||||
|         } | ||||
|         return $this->json(4002, '请求错误'); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 购物车列表 | ||||
|      * | ||||
|      * @return Json | ||||
|      * @throws DataNotFoundException | ||||
|      * @throws DbException | ||||
|      * @throws ModelNotFoundException | ||||
|      */ | ||||
|     public function shoppingCart(): Json | ||||
|     { | ||||
|         $params    = $this->request->param(); | ||||
|         $accountId = $this->request->user['user_id'] ?? 0; | ||||
|         $type      = $params['type'] ?? ''; | ||||
|         $page      = $params['page'] ?? 1; | ||||
|         $size      = $params['size'] ?? 20; | ||||
| 
 | ||||
|         $data = OrderRepository::getInstance()->shoppingCart($accountId, $type, $page, $size); | ||||
| 
 | ||||
|         return $this->json(0, 'success', $data); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 添加购物车 | ||||
|      * | ||||
|      * @return Json | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public function shoppingCartAdd(): Json | ||||
|     { | ||||
|         if ($this->request->isPost()) { | ||||
|             $params    = $this->request->param(); | ||||
|             $accountId = $this->request->user['user_id'] ?? 0; | ||||
|             $rules     = [ | ||||
|                 'sku_id|商品' => 'require|number', | ||||
|                 'num|数量'    => 'require|number', | ||||
|             ]; | ||||
| 
 | ||||
|             $validate = $this->validateByApi($params, $rules); | ||||
|             if ($validate !== true) { | ||||
|                 return $validate; | ||||
|             } | ||||
| 
 | ||||
|             try { | ||||
|                 OrderRepository::getInstance()->shoppingCartAdd($accountId, $params['sku_id'], $params['num'] ?? 1); | ||||
|                 return $this->json(); | ||||
|             } catch (RepositoryException $e) { | ||||
|                 return $this->json(4000, $e->getMessage()); | ||||
|             } catch (Exception $e) { | ||||
|                 OrderRepository::log('购物车添加失败', $e); | ||||
|                 return $this->json(5000, '购物车添加失败'); | ||||
|             } | ||||
|         } | ||||
|         return $this->json(4002, '请求错误'); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 购物车商品数量变更 | ||||
|      * | ||||
|      * @return Json | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public function shoppingCartChangeNum(): Json | ||||
|     { | ||||
|         if ($this->request->isPost()) { | ||||
|             $params = $this->request->param(); | ||||
|             $rules  = [ | ||||
|                 'id|ID'  => 'require|number', | ||||
|                 'num|数量' => 'require|number', | ||||
|             ]; | ||||
| 
 | ||||
|             $validate = $this->validateByApi($params, $rules); | ||||
|             if ($validate !== true) { | ||||
|                 return $validate; | ||||
|             } | ||||
|             try { | ||||
|                 OrderRepository::getInstance()->shoppingCartChangeNum($params['id'], $params['num']); | ||||
|             } catch (RepositoryException $e) { | ||||
|                 return $this->json(4000, $e->getMessage()); | ||||
|             } catch (Exception $e) { | ||||
|                 OrderRepository::log('购物车数量加减失败', $e); | ||||
|                 return $this->json(5000, '操作失败'); | ||||
|             } | ||||
| 
 | ||||
|             return $this->json(); | ||||
|         } | ||||
|         return $this->json(4002, '请求错误'); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 购物车商品删除 | ||||
|      * | ||||
|      * @return Json | ||||
|      */ | ||||
|     public function shoppingCartDel(): Json | ||||
|     { | ||||
|         if ($this->request->isPost()) { | ||||
|             $id        = input('post.id/d', 0); | ||||
|             $accountId = $this->request->user['user_id'] ?? 0; | ||||
|             if (!$id) { | ||||
|                 return $this->json(4001, '参数错误'); | ||||
|             } | ||||
| 
 | ||||
|             try { | ||||
|                 OrderRepository::getInstance()->shoppingCartDel($accountId, $id); | ||||
|             } catch (RepositoryException $e) { | ||||
|                 return $this->json(4000, $e->getMessage()); | ||||
|             } catch (Exception $e) { | ||||
|                 OrderRepository::log('购物车数量加减失败', $e); | ||||
|                 return $this->json(5000, '操作失败'); | ||||
|             } | ||||
| 
 | ||||
|             return $this->json(); | ||||
|         } | ||||
|         return $this->json(4002, '请求错误'); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 订单准备信息 | ||||
|      * 结算页面 获取商品数据及汇总金额 | ||||
|      * @return Json | ||||
|      */ | ||||
|     public function prepareInfo(): Json | ||||
|     { | ||||
|         if ($this->request->isPost()) { | ||||
|             $params    = $this->request->param(); | ||||
|             $accountId = $this->request->user['user_id'] ?? 0; | ||||
| 
 | ||||
|             try { | ||||
|                 $data = OrderRepository::getInstance()->prepareInfo($accountId, $params); | ||||
|             } catch (RepositoryException $e) { | ||||
|                 return $this->json(4000, $e->getMessage()); | ||||
|             } catch (Exception $e) { | ||||
|                 OrderRepository::log('获取订单前置信息失败', $e, 'error', 'order'); | ||||
|                 return $this->json(5000, '订单信息获取失败'); | ||||
|             } | ||||
| 
 | ||||
|             return $this->json(0, 'success', $data); | ||||
|         } | ||||
|         return $this->json(4002, '请求错误'); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 支付成功通知 | ||||
|      * 结算页面 获取商品数据及汇总金额 | ||||
|      * | ||||
|      * @return Json | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public function paid(): Json | ||||
|     { | ||||
|         if ($this->request->isPost()) { | ||||
|             $params    = $this->request->param(); | ||||
|             $accountId = $this->request->user['user_id'] ?? 0; | ||||
|             $rules     = [ | ||||
|                 'order_coding|订单编号' => 'require', | ||||
|             ]; | ||||
| 
 | ||||
|             $validate = $this->validateByApi($params, $rules); | ||||
|             if ($validate !== true) { | ||||
|                 return $validate; | ||||
|             } | ||||
| 
 | ||||
|             try { | ||||
|                 if (OrderRepository::getInstance()->setPaid($params['order_coding'])) { | ||||
|                     return $this->json(); | ||||
|                 } | ||||
|                 return $this->json(4003, '支付失败'); | ||||
|             } catch (RepositoryException $e) { | ||||
|                 return $this->json(4000, $e->getMessage()); | ||||
|             } catch (Exception $e) { | ||||
|                 OrderRepository::log('支付成功通知操作失败', $e); | ||||
|                 return $this->json(5000, '操作失败'); | ||||
|             } | ||||
|         } | ||||
|         return $this->json(4002, '请求错误'); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 订单验收 - 确认收货 | ||||
|      * | ||||
|      * @return Json | ||||
|      */ | ||||
|     public function accepted(): Json | ||||
|     { | ||||
|         if (!$this->request->isPost()) { | ||||
|             return $this->json(4002, '请求错误'); | ||||
|         } | ||||
| 
 | ||||
|         $accountId = $this->request->user['user_id'] ?? 0; | ||||
|         $orderId   = $this->request->param('order_id', 0); | ||||
| 
 | ||||
|         try { | ||||
|             OrderRepository::getInstance()->orderAccepted($orderId, $accountId); | ||||
| 
 | ||||
|         } catch (RepositoryException $e) { | ||||
|             return $this->json(4000, $e->getMessage()); | ||||
|         } | ||||
| 
 | ||||
|         return $this->json(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 发货 | ||||
|      * | ||||
|      * @return Json | ||||
|      */ | ||||
|     public function ship(): Json | ||||
|     { | ||||
|         if (!$this->request->isPost()) { | ||||
|             return $this->json(4002, '请求错误'); | ||||
|         } | ||||
| 
 | ||||
|         $orderId       = $this->request->param('order_id', 0); | ||||
|         $expressId     = $this->request->param('express_id', 0); | ||||
|         $expressNumber = $this->request->param('express_number', 0); | ||||
| 
 | ||||
|         try { | ||||
|             OrderRepository::getInstance()->orderShipping($orderId, $expressId, $expressNumber); | ||||
| 
 | ||||
|         } catch (RepositoryException $e) { | ||||
|             return $this->json(4000, $e->getMessage()); | ||||
|         } | ||||
| 
 | ||||
|         return $this->json(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 查询订单物流 | ||||
|      * | ||||
|      * @return Json | ||||
|      */ | ||||
|     public function logistics(): Json | ||||
|     { | ||||
|         $orderCoding = input('order_coding'); | ||||
| 
 | ||||
|         try { | ||||
|             $res = OrderRepository::getInstance()->logistics($orderCoding); | ||||
|             return $this->json(0, 'success', $res); | ||||
|         } catch (RepositoryException $e) { | ||||
|             return $this->json(4000, $e->getMessage()); | ||||
|         } catch (Exception $e) { | ||||
|             OrderRepository::log('物流查询失败', $e); | ||||
|             return $this->json(5000, '获取物流信息失败'); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 取消订单 | ||||
|      * | ||||
|      * @return Json | ||||
|      * @throws DataNotFoundException | ||||
|      * @throws DbException | ||||
|      * @throws ModelNotFoundException | ||||
|      */ | ||||
|     public function cancel(): Json | ||||
|     { | ||||
|         if (!$this->request->isPost()) { | ||||
|             return $this->json(4002, '请求错误'); | ||||
|         } | ||||
| 
 | ||||
|         $orderCoding = $this->request->param('order_coding', 0); | ||||
|         $reason      = $this->request->param('remarks', ''); | ||||
| 
 | ||||
|         try { | ||||
|             OrderRepository::getInstance()->setClosed($orderCoding, OrderModel::STATUS_CLOSED, $reason); | ||||
|         } catch (RepositoryException $e) { | ||||
|             return $this->json(4000, $e->getMessage()); | ||||
|         } | ||||
| 
 | ||||
|         return $this->json(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 订单付款 | ||||
|      * | ||||
|      * @return Json | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public function pay(): Json | ||||
|     { | ||||
|         if (!$this->request->isPost()) { | ||||
|             return $this->json(4002, '请求错误'); | ||||
|         } | ||||
| 
 | ||||
|         $accountId   = $this->request->user['user_id'] ?? 0; | ||||
|         $orderCoding = $this->request->param('order_coding', 0); | ||||
| 
 | ||||
|         try { | ||||
|             $res = OrderRepository::getInstance()->pay($orderCoding, $accountId); | ||||
|             return $this->json(0, 'success', $res); | ||||
|         } catch (RepositoryException $e) { | ||||
|             return $this->json(4000, $e->getMessage()); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 购物车数量 | ||||
|      * | ||||
|      * @return Json | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public function shoppingCartCount(): Json | ||||
|     { | ||||
|         $accountId = $this->request->user['user_id'] ?? 0; | ||||
|         $type      = $this->request->param('type/s', 'spu'); | ||||
| 
 | ||||
|         try { | ||||
|             $count = OrderRepository::getInstance()->shoppingCartCount($accountId, $type); | ||||
|             return $this->json(0, 'success', ['count' => $count]); | ||||
|         } catch (RepositoryException $e) { | ||||
|             return $this->json(4000, $e->getMessage()); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 商品sku核验 | ||||
|      * | ||||
|      */ | ||||
|     public function check(): Json | ||||
|     { | ||||
|         $orderCoding = input('order_coding/s', ''); | ||||
|         $id          = input('id/d', 0); | ||||
|         $checkBy     = input('check_user/d', 0); | ||||
|         $num         = input('num/d', 1); | ||||
| 
 | ||||
|         try { | ||||
|             OrderRepository::getInstance()->check($orderCoding, $id, $num, $checkBy); | ||||
|         } catch (RepositoryException $e) { | ||||
|             return $this->json(4000, $e->getMessage()); | ||||
|         } catch (Exception $e) { | ||||
|             OrderRepository::log('订单商品核验失败', $e); | ||||
|             return $this->json(5000, '订单商品核验失败'); | ||||
|         } | ||||
|         return $this->json(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 商品sku核验结果 | ||||
|      * | ||||
|      */ | ||||
|     public function checkResult(): Json | ||||
|     { | ||||
|         $orderCoding = input('order_coding/s', ''); | ||||
|         $id          = input('id/d', 0); | ||||
|         $notCheckNum = input('not_check_num/d', 0); | ||||
| 
 | ||||
|         try { | ||||
|             $res = OrderRepository::getInstance()->checkResult($orderCoding, $id, $notCheckNum); | ||||
|             return $this->json(0, 'success', ['result' => (int) $res]); | ||||
|         } catch (RepositoryException $e) { | ||||
|             return $this->json(4000, $e->getMessage()); | ||||
|         } catch (Exception $e) { | ||||
|             OrderRepository::log('订单商品核验结果获取失败', $e); | ||||
|             return $this->json(5000, '订单商品核验结果获取失败'); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,152 @@ | |||
| <?php | ||||
| 
 | ||||
| namespace app\controller\api; | ||||
| 
 | ||||
| use app\exception\RepositoryException; | ||||
| use app\repository\BusinessRepository; | ||||
| use app\repository\RechargeRepository; | ||||
| use app\service\wx\WechatPay; | ||||
| use app\model\Recharge as RechargeModel; | ||||
| use think\facade\Db; | ||||
| use think\facade\Log; | ||||
| 
 | ||||
| /** | ||||
|  * 充值 | ||||
|  * | ||||
|  * Class Recharge | ||||
|  * @package app\controller\api | ||||
|  */ | ||||
| class Recharge extends Base | ||||
| { | ||||
|     protected $noNeedLogin = ['query']; | ||||
| 
 | ||||
|     /** | ||||
|      * 查询是否支付成功 | ||||
|      * */ | ||||
|     public function query() | ||||
|     { | ||||
|         $orderNum = input("order_num/s"); | ||||
|         if (empty($orderNum)) { | ||||
|             return $this->json("4001", "参数错误"); | ||||
|         } | ||||
|         $recharge = RechargeRepository::getInstance()->getModel()->where(["order_num" => $orderNum])->lock(true)->find(); | ||||
|         if (empty($recharge)) { | ||||
|             return $this->json("4001", "订单不存在"); | ||||
|         } | ||||
|         if ($recharge['state'] == RechargeModel::state_on) { | ||||
|             return $this->json(); | ||||
|         } | ||||
|         $business = BusinessRepository::getInstance()->getModel()->where(["code" => $recharge['business_code']])->lock(true)->find(); | ||||
|         if (empty($business)) { | ||||
|             return $this->json("4001", "商家不存在"); | ||||
|         } | ||||
|         //查询  交易成功判断条件: return_code、result_code和trade_state都为SUCCESS
 | ||||
|         $res = WechatPay::getInstance()->order->queryByOutTradeNumber($orderNum); | ||||
|         if ($res['return_code'] == 'SUCCESS') { // return_code 表示通信状态,不代表支付状态
 | ||||
|             if (isset($res['result_code']) && $res['result_code'] == 'SUCCESS') { | ||||
|                 if (isset($res['trade_state']) && $res['trade_state'] == 'SUCCESS') { | ||||
|                     Db::startTrans(); | ||||
|                     try { | ||||
|                         //这里确定支付成功
 | ||||
|                         $total_fee = $res['total_fee'] / 100; | ||||
|                         //加余额
 | ||||
|                         $business->save(["balance" => ($business["balance"] + $total_fee)]); | ||||
|                         //修改支付状态
 | ||||
|                         $recharge->save([ | ||||
|                             "money" => $total_fee, | ||||
|                             "state" => RechargeModel::state_on, | ||||
|                             "update_time" => date("Y-m-d H:i:s"), | ||||
|                             "balance" => $business->balance | ||||
|                         ]); | ||||
|                         Db::commit(); | ||||
|                         return $this->json(); | ||||
|                     } catch (RepositoryException $e) { | ||||
|                         Db::rollback(); | ||||
|                         return $this->json("5001", $e->getMessage()); | ||||
|                     } catch (\Exception $e) { | ||||
|                         Db::rollback(); | ||||
|                         return $this->json("5001", "充值失败"); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         return $this->json("4001", "未支付成功"); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 微信的回调 | ||||
|      * | ||||
|      * @throws \EasyWeChat\Kernel\Exceptions\Exception | ||||
|      */ | ||||
|     public function notify(){ | ||||
|         if ($this->request->isPost()) { | ||||
|             $app      = WechatPay::getInstance(); | ||||
|             $response = $app->handlePaidNotify(function ($message, $fail) { | ||||
|                 //                $aa = '{"appid":"wxa02e44170bc722cd","bank_type":"OTHERS","cash_fee":"1","fee_type":"CNY","is_subscribe":"N","mch_id":"1605090111","nonce_str":"60f7d8a1e4ac8","openid":"oKrEm0ehgsy2ZTWzEva4tbLuUgFw","out_trade_no":"16268555858753004863","result_code":"SUCCESS","return_code":"SUCCESS","sign":"DB3F6CDCB7FBB3B9DDF7C0CC8BBD5AAD","time_end":"20210721162000","total_fee":"1","trade_type":"JSAPI","transaction_id":"4200001200202107217942681078"}';
 | ||||
|                 //                $message = json_decode($aa, true);
 | ||||
|                 $m     = json_encode($message, JSON_UNESCAPED_UNICODE); | ||||
| 
 | ||||
|                 $recharge = RechargeRepository::getInstance()->getModel()->where(["order_num" => $message['out_trade_no']])->lock(true)->find(); | ||||
|                 if (empty($recharge)) { | ||||
|                     $this->log(sprintf("[微信支付回调][%s][%s]订单支付成功,但系统查无此订单 info:%s", date('Y-m-d H:i:s'), $message['out_trade_no'], $m), 'error'); | ||||
|                     return true;//订单不存在
 | ||||
|                 } | ||||
|                 if ($recharge['state'] == RechargeModel::state_on) { | ||||
|                     return true;//订单已经支付
 | ||||
|                 } | ||||
|                 $business = BusinessRepository::getInstance()->getModel()->where(["code" => $recharge['business_code']])->lock(true)->find(); | ||||
|                 if (empty($business)) { | ||||
|                     $this->log(sprintf("[微信支付回调][%s][%s]订单支付成功,但商家不存在 info:%s", date('Y-m-d H:i:s'), $message['out_trade_no'], $m), 'error'); | ||||
|                     return true; | ||||
|                 } | ||||
| 
 | ||||
| 
 | ||||
|                 if ($message['return_code'] == 'SUCCESS') { // return_code 表示通信状态,不代表支付状态
 | ||||
|                     if (isset($message['result_code']) && $message['result_code'] == 'SUCCESS') { | ||||
|                         if (isset($message['trade_state']) && $message['trade_state'] == 'SUCCESS') { | ||||
|                             Db::startTrans(); | ||||
|                             try { | ||||
|                                 //这里确定支付成功
 | ||||
|                                 $total_fee = $message['total_fee'] / 100; | ||||
|                                 //加余额
 | ||||
|                                 $business->save(["balance" => ($business["balance"] + $total_fee)]); | ||||
|                                 //修改支付状态
 | ||||
|                                 $recharge->save([ | ||||
|                                     "money" => $total_fee, | ||||
|                                     "state" => RechargeModel::state_on, | ||||
|                                     "update_time" => date("Y-m-d H:i:s"), | ||||
|                                     "balance" => $business->balance | ||||
|                                 ]); | ||||
|                                 Db::commit(); | ||||
|                                 //记录日志
 | ||||
|                                 $this->log(sprintf("[微信支付回调][%s][%s]订单支付成功 info:%s", date('Y-m-d H:i:s'), $message['out_trade_no'], $m), 'info'); | ||||
|                                 return true; | ||||
|                             } catch (RepositoryException $e) { | ||||
|                                 Db::rollback(); | ||||
|                                 $this->log(sprintf("[微信支付回调][%s][%s]订单支付成功-修改订单状态失败-RepositoryException info:%s", date('Y-m-d H:i:s'), $message['out_trade_no'], $m), 'info'); | ||||
|                                 return $fail('Order status edit failed.'); | ||||
|                             } catch (\Exception $e) { | ||||
|                                 Db::rollback(); | ||||
|                                 $this->log(sprintf("[微信支付回调][%s][%s]订单支付成功-修改订单状态失败-Exception info:%s", date('Y-m-d H:i:s'), $message['out_trade_no'], $m), 'info'); | ||||
|                                 return $fail('Order status edit failed.'); | ||||
|                             } | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|                 return $fail('通信失败,请稍后再通知我'); | ||||
|             }); | ||||
| 
 | ||||
|             $response->send(); | ||||
|         } | ||||
|     } | ||||
|     /** | ||||
|      * 记录订单日志 | ||||
|      * | ||||
|      * @param string $message | ||||
|      * @param string $type | ||||
|      */ | ||||
|     private function log(string $message, string $type = 'info'): void | ||||
|     { | ||||
|         Log::channel('order')->write($message, $type); | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,181 @@ | |||
| <?php | ||||
| 
 | ||||
| namespace app\controller\api; | ||||
| 
 | ||||
| use app\exception\RepositoryException; | ||||
| use app\model\Account; | ||||
| use app\model\AccountSignOnline; | ||||
| use app\repository\AccountRepository; | ||||
| use think\Exception; | ||||
| use think\facade\Config; | ||||
| use think\facade\Db; | ||||
| use think\response\Json; | ||||
| 
 | ||||
| class Sign extends Base | ||||
| { | ||||
|     protected $noNeedLogin = []; | ||||
| 
 | ||||
| 
 | ||||
|     /** | ||||
|      * 签到页面加载 | ||||
|      * */ | ||||
|     public function miniLoad() | ||||
|     { | ||||
|         Config::load('extra/base', 'base'); | ||||
|         $baseConfig = config('base'); | ||||
|         $score = isset($baseConfig['sign_score']) ? abs($baseConfig['sign_score']) : 1; | ||||
| 
 | ||||
|         $userId = $this->request->user['user_id'] ?? 0; | ||||
|         if ($userId == 0) { | ||||
|             return $this->json(6001, "请先登录"); | ||||
|         } | ||||
| 
 | ||||
|         $account = Account::findOne(["id" => $userId], []); | ||||
|         if (empty($account)) { | ||||
|             return $this->json(6001, "请先登录"); | ||||
|         } | ||||
| 
 | ||||
|         //更新连续签到次数
 | ||||
|         AccountRepository::getInstance()->checkContinuitySign($account); | ||||
| 
 | ||||
|         $weekDate = getLatelyWeekDate(); | ||||
| 
 | ||||
|         $weedSignInOnlineRecord = AccountRepository::getInstance()->weedSignInOnlineRecord($userId, $weekDate["1"]["date"], strtotime($weekDate["7"]["date"]) + 86399); | ||||
| 
 | ||||
|         foreach ($weedSignInOnlineRecord as $item) { | ||||
|             $w = date("w", strtotime($item['created_at'])); | ||||
|             if ($w == 0) { | ||||
|                 $weekDate["1"]["record"] = $item["score"]; | ||||
|             } else { | ||||
|                 $weekDate[$w]["record"] = $item["score"]; | ||||
|             } | ||||
|             $weekDate[$w]['is_sign'] = AccountSignOnline::COMMON_ON;//当天是否签到
 | ||||
|         } | ||||
|         $todaySignIn = AccountSignOnline::COMMON_OFF; | ||||
|         foreach ($weekDate as &$item) { | ||||
| 
 | ||||
|             $key = date("m.d", strtotime($item['date'])); | ||||
|             if (!isset($item['record'])) { | ||||
|                 $item['record'] = $score; | ||||
|                 $item['is_sign'] = AccountSignOnline::COMMON_OFF;//当天是否签到
 | ||||
|             } | ||||
| 
 | ||||
|             if ($key == date("m.d")) { | ||||
|                 $key = "今天"; | ||||
| 
 | ||||
|                 if ($item['is_sign'] == AccountSignOnline::COMMON_ON) { | ||||
|                     $todaySignIn = AccountSignOnline::COMMON_ON; | ||||
|                 } | ||||
|             } elseif ($key == (date("m.d", strtotime("+1 day")))) { | ||||
|                 $key = "明天"; | ||||
|             } | ||||
|             $item["key"] = $key; | ||||
| 
 | ||||
| 
 | ||||
|         } | ||||
| 
 | ||||
|         return $this->json(0, "操作成功", [ | ||||
|             "sign_record" => $weekDate, | ||||
|             "reward_score" => $score, | ||||
|             "user_score" => $account['score'], | ||||
|             "today_sign_in" => $todaySignIn, | ||||
|         ]); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 签到记录 | ||||
|      * */ | ||||
| 
 | ||||
|     public function onlineSignRecord() | ||||
|     { | ||||
|         $userId = $this->request->user['user_id'] ?? 0; | ||||
|         if ($userId == 0) { | ||||
|             return $this->json(6001, "请先登录"); | ||||
|         } | ||||
| 
 | ||||
|         $page = input("page/d", 1); | ||||
|         $size = input("size/d", 10); | ||||
| 
 | ||||
|         $record = AccountRepository::getInstance()->onlineSignRecordList($userId, $page, $size); | ||||
|         if ($record->isEmpty()) { | ||||
|             return $this->json(4001, "没有更多"); | ||||
|         } | ||||
|         return $this->json(0, "ok", $record); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 线上签到 | ||||
|      * */ | ||||
|     public function onlineSingIn(): Json | ||||
|     { | ||||
|         //检查是否已经签到
 | ||||
|         $userId = $this->request->user['user_id'] ?? 0; | ||||
|         if ($userId == 0) { | ||||
|             return $this->json(6001, "请先登录"); | ||||
|         } | ||||
| 
 | ||||
|         $check = AccountRepository::getInstance()->checkSignInOnline($userId); | ||||
|         if ($check) { | ||||
|             return $this->json(4003, "今天已经签到了,请明天再来"); | ||||
|         } | ||||
|         $account = Account::findOne(["id" => $userId], [], function ($q) { | ||||
|             return $q->lock(true); | ||||
|         }); | ||||
|         if (empty($account)) { | ||||
|             return $this->json(6001, "请先登录"); | ||||
|         } | ||||
| 
 | ||||
|         //更新连续签到次数
 | ||||
|         AccountRepository::getInstance()->checkContinuitySign($account); | ||||
| 
 | ||||
|         Config::load('extra/base', 'base'); | ||||
|         $baseConfig = config('base'); | ||||
|         $score = isset($baseConfig['sign_score']) ? abs($baseConfig['sign_score']) : 1; | ||||
| 
 | ||||
|         Db::startTrans(); | ||||
|         try { | ||||
|             AccountRepository::getInstance()->SignInOnline($account, $score); | ||||
|             Db::commit(); | ||||
|             return $this->json(); | ||||
|         } catch (Exception $e) { | ||||
|             Db::rollback(); | ||||
|             $this->json(4003, "签到失败"); | ||||
|         } catch (RepositoryException $e) { | ||||
|             Db::rollback(); | ||||
|             $this->json(4003, "签到失败"); | ||||
|         } | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     /** | ||||
|      * 线下签到 | ||||
|      * */ | ||||
|     public function SingIn(): Json | ||||
|     { | ||||
|         //检查是否已经签到
 | ||||
|         $userId = $this->request->user['user_id'] ?? 0; | ||||
|         if ($userId == 0) { | ||||
|             return $this->json(6001, "请先登录"); | ||||
|         } | ||||
| 
 | ||||
|         $check = AccountRepository::getInstance()->checkSignIn($userId); | ||||
|         if ($check) { | ||||
|             return $this->json(4003, "今天已经签到了,请明天再来"); | ||||
|         } | ||||
|         Db::startTrans(); | ||||
|         try { | ||||
|             AccountRepository::getInstance()->SignIn($userId); | ||||
|             Db::commit(); | ||||
|             return $this->json(); | ||||
|         } catch (Exception $e) { | ||||
|             Db::rollback(); | ||||
|             $this->json(4003, "签到失败"); | ||||
|         } catch (RepositoryException $e) { | ||||
|             Db::rollback(); | ||||
|             $this->json(4003, "签到失败"); | ||||
|         } | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
| } | ||||
|  | @ -0,0 +1,335 @@ | |||
| <?php | ||||
| 
 | ||||
| namespace app\controller\api; | ||||
| 
 | ||||
| use app\controller\api\Base; | ||||
| use app\exception\RepositoryException; | ||||
| use app\model\AccountLevel; | ||||
| use app\model\AccountRecord; | ||||
| use app\model\AccountRole; | ||||
| use app\model\Spu as SpuModel; | ||||
| use app\model\Disease; | ||||
| use app\model\SpuActivity; | ||||
| use app\model\Staff; | ||||
| use app\repository\OrderRepository; | ||||
| use app\repository\SpuRepository; | ||||
| use Exception; | ||||
| use think\Collection; | ||||
| use think\db\exception\DataNotFoundException; | ||||
| use think\db\exception\DbException; | ||||
| use think\db\exception\ModelNotFoundException; | ||||
| use think\facade\Log; | ||||
| use think\response\Json; | ||||
| 
 | ||||
| class Spu extends Base | ||||
| { | ||||
|     protected $exceptExtra = ['list', 'category', 'detail']; | ||||
| 
 | ||||
|     /** | ||||
|      * 商品列表筛选条件 | ||||
|      * | ||||
|      * @throws ModelNotFoundException | ||||
|      * @throws DbException | ||||
|      * @throws DataNotFoundException | ||||
|      */ | ||||
|     public function condition(): Json | ||||
|     { | ||||
|         $list = [ | ||||
|             'disease'      => Disease::getListByPid(0, ['pid', 'name', 'id', 'sort']), | ||||
|             'doctor_roles' => AccountRole::findAccountRolesByGroupName(AccountRole::ROLE_GROUP_DOCTOR), | ||||
|             'activity'     => SpuModel::activity(), | ||||
|         ]; | ||||
| 
 | ||||
|         return $this->json(0, 'success', $list); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 获取已发布的商品列表 | ||||
|      * | ||||
|      * @return Json | ||||
|      * @throws RepositoryException | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public function list(): Json | ||||
|     { | ||||
|         $repo = SpuRepository::getInstance(); | ||||
| 
 | ||||
|         $fields = SpuModel::spuListFields(); | ||||
| 
 | ||||
|         $params             = input(); | ||||
|         $params['fields']   = $fields; | ||||
|         $params['is_score'] = SpuModel::COMMON_OFF;//排除积分商品
 | ||||
| 
 | ||||
|         $list = $repo->listForFront($params, function ($q) { | ||||
|             return $q->with([ | ||||
|                 'activity_info' => function ($query) { | ||||
|                     $query->withoutField('content'); | ||||
|                 } | ||||
|             ]); | ||||
|         }); | ||||
| 
 | ||||
|         return $this->json(0, 'success', $list); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 获取已发布的积分商品列表 | ||||
|      * | ||||
|      * @return Json | ||||
|      * @throws RepositoryException | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public function score(): Json | ||||
|     { | ||||
|         $repo = SpuRepository::getInstance(); | ||||
| 
 | ||||
|         $type      = input('type/s', SpuModel::TYPE_NORMAL);//normal=综合 newest=最新
 | ||||
|         $sortField = input('sort_field/s', '');// score=积分 num=兑换量
 | ||||
|         $sortValue = input('sort_value/s', '');//desc=降序 asc=升序
 | ||||
| 
 | ||||
|         $rules = [ | ||||
|             'page|页数'         => 'integer|gt:0', | ||||
|             'size|每页数量'       => 'integer|gt:0', | ||||
|             'type|类型'         => 'in:newest,'.SpuModel::TYPE_NORMAL, | ||||
|             'sort_field|排序字段' => 'in:score,amount', | ||||
|             'sort_value|排序值'  => 'in:asc,desc', | ||||
|         ]; | ||||
| 
 | ||||
|         $message = [ | ||||
|             'type.in'       => '类型错误', | ||||
|             '$sortField.in' => '排序字段错误', | ||||
|             'sort_value.in' => '排序值错误', | ||||
|         ]; | ||||
| 
 | ||||
|         $params = input(); | ||||
| 
 | ||||
|         $validate = $this->validateByApi($params, $rules, $message); | ||||
|         if ($validate !== true) { | ||||
|             return $validate; | ||||
|         } | ||||
| 
 | ||||
|         $order = [];//排序
 | ||||
| 
 | ||||
|         // 综合排序
 | ||||
|         if ($type === SpuModel::TYPE_NORMAL) { | ||||
|             $order = [ | ||||
|                 'sort' => 'desc', | ||||
|                 'id'   => 'desc', | ||||
|             ]; | ||||
|         } | ||||
| 
 | ||||
|         // 最新排序
 | ||||
|         if ($type === 'newest') { | ||||
|             $order = ['published_at' => 'desc']; | ||||
|         } | ||||
| 
 | ||||
|         // 兑换量排序
 | ||||
|         if (!empty($sortField)) { | ||||
|             if (empty($sortValue)) { | ||||
|                 return $this->json(4003, '排序参数错误'); | ||||
|             } | ||||
|             $order = [ | ||||
|                 $sortField => $sortValue | ||||
|             ]; | ||||
|         } | ||||
| 
 | ||||
|         $params['is_score'] = SpuModel::COMMON_ON; | ||||
|         $params['fields']   = SpuModel::scoreListFields(); | ||||
| 
 | ||||
|         $list = $repo->listForFront($params, function ($q) { | ||||
|             return $q->with([ | ||||
|                 'activity_info' => function ($query) { | ||||
|                     $query->withoutField('content'); | ||||
|                 } | ||||
|             ]); | ||||
|         }, $order); | ||||
| 
 | ||||
|         return $this->json(0, 'success', $list); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 收藏列表 | ||||
|      * | ||||
|      * @return Json | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public function collection(): Json | ||||
|     { | ||||
|         $rules = [ | ||||
|             'page|页数'   => 'integer', | ||||
|             'size|每页数量' => 'integer', | ||||
|         ]; | ||||
| 
 | ||||
|         $params    = input(); | ||||
|         $page      = $params['page'] ?? 1; | ||||
|         $size      = $params['size'] ?? 10; | ||||
|         $accountId = $this->request->user['user_id'] ?? 0; | ||||
| 
 | ||||
| 
 | ||||
|         $params['page'] = 1; | ||||
|         $params['size'] = 0; | ||||
| 
 | ||||
|         $validate = $this->validateByApi($params, $rules); | ||||
|         if ($validate !== true) { | ||||
|             return $validate; | ||||
|         } | ||||
| 
 | ||||
|         //获取收藏相关
 | ||||
|         $collection = AccountRecord::where('type', AccountRecord::TYPE_SPU) | ||||
|             ->where('action', AccountRecord::ACTION_COLLECT) | ||||
|             ->where('account_id', $accountId) | ||||
|             ->where('is_record', AccountRecord::COMMON_ON) | ||||
|             ->order('recorded_at', 'desc'); | ||||
| 
 | ||||
|         $total = $collection->count(); | ||||
|         if ($total <= 0) { | ||||
|             return $this->json(0, 'success', [ | ||||
|                 'total'   => 0, | ||||
|                 'current' => $page, | ||||
|                 'size'    => $size, | ||||
|                 'list'    => new Collection(), | ||||
|             ]); | ||||
|         } | ||||
| 
 | ||||
|         $recordList = $collection->page($page)->limit($size)->field('relation_id,recorded_at')->select(); | ||||
| 
 | ||||
|         $where   = []; | ||||
|         $where[] = ['id', 'in', $recordList->column('relation_id')]; | ||||
| 
 | ||||
|         $list = SpuRepository::getInstance()->listForFront($params, function ($q) { | ||||
|             return $q->with([ | ||||
|                 'activity_info' => function ($query) { | ||||
|                     $query->withoutField('content'); | ||||
|                 } | ||||
|             ]); | ||||
|         }, [], $where); | ||||
| 
 | ||||
|         $data = []; | ||||
|         $spuList = $list['list']->toArray(); | ||||
|         foreach ($recordList as $record) { | ||||
|             foreach ($spuList as $key => $spu) { | ||||
|                 if ($record['relation_id'] == $spu['id']) { | ||||
|                     $data[] = $spu; | ||||
|                     unset($spuList[$key]); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         $list['total']   = $total; | ||||
|         $list['current'] = $page; | ||||
|         $list['size']    = $size; | ||||
|         $list['list']    = $data; | ||||
| 
 | ||||
|         return $this->json(0, 'success', $list); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     /** | ||||
|      * SPU 详情 | ||||
|      */ | ||||
|     public function detail(): Json | ||||
|     { | ||||
|         $repo       = SpuRepository::getInstance(); | ||||
|         $id         = input('id/d', 0); | ||||
|         $shareId    = input('share_id/d', 0);//分享人ID
 | ||||
|         $isActivity = input('is_activity/d', 0);//分享人ID
 | ||||
|         $accountId  = $this->request->user['user_id'] ?? 0; | ||||
| 
 | ||||
|         try { | ||||
|             $data = $repo->detail($id, $accountId, $shareId, (bool) $isActivity); | ||||
|             return $this->json(0, 'success', $data); | ||||
|         } catch (RepositoryException $e) { | ||||
|             return $this->json(4001, $e->getMessage()); | ||||
|         } catch (Exception $e) { | ||||
|             $repo->log($e->getMessage(), $e); | ||||
|             return $this->json(5000, '获取详情失败'); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 获取指定活动商品的拼团列表 仅限拼团活动商品 | ||||
|      */ | ||||
|     public function groupList(): Json | ||||
|     { | ||||
|         $id = input('id/d', 0); | ||||
| 
 | ||||
|         try { | ||||
|             $data = OrderRepository::getInstance()->getGroupList($id); | ||||
|             return $this->json(0, 'success', $data); | ||||
|         } catch (RepositoryException $e) { | ||||
|             return $this->json(4001, $e->getMessage()); | ||||
|         } catch (Exception $e) { | ||||
|             SpuRepository::log($e->getMessage(), $e); | ||||
|             return $this->json(5000, '获取拼团列表失败'); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 收藏 | ||||
|      */ | ||||
|     public function record(): Json | ||||
|     { | ||||
|         if (!$this->request->isPost()) { | ||||
|             return $this->json(4000, '无效请求'); | ||||
|         } | ||||
| 
 | ||||
|         $accountId = $this->request->user['user_id'] ?? 0; | ||||
|         $id        = $this->request->param('id/d', 0); | ||||
|         $action    = $this->request->param('action/s', ''); | ||||
| 
 | ||||
|         try { | ||||
|             if ($accountId <= 0 || $id <= 0) { | ||||
|                 return $this->json(4001, '无效请求'); | ||||
|             } | ||||
| 
 | ||||
|             if (!in_array($action, AccountRecord::allowActions())) { | ||||
|                 return $this->json(4001, '操作类型参数错误'); | ||||
|             } | ||||
| 
 | ||||
|             if (!SpuModel::findById($id)) { | ||||
|                 return $this->json(4001, '商品不存在'); | ||||
|             } | ||||
| 
 | ||||
|             AccountRecord::record($accountId, AccountRecord::TYPE_SPU, $action, $id); | ||||
|         } catch (Exception $e) { | ||||
|             Log::error('[商品记录失败]'.$e->getMessage()); | ||||
|             return $this->json(5000, '操作失败'); | ||||
|         } | ||||
| 
 | ||||
|         return $this->json(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 取消 收藏 | ||||
|      */ | ||||
|     public function unRecord(): Json | ||||
|     { | ||||
|         if (!$this->request->isPost()) { | ||||
|             return $this->json(4000, '无效请求'); | ||||
|         } | ||||
| 
 | ||||
|         $accountId = $this->request->user['user_id'] ?? 0; | ||||
|         $id        = $this->request->param('id/d', 0); | ||||
|         $action    = $this->request->param('action/s', ''); | ||||
| 
 | ||||
|         try { | ||||
|             if ($accountId <= 0 || $id <= 0) { | ||||
|                 return $this->json(4001, '无效请求'); | ||||
|             } | ||||
| 
 | ||||
|             if (!in_array($action, AccountRecord::allowActions())) { | ||||
|                 return $this->json(4001, '操作类型参数错误'); | ||||
|             } | ||||
| 
 | ||||
|             if (!SpuModel::findById($id)) { | ||||
|                 return $this->json(4001, '商品不存在'); | ||||
|             } | ||||
| 
 | ||||
|             AccountRecord::unRecord($accountId, $id, AccountRecord::TYPE_SPU, $action); | ||||
|         } catch (Exception $e) { | ||||
|             Log::error('[取消商品记录失败]'.$e->getMessage()); | ||||
|             return $this->json(5000, '操作失败'); | ||||
|         } | ||||
| 
 | ||||
|         return $this->json(); | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,77 @@ | |||
| <?php | ||||
| 
 | ||||
| namespace app\controller\api; | ||||
| 
 | ||||
| use app\model\AccountFootmarks; | ||||
| use app\model\Event; | ||||
| use Exception; | ||||
| use think\db\exception\DataNotFoundException; | ||||
| use think\db\exception\DbException; | ||||
| use think\db\exception\ModelNotFoundException; | ||||
| use think\response\Json; | ||||
| 
 | ||||
| class Statistics extends Base | ||||
| { | ||||
|     protected $noNeedLogin = ['event']; | ||||
|     /** | ||||
|      * 事件列表 | ||||
|      * | ||||
|      * @return Json | ||||
|      * @throws DataNotFoundException | ||||
|      * @throws DbException | ||||
|      * @throws ModelNotFoundException | ||||
|      */ | ||||
|     public function event(): Json | ||||
|     { | ||||
|         $data = Event::field('id, name')->select()->toArray(); | ||||
| 
 | ||||
|         return $this->json(0, 'success', $data); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 上报 | ||||
|      * | ||||
|      * @return Json | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public function report(): Json | ||||
|     { | ||||
|         $data      = input(); | ||||
|         $accountId = $this->request->user['user_id'] ?? 0; | ||||
| 
 | ||||
|         if (empty($data)) { | ||||
|             return $this->json(); | ||||
|         } | ||||
| 
 | ||||
|         if (!is_array($data)) { | ||||
|             $data = json_decode($data, true); | ||||
|         } | ||||
| 
 | ||||
|         $insert = []; | ||||
|         if (count($data) > 1000) { | ||||
|             //TODO 太大就分片处理
 | ||||
| 
 | ||||
|         } else { | ||||
|             foreach ($data as $d) { | ||||
|                 if (!isset($d['e']) || !isset($d['t'])) { | ||||
|                     return $this->json(4001, '参数错误'); | ||||
|                 } | ||||
|                 $arr               = []; | ||||
|                 $arr['event_id']   = (int) ($d['e'] ?? 0); | ||||
|                 $arr['account_id'] = $accountId; | ||||
|                 $arr['content_id'] = (int) ($d['c'] ?? 0); | ||||
|                 $t = (strlen($d['t']) == 13) ?  $d['t'] / 1000 : $d['t']; | ||||
|                 $arr['created_at'] = date('Y-m-d H:i:s', $t); | ||||
| 
 | ||||
|                 $insert[] = $arr; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         // 若量大 时间长 可丢入队列操作
 | ||||
|         if (count($insert) > 0) { | ||||
|             (new AccountFootmarks())->saveAll($insert); | ||||
|         } | ||||
| 
 | ||||
|         return $this->json(); | ||||
|     } | ||||
| } | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							|  | @ -0,0 +1,132 @@ | |||
| <?php | ||||
| namespace app\controller\api\file; | ||||
| 
 | ||||
| use app\controller\api\Base; | ||||
| use app\model\File; | ||||
| use app\model\System; | ||||
| use app\service\Image; | ||||
| use app\validate\Upload as VUpload; | ||||
| use think\facade\Config; | ||||
| use think\facade\Filesystem; | ||||
| use think\facade\Lang; | ||||
| use think\response\Json; | ||||
| 
 | ||||
| /** | ||||
|  * 文件上传 | ||||
|  * | ||||
|  * Class Upload | ||||
|  * @package app\controller\api\file | ||||
|  */ | ||||
| class Upload extends Base | ||||
| { | ||||
|     protected $noNeedLogin = []; | ||||
| 
 | ||||
|     // 图片上传是否进行压缩[max-width:1920px]
 | ||||
|     private bool $isCompress = true; | ||||
|     private $validate = null; | ||||
|     // 文件上传对外默认保存目录(相对路径)
 | ||||
|     private string $uploadPath = ''; | ||||
|     // 文件上传对外默认保存目录是否有写权限
 | ||||
|     private bool $uploadPathIsWritable = false; | ||||
|     protected bool $saveToOos = false; | ||||
| 
 | ||||
|     public function initialize() | ||||
|     { | ||||
|         parent::initialize(); | ||||
| 
 | ||||
|         $system = System::getSystem(); | ||||
|         if (!empty($system)) { | ||||
|             $this->isCompress = $system['compress'] ?? true; | ||||
|         } | ||||
|         $this->validate = new VUpload(); | ||||
|         $this->uploadPath = Config::get('filesystem.disks.local.url'); | ||||
|         if(is_writable(app()->getRootPath() . 'public' . $this->uploadPath)){ | ||||
|             $this->uploadPathIsWritable = true; | ||||
|         } | ||||
| 
 | ||||
|         $this->cancelTimeLimit(); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     /** | ||||
|      * 通用文件上传 | ||||
|      * @return Json | ||||
|      */ | ||||
|     public function file() | ||||
|     { | ||||
|         $file = request()->file('file'); | ||||
|         if (empty($file)) { | ||||
|             return  $this->json(4001, '请上传的文件'); | ||||
|         } | ||||
| 
 | ||||
|         if($this->validate->checkFile($file)){ | ||||
|             try{ | ||||
|                 if(!$this->uploadPathIsWritable){ | ||||
|                     throw new \Exception('上传文件夹需要写入权限'); | ||||
|                 } | ||||
|                 $src = Filesystem::putFile(date('Ymd'), $file, 'uniqid'); | ||||
|                 $src = $this->uploadPath . '/' . $src; | ||||
|                 $return['src'] = $src; | ||||
|                 $return['name'] = $file->getOriginalName(); | ||||
| 
 | ||||
|                 //加入上传文件表
 | ||||
|                 File::add($file, $src, 'file'); | ||||
|             } catch (\Exception $e) { | ||||
|                 return $this->json(4003, $e->getMessage()); | ||||
|             } | ||||
| 
 | ||||
|             return $this->json(0,'success', $return); | ||||
|         }else{ | ||||
| 
 | ||||
|             $errorMsg = Lang::get($this->validate->getError()); | ||||
|             return $this->json(4002, $errorMsg); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 通用图片上传 | ||||
|      * @return Json | ||||
|      */ | ||||
|     public function image() | ||||
|     { | ||||
|         $image = request()->file('image'); | ||||
|         if (empty($image)) { | ||||
|             return  $this->json(4001, '请上传图片文件'); | ||||
|         } | ||||
|         $md5 = $image->md5();//文件md5
 | ||||
|         if($this->validate->checkImage($image)){ | ||||
|             try{ | ||||
|                 if(!$this->uploadPathIsWritable){ | ||||
|                     throw new \Exception('上传文件夹需要写入权限'); | ||||
|                 } | ||||
|                 $src = Filesystem::putFile(date('Ymd'), $image, 'uniqid'); | ||||
|                 $src = $this->uploadPath . '/' . $src; | ||||
|                 $return['src'] = $src; | ||||
|                 if($this->isCompress){ | ||||
|                     Image::resize($src); | ||||
|                 } | ||||
|                | ||||
|                 //加入上传文件表
 | ||||
|                 File::add($image, $src,$md5); | ||||
|             } catch (\Exception $e) { | ||||
|                 return $this->json(4003, $e->getMessage()); | ||||
|             } | ||||
| 
 | ||||
|             return $this->json(0, 'success', $return); | ||||
|         }else{ | ||||
| 
 | ||||
|             $errorMsg = Lang::get($this->validate->getError()); | ||||
|             return $this->json(4002, $errorMsg); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     /** | ||||
|      * 同步到OOS服务器存储 | ||||
|      * @param string $src | ||||
|      */ | ||||
|     private function syncToOos(string $src) | ||||
|     { | ||||
| 
 | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,35 @@ | |||
| <?php | ||||
| 
 | ||||
| /** | ||||
|  * @OA\Info( | ||||
|  *     description="商城接口", | ||||
|  *     version="1.0.0", | ||||
|  *     title="大头商城", | ||||
|  * ) | ||||
|  */ | ||||
| 
 | ||||
| /** | ||||
|  * @OA\Tag( | ||||
|  *     name="common", | ||||
|  *     description="通用", | ||||
|  * ) | ||||
|  * | ||||
|  * @OA\Tag( | ||||
|  *     name="home", | ||||
|  *     description="首页", | ||||
|  * ) | ||||
|  * | ||||
|  * @OA\Tag( | ||||
|  *     name="goods", | ||||
|  *     description="商品相关", | ||||
|  * ) | ||||
|  * @OA\Tag( | ||||
|  *     name="order", | ||||
|  *     description="订单相关", | ||||
|  * ) | ||||
|  * @OA\Tag( | ||||
|  *     name="user", | ||||
|  *     description="用户相关", | ||||
|  * ) | ||||
|  * | ||||
|  */ | ||||
|  | @ -0,0 +1,488 @@ | |||
| <?php | ||||
| 
 | ||||
| 
 | ||||
| namespace app\controller\manager; | ||||
| 
 | ||||
| use app\model\Log; | ||||
| use app\service\AliOss; | ||||
| use think\facade\Config; | ||||
| use Exception; | ||||
| use app\model\Attachment as AttachmentModel; | ||||
| use think\db\exception\DataNotFoundException; | ||||
| use think\db\exception\DbException; | ||||
| use think\db\exception\ModelNotFoundException; | ||||
| use think\exception\ValidateException; | ||||
| use think\response\Json; | ||||
| use think\response\View; | ||||
| 
 | ||||
| /** | ||||
|  * 附件管理 - 素材管理 | ||||
|  * Class Attachment | ||||
|  * @package app\controller\manager | ||||
|  */ | ||||
| class Attachment extends Base | ||||
| { | ||||
|     protected $noNeedLogin = ['file', 'getSize', 'md5List', 'pathDirHandle', 'toOss', 'delLostFile', 'test']; | ||||
|     protected $DIRECTORY_SEPARATOR = "/"; | ||||
|     protected function initialize() | ||||
|     { | ||||
|         parent::initialize(); // TODO: Change the autogenerated stub
 | ||||
|         $this->DIRECTORY_SEPARATOR = DIRECTORY_SEPARATOR == "\\" ? "/" : DIRECTORY_SEPARATOR; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 删除 | ||||
|      * | ||||
|      * @return Json | ||||
|      * @throws DataNotFoundException | ||||
|      * @throws DbException | ||||
|      * @throws ModelNotFoundException | ||||
|      */ | ||||
|     public function del(): Json | ||||
|     { | ||||
|         if ($this->request->isPost()) { | ||||
|             $ids = input('post.ids/a', []); | ||||
|             if (empty($ids)) { | ||||
|                 $ids[] = input('post.id/d'); | ||||
|             } | ||||
| 
 | ||||
|             $items = AttachmentModel::whereIn('id', $ids)->where('is_dir', AttachmentModel::COMMON_ON)->select(); | ||||
|             if ($items->where('is_dir', AttachmentModel::COMMON_ON)->count()) { | ||||
|                 $dirPaths = []; | ||||
|                 foreach ($items->toArray() as $item) { | ||||
|                     $dirPaths[] = $item['path'].$item['name']. $this->DIRECTORY_SEPARATOR ; | ||||
|                 } | ||||
|                 if (AttachmentModel::where('path', 'in', $dirPaths)->count()) { | ||||
|                     return $this->json(4001, '待删除目录下存在内容!'); | ||||
|                 } | ||||
|             } | ||||
|             AttachmentModel::deleteByIds($ids); | ||||
| 
 | ||||
|             Log::write(get_class().'Del', 'del', '涉及到的ID为:'.implode(',', $ids)); | ||||
|             return $this->json(); | ||||
|         } | ||||
|         return $this->json(4001, '非法请求!'); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 单个字段编辑 | ||||
|      * | ||||
|      * @return Json | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public function modify(): Json | ||||
|     { | ||||
|         if ($this->request->isPost()) { | ||||
|             $item     = input('post.'); | ||||
|             $validate = $this->validateByApi($item, [ | ||||
|                 'field' => 'require', | ||||
|                 'value' => 'require', | ||||
|             ]); | ||||
| 
 | ||||
|             if ($validate !== true) { | ||||
|                 return $validate; | ||||
|             } | ||||
| 
 | ||||
|             if (!$info = AttachmentModel::findById($item['id'])) { | ||||
|                 return $this->json(4001, '记录不存在'); | ||||
|             } | ||||
| 
 | ||||
|             if ($item['field'] == 'name' && $info['is_dir'] == AttachmentModel::COMMON_ON) { | ||||
|                 return $this->json(4002, '目录名称不能修改'); | ||||
| 
 | ||||
|             } | ||||
| 
 | ||||
|             $update = [$item['field'] => $item['value']]; | ||||
| 
 | ||||
|             try { | ||||
|                 $info->save($update); | ||||
|                 return $this->json(); | ||||
|             } catch (ValidateException $e) { | ||||
|                 return $this->json(4001, $e->getError()); | ||||
|             } | ||||
|         } | ||||
|         return $this->json(4000, '非法请求'); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 添加 | ||||
|      * | ||||
|      * @return Json|View | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public function add() | ||||
|     { | ||||
|         if ($this->request->isPost()) { | ||||
|             $item = input('post.'); | ||||
| 
 | ||||
|             $validate = $this->validateByApi($item, [ | ||||
|                 'title|合集标题'     => 'require', | ||||
|                 'user|虚拟用户'      => 'require', | ||||
|                 'headimg|虚拟用户头像' => 'require', | ||||
|             ]); | ||||
| 
 | ||||
|             if ($validate !== true) { | ||||
|                 return $validate; | ||||
|             } | ||||
| 
 | ||||
|             try { | ||||
|                 $now                = date('Y-m-d H:i:s'); | ||||
|                 $item['created_at'] = $now; | ||||
|                 $item['created_by'] = $this->auth['user_id']; | ||||
|                 AttachmentModel::create($item); | ||||
|                 return $this->json(); | ||||
|             } catch (ValidateException $e) { | ||||
|                 return $this->json(4001, $e->getError()); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         return $this->view(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 添加文件夹 | ||||
|      * | ||||
|      * @return Json|View | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public function addFolder() | ||||
|     { | ||||
|         if ($this->request->isPost()) { | ||||
|             $item = input('post.'); | ||||
| 
 | ||||
|             $validate = $this->validateByApi($item, [ | ||||
|                 'name|文件夹名称' => 'require|alphaDash|max:20', | ||||
|                 'path|文件路径'  => 'require', | ||||
|             ]); | ||||
| 
 | ||||
|             // 例 name=dir4 path=/storage/dir1/dir2/dir3
 | ||||
| 
 | ||||
|             // 去首尾/
 | ||||
|             $path = trim($item['path'],  $this->DIRECTORY_SEPARATOR ); | ||||
|             // 全路径 如 /storage/dir1/dir2/dir3/dir4/  注意前后都有/
 | ||||
|             $fullPath =  $this->DIRECTORY_SEPARATOR .$path. $this->DIRECTORY_SEPARATOR .$item['name']. $this->DIRECTORY_SEPARATOR ; | ||||
| 
 | ||||
|             if ($validate !== true) { | ||||
|                 return $validate; | ||||
|             } | ||||
| 
 | ||||
|             AttachmentModel::pathDirHandle($fullPath); | ||||
|             return $this->json(); | ||||
|         } | ||||
| 
 | ||||
|         $path = input('path/s', AttachmentModel::ROOT_PATH); | ||||
| 
 | ||||
|         $this->data['path'] = $path; | ||||
|         return $this->view(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 图片列表 | ||||
|      * | ||||
|      * @return View|Json | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public function image() | ||||
|     { | ||||
|         $path = input('post.path', AttachmentModel::ROOT_PATH); | ||||
|         $path =  $this->DIRECTORY_SEPARATOR . trim($path,  $this->DIRECTORY_SEPARATOR). $this->DIRECTORY_SEPARATOR; | ||||
|         $path = str_replace("\\","/",$path); | ||||
|         $type     = input('type/s', 'image'); | ||||
|         $selected = input('selected', false); | ||||
|         $multiple = input('multiple', false); | ||||
| 
 | ||||
|         Config::load('extra/alioss', 'alioss'); | ||||
|         $config = config('alioss'); | ||||
|         $oss    = $config['customDomain']; | ||||
|         if ($this->request->isPost()) { | ||||
|             $items = $this->list($path, ['image']); | ||||
| 
 | ||||
|             return $this->json(0, '操作成功', $items); | ||||
|         } | ||||
| 
 | ||||
|         $this->data['path']     = $path; | ||||
|         $this->data['oss']      = $oss; | ||||
|         $this->data['type']     = $type; | ||||
|         $this->data['multiple'] = $multiple; | ||||
|         $this->data['selected'] = $selected; | ||||
|         return $this->view(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 视频列表 | ||||
|      * | ||||
|      * @return View|Json | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public function video() | ||||
|     { | ||||
|         $path = input('post.path', AttachmentModel::ROOT_PATH); | ||||
|         $path =  $this->DIRECTORY_SEPARATOR . trim($path,  $this->DIRECTORY_SEPARATOR ) .  $this->DIRECTORY_SEPARATOR ; | ||||
|         $path = str_replace("\\","/",$path); | ||||
|         $type     = input('type/s', 'video'); | ||||
|         $selected = input('selected', false); | ||||
|         $multiple = input('multiple', false); | ||||
| 
 | ||||
|         Config::load('extra/alioss', 'alioss'); | ||||
|         $config = config('alioss'); | ||||
|         $oss    = $config['customDomain']; | ||||
|         if ($this->request->isPost()) { | ||||
|             $items = $this->list($path, ['video']); | ||||
| 
 | ||||
|             return $this->json(0, '操作成功', $items); | ||||
|         } | ||||
| 
 | ||||
|         $this->data['path']     = $path; | ||||
|         $this->data['oss']      = $oss; | ||||
|         $this->data['type']     = $type; | ||||
|         $this->data['multiple'] = $multiple; | ||||
|         $this->data['selected'] = $selected; | ||||
|         return $this->view(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 文件列表 | ||||
|      * | ||||
|      * @return View|Json | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public function file() | ||||
|     { | ||||
|         Config::load('extra/alioss', 'alioss'); | ||||
|         $config   = config('alioss'); | ||||
|         $oss      = $config['customDomain']; | ||||
|         $type     = input('type/s', 'all'); | ||||
|         $selected = input('selected', false); | ||||
|         $multiple = input('multiple', false); | ||||
| 
 | ||||
|         if ($this->request->isPost()) { | ||||
|             $page         = input('post.page', 1); | ||||
|             $size         = input('post.size', 20); | ||||
|             $searchParams = input('searchParams'); | ||||
|             $where        = []; | ||||
| 
 | ||||
|             if ($searchParams) { | ||||
|                 foreach ($searchParams as $key => $param) { | ||||
|                     if (!empty($param)) { | ||||
|                         if (is_string($param)) { | ||||
|                             if ($key == 'is_oss') { | ||||
|                                 if ($param >= 0) { | ||||
|                                     $where[] = ['is_oss', '=', $param]; | ||||
|                                 } | ||||
|                             } else { | ||||
|                                 $where[] = [$key, 'like', '%'.$param.'%']; | ||||
|                             } | ||||
|                         } elseif (is_array($param)) { | ||||
|                             //数组空元素去除
 | ||||
|                             foreach ($param as $k => $val) { | ||||
|                                 if (empty($val)) { | ||||
|                                     unset($param[$k]); | ||||
|                                 } | ||||
|                             } | ||||
|                             if (!empty($param)) { | ||||
|                                 $where[] = [$key, 'in', $param]; | ||||
|                             } | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
| 
 | ||||
|             if ($type !== 'all') { | ||||
|                 $where[] = ['type', '=', $type]; | ||||
|             } | ||||
| 
 | ||||
|             $items = AttachmentModel::findList($where, [], $page, $size, function ($q) { | ||||
|                 return $q->where('type', '<>', 'dir')->order('updated_at', 'desc'); | ||||
|             }); | ||||
| 
 | ||||
|             $items['list']->each(function ($item) { | ||||
|                 $item->size_text = getFilesize($item['size'] ?? 0); | ||||
|             }); | ||||
| 
 | ||||
|             return $this->json(0, '操作成功', $items); | ||||
|         } | ||||
| 
 | ||||
|         $this->data['oss']      = $oss; | ||||
|         $this->data['type']     = $type; | ||||
|         $this->data['multiple'] = $multiple; | ||||
|         $this->data['selected'] = $selected; | ||||
|         return $this->view(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 一键删除失效记录 即oss不存在&&本地不存在 | ||||
|      * | ||||
|      * @return Json | ||||
|      */ | ||||
|     public function delLostFile(): Json | ||||
|     { | ||||
|         if ($this->request->isPost()) { | ||||
|             $total = AttachmentModel::where('type', '<>', AttachmentModel::TYPE_DIR) | ||||
|                 ->where('is_dir', AttachmentModel::COMMON_OFF) | ||||
|                 ->where('is_oss', AttachmentModel::COMMON_OFF) | ||||
|                 ->where('has_local', AttachmentModel::COMMON_OFF) | ||||
|                 ->count(); | ||||
|             if ($total === 0) { | ||||
|                 return $this->json(0, 'success', ['total' => $total]); | ||||
|             } | ||||
| 
 | ||||
|             if (AttachmentModel::where('type', '<>', AttachmentModel::TYPE_DIR) | ||||
|                 ->where('is_dir', AttachmentModel::COMMON_OFF) | ||||
|                 ->where('is_oss', AttachmentModel::COMMON_OFF) | ||||
|                 ->where('has_local', AttachmentModel::COMMON_OFF) | ||||
|                 ->delete()) { | ||||
|                 return $this->json(0, 'success', ['total' => $total]); | ||||
|             } | ||||
|             return $this->json(4004, '删除失败'); | ||||
|         } | ||||
|         return $this->json(4000, '请求错误'); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 一键上传本地文件到OSS | ||||
|      * | ||||
|      * @return Json | ||||
|      */ | ||||
|     public function toOss(): Json | ||||
|     { | ||||
|         if ($this->request->isPost()) { | ||||
|             Config::load('extra/alioss', 'alioss'); | ||||
|             $config = config('alioss'); | ||||
| 
 | ||||
|             $ossObject = AliOss::instance(); | ||||
|             $bucket    = $config['bucket']; | ||||
| 
 | ||||
|             $total = AttachmentModel::where('type', '<>', AttachmentModel::TYPE_DIR) | ||||
|                 ->where('is_dir', AttachmentModel::COMMON_OFF) | ||||
|                 ->where('is_oss', AttachmentModel::COMMON_OFF) | ||||
|                 ->field('id') | ||||
|                 ->count(); | ||||
|             $done  = 0; | ||||
|             $none  = 0; | ||||
|             if ($total === 0) { | ||||
|                 return $this->json(0, 'success', ['total' => $total, 'done' => $done, 'none' => $none]); | ||||
|             } | ||||
|             try { | ||||
|                 AttachmentModel::where('type', '<>', AttachmentModel::TYPE_DIR) | ||||
|                     ->where('is_dir', AttachmentModel::COMMON_OFF) | ||||
|                     ->where('is_oss', AttachmentModel::COMMON_OFF) | ||||
|                     ->field('id,src') | ||||
|                     ->chunk(3, function ($items) use ($ossObject, $bucket, &$done, &$none) { | ||||
|                         $doneIds = []; | ||||
|                         $noneIds = []; | ||||
|                         foreach ($items as $item) { | ||||
|                             if ($item['src']) { | ||||
|                                 $realPath = public_path().ltrim($item['src'],  $this->DIRECTORY_SEPARATOR ); | ||||
|                                 if (!file_exists($realPath)) { | ||||
|                                     $none++; | ||||
|                                     $noneIds[] = $item['id']; | ||||
|                                     continue; | ||||
|                                 } | ||||
|                                 $pathInfo = pathinfo($item['src']); | ||||
|                                 $object   = ltrim($item['src'],  $this->DIRECTORY_SEPARATOR ); | ||||
|                                 //是否存在
 | ||||
|                                 if (!$ossObject->doesObjectExist($bucket, $object)) { | ||||
|                                     //创建目录
 | ||||
|                                     $ossObject->createObjectDir($bucket, ltrim($pathInfo['dirname'],  $this->DIRECTORY_SEPARATOR )); | ||||
| 
 | ||||
|                                     $ossObject->uploadFile($bucket, $object, $realPath); | ||||
|                                 } | ||||
|                                 $doneIds[] = $item['id']; | ||||
|                                 $done++; | ||||
|                             } | ||||
|                         } | ||||
| 
 | ||||
|                         // 失效标记
 | ||||
|                         if ($noneIds) { | ||||
|                             $update = ['is_oss' => AttachmentModel::COMMON_OFF, 'has_local' => AttachmentModel::COMMON_OFF]; | ||||
|                             (new AttachmentModel())->where('id', 'in', $noneIds)->update($update); | ||||
|                         } | ||||
| 
 | ||||
|                         // 完成标记
 | ||||
|                         if ($doneIds) { | ||||
|                             $update = ['is_oss' => AttachmentModel::COMMON_ON]; | ||||
|                             (new AttachmentModel())->where('id', 'in', $doneIds)->update($update); | ||||
|                         } | ||||
|                     }); | ||||
| 
 | ||||
|                 return $this->json(0, 'success', ['total' => $total, 'done' => $done, 'none' => $none]); | ||||
|             } catch (Exception $e) { | ||||
|                 \think\facade\Log::error('本地文件一键上传OSS失败 '.$e->getMessage()); | ||||
|                 return $this->json(0, 'success', ['total' => $total, 'done' => $done, 'none' => $none]); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 指定类型附件列表 | ||||
|      * | ||||
|      * @param  array  $type | ||||
|      * @param  string  $path | ||||
|      * @return array | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     protected function list(string $path, array $type): array | ||||
|     { | ||||
|         $type[]  = 'dir'; | ||||
|         $where[] = ['path', '=', $path]; | ||||
|         $where[] = ['type', 'in', $type]; | ||||
|         $items   = AttachmentModel::findList($where, [], 1, 0, function ($q) { | ||||
|             return $q->order('is_dir', 'desc')->order('updated_at', 'desc'); | ||||
|         }); | ||||
|         $items['list']->each(function ($item) { | ||||
|             $item->size_text = getFilesize($item['size'] ?? 0); | ||||
|         }); | ||||
|         $items['path'] = $path; | ||||
| 
 | ||||
|         return $items; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 获取文件大小 | ||||
|      * | ||||
|      * @return Json | ||||
|      */ | ||||
|     public function getSize(): Json | ||||
|     { | ||||
|         $path  = input('post.path', ''); | ||||
|         $types = input('post.type/a', []); | ||||
| 
 | ||||
|         $size = ''; | ||||
|         if (empty($path)) { | ||||
|             return $this->json(0, '操作成功', $size); | ||||
|         } | ||||
|         $path = str_replace("\\","/",$path); | ||||
|         $total = AttachmentModel::where('path', 'like', $path.'%') | ||||
|             ->when(!empty($types), function ($q) use ($types) { | ||||
|                 $q->where('type', 'in', $types); | ||||
|             }) | ||||
|             ->sum('size'); | ||||
| 
 | ||||
|         return $this->json(0, '操作成功', getFilesize($total)); | ||||
|     } | ||||
| 
 | ||||
|     // 将没有md5的文件 更新md5  仅针对本地文件
 | ||||
|     public function md5List() | ||||
|     { | ||||
|         $noMd5List = AttachmentModel::whereNull('md5')->select(); | ||||
|         $update    = []; | ||||
|         foreach ($noMd5List as $item) { | ||||
|             try { | ||||
|                 if (!empty($item['src'])) { | ||||
|                     $arr        = []; | ||||
|                     $path       = public_path().ltrim($item['src'],  $this->DIRECTORY_SEPARATOR ); | ||||
|                     $file       = new \think\File($path); | ||||
|                     $arr['md5'] = $file->md5(); | ||||
|                     $arr['id']  = $item['id']; | ||||
| 
 | ||||
|                     $update[] = $arr; | ||||
|                 } | ||||
|             } catch (Exception $e) { | ||||
|                 continue; | ||||
|             } | ||||
| 
 | ||||
|         } | ||||
|         (new AttachmentModel())->saveAll($update); | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,153 @@ | |||
| <?php | ||||
| namespace app\controller\manager; | ||||
| 
 | ||||
| use think\facade\{Db, Config, Env}; | ||||
| use app\model\{Log as MLog}; | ||||
| use app\service\Tool; | ||||
| 
 | ||||
| class Backup extends Base | ||||
| { | ||||
|     /** | ||||
|      * 因受mysql 配置参数net_buffer_length和max_allowed_packet大小的限制,因此insert语句改为单条插入 | ||||
|      * show VARIABLES like "%net_buffer_length%" 默认单条sql语句长度16k  | ||||
|      * show VARIABLES like "%max_allowed_packet%" 默认单个sql文件最大容量 | ||||
|      * sql 文件注释 -- + 空格之后填写注释内容 | ||||
|      * 因根目录文件夹权限限制,因此需要手动创建backup/data目录并赋予权限(www用户组) | ||||
|      */ | ||||
|     public function back() | ||||
|     { | ||||
|         ini_set('max_execution_time', 0); | ||||
|         ini_set("memory_limit",-1); | ||||
|         set_time_limit(0); | ||||
| 
 | ||||
|         $path = Config::get('filesystem.disks.backup.root') . '/'; | ||||
|         $dataBase = Env::get('database.database'); | ||||
|         // 不要使用单引号,双引号中的变量可以解析,单引号就是绝对的字符串
 | ||||
|         $eol = "\r\n"; | ||||
|         $eolB = "\r\n\r\n"; | ||||
|         $info = '-- ------------------------------'.$eol; | ||||
|         $info .= '-- 日期: '.date('Y-m-d H:i:s',time()).$eol; | ||||
|         $info .= '-- MySQL --Database - '.$dataBase.$eol; | ||||
|         $info .= '-- ------------------------------'.$eol; | ||||
| 
 | ||||
|         $info .= 'CREATE DATABASE IF NOT EXISTS `'.$dataBase.'` DEFAULT CHARACTER SET "utf8mb4" COLLATE "utf8mb4_general_ci";'.$eolB; | ||||
|         $info .= 'USE `'.$dataBase.'`;'.$eol; | ||||
| 
 | ||||
|         if(is_dir($path)) { | ||||
|             if(!is_writable($path)) { | ||||
|                 chmod($path, 0755); | ||||
|             } | ||||
|         } else { | ||||
|             mkdir($path, 0755, true); | ||||
|         } | ||||
|         $fileName = $path.$dataBase.'_'.date('YmdHis',time()).'.sql'; | ||||
|         if(file_exists($fileName)) { | ||||
|             @unlink($fileName); | ||||
|         } | ||||
|         // 以追加的方式写入
 | ||||
|         file_put_contents($fileName, $info, FILE_APPEND); | ||||
|         $tables = Db::query('show tables'); | ||||
|         foreach ($tables as $table) { | ||||
|             // 表结构
 | ||||
|             $tableName = $table['Tables_in_'.$dataBase]; | ||||
|             $sqlTable = 'SHOW CREATE TABLE '.$tableName; | ||||
|             $res = Db::query($sqlTable); | ||||
|             $infoTable = '-- ------------------------------'.$eol; | ||||
|             $infoTable .= '-- Table structure for `'.$tableName.'`'.$eol; | ||||
|             $infoTable .= '-- ------------------------------'.$eolB; | ||||
|             $infoTable .= 'DROP TABLE IF EXISTS `'.$tableName.'`;'.$eolB; | ||||
|             $infoTable .= $res[0]['Create Table'].';'.$eolB; | ||||
|             // 表数据
 | ||||
|             $infoTable .= '-- ------------------------------'.$eol; | ||||
|             $infoTable .= '-- Data for the table `'.$tableName.'`'.$eol; | ||||
|             $infoTable .= '-- ------------------------------'.$eolB; | ||||
|             file_put_contents($fileName, $infoTable, FILE_APPEND); | ||||
| 
 | ||||
|             $sqlData = 'select * from '.$tableName; | ||||
|             $data = Db::query($sqlData); | ||||
|             $count = count($data); | ||||
|             if ($count > 0) { | ||||
|                 $dataStr = 'INSERT INTO `'.$tableName.'` VALUE '; | ||||
|                 foreach ($data as $k => $item) { | ||||
|                     $valStr = '('; | ||||
|                     foreach ($item as $val) { | ||||
|                         // 字符串转义
 | ||||
|                         $val = addslashes($val); | ||||
|                         $valStr .= '"'.$val.'", '; | ||||
|                     } | ||||
|                     // 去除最后的逗号和空格
 | ||||
|                     $valStr = substr($valStr,0,strlen($valStr)-2); | ||||
|                     // 限制单条sql语句在16K以内(可根据mysql配置条件进行调整)
 | ||||
|                     $sqlLength = strlen($dataStr) + strlen($valStr); | ||||
|                     if($sqlLength >= (1024 * 16 - 10)) { | ||||
|                         $dataStr .= $valStr.');'.$eol; | ||||
|                         file_put_contents($fileName, $dataStr, FILE_APPEND); | ||||
|                         // 提前分段写入后需重置数据语句
 | ||||
|                         if ($k <= ($count-1)) { | ||||
|                             $dataStr = 'INSERT INTO `'.$tableName.'` VALUE '; | ||||
|                         } else { | ||||
|                             $dataStr = ''; | ||||
|                         } | ||||
|                     } else { | ||||
|                         if ($k < ($count-1)) { | ||||
|                             $dataStr .= $valStr.'),'.$eol; | ||||
|                         } else { | ||||
|                             $dataStr .= $valStr.');'.$eolB; | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|                 file_put_contents($fileName, $dataStr, FILE_APPEND); | ||||
|             } | ||||
|         } | ||||
|         clearstatcache(); | ||||
| 
 | ||||
|         $backups = explode('/', $fileName); | ||||
|         $backupName =  $backups[count($backups)-1]; | ||||
|         $src = Config::get('filesystem.disks.backup.url') . '/'; | ||||
|         return $this->json(0, '备份成功:' . $src . $backupName); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     public function index() | ||||
|     { | ||||
|         $path = Config::get('filesystem.disks.backup.root') . '/'; | ||||
|         $src = Config::get('filesystem.disks.backup.url') . '/'; | ||||
|         $items = []; | ||||
|         if(is_dir($path)) { | ||||
|             if(!is_readable($path)) { | ||||
|                 chmod($path,0755); | ||||
|             } | ||||
|             $files = scandir($path); | ||||
|             foreach ($files as $file) { | ||||
|                 if($file != '.' && $file != '..') { | ||||
|                     $ext = substr($file, -4); | ||||
|                     if ($ext == '.sql') { | ||||
|                         $creatTime = substr($file, -18, 14); | ||||
|                         $items[] = [ | ||||
|                             'file' => $file, | ||||
|                             'path' => $src . $file, | ||||
|                             'time' =>is_numeric($creatTime) ? date('Y-m-d H:i:s', strtotime($creatTime)) : '', | ||||
|                         ]; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         clearstatcache(); | ||||
| 
 | ||||
|         $this->data['items'] = $items; | ||||
|         $this->data['backupPath'] = str_replace('\\','/', $path); | ||||
|         return $this->view(); | ||||
|     } | ||||
|      | ||||
|     public function del() | ||||
|     { | ||||
|         if (request()->isPost()) { | ||||
|             $filePath = input('post.id'); | ||||
|             Tool::delFile($filePath); | ||||
|             MLog::write('backup', 'del', '删除了备份数据文件,文件路径为:' . $filePath); | ||||
|             return $this->json(); | ||||
|         } else { | ||||
|             return $this->json(1, '非法请求'); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,104 @@ | |||
| <?php | ||||
| 
 | ||||
| namespace app\controller\manager; | ||||
| 
 | ||||
| use app\controller\BaseController; | ||||
| use app\service\File as FileTool; | ||||
| use Exception; | ||||
| use think\exception\ValidateException; | ||||
| use think\response\Json; | ||||
| use think\response\Redirect; | ||||
| use think\response\View; | ||||
| 
 | ||||
| /** | ||||
|  * 控制器基础类 | ||||
|  */ | ||||
| class Base extends BaseController | ||||
| { | ||||
|     protected $data = []; | ||||
|     protected $auth = null; | ||||
| 
 | ||||
|     protected function initialize() | ||||
|     { | ||||
|         $this->middleware      = [ | ||||
|             'auth' => ['except' => array_merge($this->noNeedLogin, $this->noNeedRight)], | ||||
|             //            'jwt'  => ['except' => $this->noNeedRight],
 | ||||
|         ]; | ||||
|         $this->auth            = session('auth'); | ||||
|         $this->data['member']  = $this->auth; | ||||
|         $this->data['_token']  = $this->auth['token'] ?? ''; | ||||
|         $this->data['groupId'] = $this->auth['groupId'] ?? 0; | ||||
| 
 | ||||
|         $this->fileDomain(); | ||||
|     } | ||||
| 
 | ||||
|     //变量赋值到模板
 | ||||
|     protected function view(string $template = '') | ||||
|     { | ||||
|         return view($template)->assign($this->data); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * @param  string  $msg | ||||
|      * @param  string|null  $url | ||||
|      * @param  string  $data | ||||
|      * @param  int  $wait | ||||
|      * @return Redirect | ||||
|      */ | ||||
|     protected function error($msg = '', string $url = null, $data = '', int $wait = 3): Redirect | ||||
|     { | ||||
|         if (is_null($url)) { | ||||
|             $url = $this->request->isAjax() ? '' : 'javascript:history.back(-1);'; | ||||
|         } elseif ($url) { | ||||
|             $url = (strpos($url, '://') || 0 === strpos($url, '/')) ? $url : $this->app->route->buildUrl($url); | ||||
|         } | ||||
|         $result = [ | ||||
|             'code' => 0, | ||||
|             'msg'  => $msg, | ||||
|             'data' => $data, | ||||
|             'url'  => $url, | ||||
|             'wait' => $wait, | ||||
|         ]; | ||||
| 
 | ||||
|         return $this->redirect(url('/manager/error/jump', $result)); | ||||
|     } | ||||
| 
 | ||||
|     public function __call($name, $args) | ||||
|     { | ||||
|         return $this->view('/manager/error/jump'); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 验证器 | ||||
|      * | ||||
|      * @param  array  $data | ||||
|      * @param $validate | ||||
|      * @param  array  $message | ||||
|      * @param  bool  $batch | ||||
|      * @return Redirect | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     protected function validateError(array $data, $validate, array $message = [], bool $batch = false): Redirect | ||||
|     { | ||||
|         try { | ||||
|             parent::validate($data, $validate, $message, $batch); | ||||
|         } catch (ValidateException $e) { | ||||
|             $msg = $e->getMessage(); | ||||
|             if ($batch) { | ||||
|                 $msg = implode(',', $e->getError()); | ||||
|             } | ||||
| 
 | ||||
|             return $this->error($msg); | ||||
|         } catch (Exception $e) { | ||||
|             throw $e; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 文件域名前缀 | ||||
|      */ | ||||
|     public function fileDomain() | ||||
|     { | ||||
|         $this->data['fileDomain'] = FileTool::getFileDomain(); | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,364 @@ | |||
| <?php | ||||
| 
 | ||||
| namespace app\controller\manager; | ||||
| 
 | ||||
| use app\exception\RepositoryException; | ||||
| use app\model\BusinessFlow; | ||||
| use app\model\Coupon; | ||||
| use app\model\CouponMain; | ||||
| use app\model\Recharge; | ||||
| use app\model\Business as BusinessModel; | ||||
| use app\model\Member; | ||||
| use app\repository\BusinessRepository; | ||||
| use app\repository\CouponRepository; | ||||
| use app\repository\RechargeRepository; | ||||
| use app\service\wx\WechatPay; | ||||
| use Exception; | ||||
| 
 | ||||
| use think\facade\Db; | ||||
| use think\response\Json; | ||||
| use think\response\View; | ||||
| 
 | ||||
| /*商家*/ | ||||
| 
 | ||||
| class Business extends Base | ||||
| { | ||||
|     protected $noNeedLogin = ['queryManagerRecharge']; | ||||
|     /** | ||||
|      * 商家列表列表 | ||||
|      * | ||||
|      * @return Json|View | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public function index() | ||||
|     { | ||||
|         if ($this->request->isPost()) { | ||||
|             $model = new BusinessFlow(); | ||||
|             $repo = BusinessRepository::getInstance($model); | ||||
|             $keyword = $this->request->param('keyword/s', ''); | ||||
|             $page = $this->request->param('page/d', 1); | ||||
|             $size = $this->request->param('size/d', 30); | ||||
| 
 | ||||
|             $whereMap = [["business.state", "=", BusinessModel::state_on]]; | ||||
|             $orders = ['business.id' => 'desc']; | ||||
|             if (!empty($keyword)) { | ||||
|                 $whereMap[] = ['account.nick_name|business.business_name', 'like', "%$keyword%"]; | ||||
|             } | ||||
| 
 | ||||
|             $list = $repo->businessList($whereMap, $page, $size, $orders); | ||||
|             $list["list"]->each(function ($item) { | ||||
|                 //得到当前商家的所有优惠券
 | ||||
|                 $date = date("Y-m-d H:i:s"); | ||||
|                 //优惠券总数
 | ||||
|                 $item->coupon_total_count = CouponMain::where(["business_code" => $item->business->code])->sum("count"); | ||||
| 
 | ||||
|                 //进行中优惠券总数
 | ||||
|                 $item->coupon_doing_count = CouponMain::where(["business_code" => $item->business->code]) | ||||
|                     ->whereTime("start_time", "<", $date) | ||||
|                     ->whereTime("end_time", ">", $date) | ||||
|                     ->where("status", CouponMain::status_on) | ||||
|                     ->where("on_shelf", CouponMain::on_shelf_on) | ||||
|                     ->sum("count"); | ||||
| 
 | ||||
|                 //进行中优惠券总数
 | ||||
|                 $item->coupon_receive_count = CouponMain::where(["business_code" => $item->business->code])->sum("received_count"); | ||||
| 
 | ||||
|                 //过期未使用优惠券总数
 | ||||
|                 $item->coupon_be_overdue_count = Coupon::where(["business_code" => $item->business->code]) | ||||
|                     ->where("is_verificated", "=", Coupon::is_verificated_off) | ||||
|                     ->whereTime("end_time", "<", $date) | ||||
|                     ->count(); | ||||
| 
 | ||||
|                 //已使用优惠券总数
 | ||||
|                 $item->coupon_used_count = Coupon::where(["business_code" => $item->business->code]) | ||||
|                     ->where("is_verificated", "=", Coupon::is_verificated_on) | ||||
|                     ->count(); | ||||
| 
 | ||||
|                 //商家充值总额
 | ||||
|                 $item->recharge_total_money = Recharge::where(["business_code" => $item->business->code]) | ||||
|                     ->where("state", "=", Recharge::state_on) | ||||
|                     ->sum("money"); | ||||
|             }); | ||||
| 
 | ||||
|             return $this->json(0, 'success', $list); | ||||
|         } | ||||
| 
 | ||||
|         return $this->view(); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     /** | ||||
|      * 商家优惠券列表 | ||||
|      * | ||||
|      * @return Json|View | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public function businessCouponList() | ||||
|     { | ||||
|         $businessCode = input("business_code/s", ""); | ||||
|         if ($this->request->isPost()) { | ||||
| 
 | ||||
|             event('CouponStatusCheck'); | ||||
| 
 | ||||
|             $repo = BusinessRepository::getInstance(); | ||||
|             $keyword = $this->request->param('keyword/s', ''); | ||||
|             $page = $this->request->param('page/d', 1); | ||||
|             $size = $this->request->param('size/d', 30); | ||||
| 
 | ||||
|             $whereMap = ["business_code" => $businessCode]; | ||||
| 
 | ||||
|             if (!empty($keyword)) { | ||||
|                 $whereMap[] = ['name', 'like', "%$keyword%"]; | ||||
|             } | ||||
| 
 | ||||
|             $list = $repo->businessCouponList($whereMap, $page, $size, ["create_time" => "desc", "id" => "desc"]); | ||||
| 
 | ||||
|             return $this->json(0, 'success', $list); | ||||
|         } | ||||
|         $this->data["businessCode"] = $businessCode; | ||||
|         return $this->view(); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     /** | ||||
|      * 商家扣费记录列表 | ||||
|      * | ||||
|      * @return Json|View | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public function businessDeductionList() | ||||
|     { | ||||
|         $businessCode = input("business_code/s", ""); | ||||
|         if ($this->request->isPost()) { | ||||
|             $repo = BusinessRepository::getInstance(); | ||||
|             $keyword = $this->request->param('keyword/s', ''); | ||||
|             $page = $this->request->param('page/d', 1); | ||||
|             $size = $this->request->param('size/d', 30); | ||||
| 
 | ||||
|             $whereMap = ["business_code" => $businessCode]; | ||||
| 
 | ||||
|             if (!empty($keyword)) { | ||||
|                 $whereMap[] = ['reason|business_name', 'like', "%$keyword%"]; | ||||
|             } | ||||
| 
 | ||||
|             $list = $repo->businessDeductionList($whereMap, $page, $size, ["create_time" => "desc", "id" => "desc"]); | ||||
| 
 | ||||
|             return $this->json(0, 'success', $list); | ||||
|         } | ||||
|         $this->data["businessCode"] = $businessCode; | ||||
|         return $this->view(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 商家充值记录列表 | ||||
|      * | ||||
|      * @return Json|View | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public function businessRechargeList() | ||||
|     { | ||||
|         $businessCode = input("business_code/s", ""); | ||||
|         if ($this->request->isPost()) { | ||||
|             $repo = BusinessRepository::getInstance(); | ||||
|             $keyword = $this->request->param('keyword/s', ''); | ||||
|             $page = $this->request->param('page/d', 1); | ||||
|             $size = $this->request->param('size/d', 30); | ||||
| 
 | ||||
|             $whereMap = ["business_code" => $businessCode]; | ||||
| 
 | ||||
|             if (!empty($keyword)) { | ||||
|                 $whereMap[] = ['order_num', 'like', "%$keyword%"]; | ||||
|             } | ||||
| 
 | ||||
|             $list = $repo->businessRechargeList($whereMap, $page, $size, ["create_time" => "desc", "id" => "desc"]); | ||||
| 
 | ||||
|             return $this->json(0, 'success', $list); | ||||
|         } | ||||
|         $this->data["businessCode"] = $businessCode; | ||||
|         return $this->view(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 商家详情 | ||||
|      * | ||||
|      * @return Json|View | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public function businessDetail() | ||||
|     { | ||||
|         $businessCode = input("business_code/s", ""); | ||||
|         if ($this->request->isPost()) { | ||||
| 
 | ||||
|         } | ||||
|         $business = $repo = BusinessRepository::getInstance()->findOneByWhere(['code' => $businessCode]); | ||||
|         if (empty($business)) { | ||||
|             return $this->error("商家不存在"); | ||||
|         } | ||||
|         $this->data["item"] = $business; | ||||
|         return $this->view(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 商家认证列表 | ||||
|      * | ||||
|      * @return Json|View | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public function businessWaitList() | ||||
|     { | ||||
|         if ($this->request->isPost()) { | ||||
|             $model = new BusinessFlow(); | ||||
|             $repo = BusinessRepository::getInstance($model); | ||||
|             $keyword = $this->request->param('keyword/s', ''); | ||||
|             $page = $this->request->param('page/d', 1); | ||||
|             $size = $this->request->param('size/d', 30); | ||||
| 
 | ||||
|             $whereMap = [["business.state", "in", [BusinessModel::state_reviewing, BusinessModel::state_off]]]; | ||||
|             $orders = ['business.id' => 'desc']; | ||||
|             if (!empty($keyword)) { | ||||
|                 $whereMap[] = ['account.nick_name|business.business_name', 'like', "%$keyword%"]; | ||||
|             } | ||||
| 
 | ||||
|             $list = $repo->businessList($whereMap, $page, $size, $orders); | ||||
| 
 | ||||
|             return $this->json(0, 'success', $list); | ||||
|         } | ||||
| 
 | ||||
|         return $this->view(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 执行商家认证 | ||||
|      * | ||||
|      * @return Json|View | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public function businessWait() | ||||
|     { | ||||
|         if ($this->request->isPost()) { | ||||
|             $businessCode = input("business_code/s", ""); | ||||
|             $state = input("state/d", 0); | ||||
|             $business = BusinessRepository::getInstance()->findOneByWhere(["code" => $businessCode]); | ||||
|             if (empty($business)) { | ||||
|                 return $this->json(4001, "商家不存在"); | ||||
|             } | ||||
|             if ($business['state'] != BusinessModel::state_reviewing) { | ||||
|                 return $this->json(4001, "商家当前状态不可审核"); | ||||
|             } | ||||
|             if (!in_array($state, [BusinessModel::state_off, BusinessModel::state_on])) { | ||||
|                 return $this->json(4001, "错误的审核状态"); | ||||
|             } | ||||
|             Db::startTrans(); | ||||
|             try { | ||||
|                 $business->save(["state"=>$state]); | ||||
|                 Db::commit(); | ||||
|                 return  $this->json(); | ||||
|             }catch (RepositoryException $e){ | ||||
|                 Db::rollback(); | ||||
|                 return $this->json("5001","审核失败"); | ||||
|             }catch (\think\Exception $e){ | ||||
|                 Db::rollback(); | ||||
|                 return $this->json("5002","审核失败"); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 给商家指派代理商 | ||||
|      * | ||||
|      * @return Json|View | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public function assign() | ||||
|     { | ||||
|         $businessCode = input("business_code/s", ""); | ||||
|         $business = BusinessRepository::getInstance()->findOneByWhere(["code" => $businessCode]); | ||||
| 
 | ||||
|         if ($this->request->isPost()) { | ||||
|             $anent_code = input("agency_code/s", ""); | ||||
|             if(empty($business)){ | ||||
|                 return  $this->json(4001,"商家不存在"); | ||||
|             } | ||||
|             Db::startTrans(); | ||||
|             try { | ||||
|                 $business->save(["agency_code"=>$anent_code]); | ||||
|                 Db::commit(); | ||||
|                 return  $this->json(); | ||||
|             }catch (RepositoryException $e){ | ||||
|                 Db::rollback(); | ||||
|                 return $this->json("5001","指派失败"); | ||||
|             }catch (\think\Exception $e){ | ||||
|                 Db::rollback(); | ||||
|                 return $this->json("5002","指派失败"); | ||||
|             } | ||||
|         } | ||||
|         if(empty($business)){ | ||||
|             return  $this->error("商家不存在"); | ||||
|         } | ||||
|         $this->data["agent"] = Member::getAgentAll(); | ||||
|         $this->data["businessCode"] = $businessCode; | ||||
|         $this->data["business"] = $business; | ||||
|         return $this->view(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 代为充值 | ||||
|      * | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public function rechargeBehalf() | ||||
|     { | ||||
|         $businessCode = input("business_code/s", ""); | ||||
|         $business = BusinessRepository::getInstance()->findOneByWhere(["code" => $businessCode]); | ||||
| 
 | ||||
|         if ($this->request->isPost()) { | ||||
|             $money = input("money/f", 0,"abs"); | ||||
|             if($money<=0){ | ||||
|                 return  $this->json(4001,"金额错误"); | ||||
|             } | ||||
|             $money = floor($money * 100) / 100; | ||||
|             if(empty($business)){ | ||||
|                 return  $this->json(4001,"商家不存在"); | ||||
|             } | ||||
|             Db::startTrans(); | ||||
|             try { | ||||
|                 //创建充值订单
 | ||||
|                 if (!$order = RechargeRepository::getInstance()->createOrder($businessCode,$money)) { | ||||
|                     throw new RepositoryException('订单创建失败,请稍后重试'); | ||||
|                 } | ||||
|                 //生成支付
 | ||||
|                 $res = WechatPay::getInstance()->order->unify([ | ||||
|                     'body'         => '商家充值', | ||||
|                     'out_trade_no' => $order->order_num, | ||||
|                     'total_fee'    => $money * 100, | ||||
|                     'trade_type'   => 'NATIVE', | ||||
|                     'product_id'   => $order->id, | ||||
|                     'notify_url'   => $this->request->domain()."/api/recharge/notify.html", | ||||
|                 ]); | ||||
| 
 | ||||
|                 if(!isset($res['code_url'])){ | ||||
|                     throw new RepositoryException('订单创建失败,请稍后重试'); | ||||
|                 } | ||||
| 
 | ||||
|                 Db::commit(); | ||||
|                 return $this->json(0,"success",["order_num"=>$order->order_num,"code_url"=>$res['code_url']]); | ||||
|             }catch (RepositoryException $e){ | ||||
|                 Db::rollback(); | ||||
|                 return $this->json("5001",$e->getMessage()); | ||||
|             }catch (Exception $e){ | ||||
|                 Db::rollback(); | ||||
|                 return $this->json("5001",$e->getMessage()); | ||||
|             } | ||||
| 
 | ||||
|         } | ||||
|         if(empty($business)){ | ||||
|             return  $this->error("商家不存在"); | ||||
|         } | ||||
| 
 | ||||
|         $this->data["businessCode"] = $businessCode; | ||||
| 
 | ||||
|         return $this->view(); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
| } | ||||
|  | @ -0,0 +1,215 @@ | |||
| <?php | ||||
| 
 | ||||
| namespace app\controller\manager; | ||||
| 
 | ||||
| use app\repository\CmsRepository; | ||||
| use app\model\Log; | ||||
| use app\model\Category as CategoryModel; | ||||
| 
 | ||||
| use Exception; | ||||
| use think\facade\Db; | ||||
| use think\db\exception\DataNotFoundException; | ||||
| use think\db\exception\DbException; | ||||
| use think\db\exception\ModelNotFoundException; | ||||
| use think\exception\ValidateException; | ||||
| use think\response\Json; | ||||
| use think\response\View; | ||||
| 
 | ||||
| /** | ||||
|  * 分类管理 | ||||
|  * | ||||
|  * Class Category | ||||
|  * @package app\controller\manager | ||||
|  */ | ||||
| class Category extends Base | ||||
| { | ||||
|     /** | ||||
|      * 编辑 | ||||
|      * | ||||
|      * @return Json|View | ||||
|      * @throws DataNotFoundException | ||||
|      * @throws DbException | ||||
|      * @throws ModelNotFoundException | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public function edit() | ||||
|     { | ||||
|         $id = input('id/d', 0); | ||||
| 
 | ||||
|         if (!$info = CategoryModel::findById($id)) { | ||||
|             return $this->json(4001, '记录不存在'); | ||||
|         } | ||||
| 
 | ||||
|         if ($this->request->isPost()) { | ||||
|             $item     = input('post.'); | ||||
|             $validate = $this->validateByApi($item, [ | ||||
|                 'pid|父级分类' => 'require|number', | ||||
|                 'name|标题'  => 'require|max:100|unique:disease,name,'.$id, | ||||
|             ]); | ||||
| 
 | ||||
|             if ($validate !== true) { | ||||
|                 return $validate; | ||||
|             } | ||||
| 
 | ||||
|             Db::startTrans(); | ||||
|             try { | ||||
|                 $oldPath      = $info['path'] ?? ''; | ||||
|                 $item['path'] = CategoryModel::getPath($item['pid']); | ||||
|                 $info->save($item); | ||||
| 
 | ||||
|                 //刷新所有路径
 | ||||
|                 $oldPath = $oldPath.','.$id; | ||||
|                 $newPath = $item['path'].','.$id; | ||||
|                 if ($oldPath != $newPath) { | ||||
|                     CategoryModel::refreshPath(); | ||||
|                 } | ||||
|                 Db::commit(); | ||||
|                 return $this->json(); | ||||
|             } catch (ValidateException $e) { | ||||
|                 Db::rollback(); | ||||
|                 return $this->json(4001, $e->getError()); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         $disabled                = CategoryModel::getAllChildrenIds($id); | ||||
|         $disabled[]              = $id; | ||||
|         $this->data['jsonList']  = $this->categoryJson([$info['pid']], $disabled); | ||||
|         $this->data['item']      = $info; | ||||
| 
 | ||||
|         return $this->view(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 单个字段编辑 | ||||
|      * | ||||
|      * @return Json | ||||
|      * @throws DataNotFoundException | ||||
|      * @throws DbException | ||||
|      * @throws ModelNotFoundException | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public function modify(): Json | ||||
|     { | ||||
|         if ($this->request->isPost()) { | ||||
|             $item     = input('post.'); | ||||
|             $validate = $this->validateByApi($item, [ | ||||
|                 'id|ID'     => 'require|number', | ||||
|                 'field|字段名' => 'require', | ||||
|                 'value|值'   => 'require', | ||||
|             ]); | ||||
| 
 | ||||
|             if ($validate !== true) { | ||||
|                 return $validate; | ||||
|             } | ||||
| 
 | ||||
|             if (!$info = CategoryModel::findById($item['id'])) { | ||||
|                 return $this->json(4001, '记录不存在'); | ||||
|             } | ||||
| 
 | ||||
|             $update = [$item['field'] => $item['value']]; | ||||
| 
 | ||||
|             try { | ||||
|                 $info->save($update); | ||||
|                 return $this->json(); | ||||
|             } catch (ValidateException $e) { | ||||
|                 return $this->json(4001, $e->getError()); | ||||
|             } | ||||
|         } | ||||
|         return $this->json(4000, '非法请求'); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 添加 | ||||
|      * | ||||
|      * @return Json|View | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public function add() | ||||
|     { | ||||
|         if ($this->request->isPost()) { | ||||
|             $item     = input('post.'); | ||||
|             $validate = $this->validateByApi($item, [ | ||||
|                 'pid|父级分类'  => 'require|number', | ||||
|                 'name|标题' => 'require|max:100', | ||||
|             ]); | ||||
| 
 | ||||
|             if ($validate !== true) { | ||||
|                 return $validate; | ||||
|             } | ||||
|             try { | ||||
|                 CategoryModel::create($item); | ||||
|                 return $this->json(); | ||||
|             } catch (ValidateException $e) { | ||||
|                 return $this->json(4001, $e->getError()); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         $this->data['jsonList']  = $this->categoryJson(); | ||||
| 
 | ||||
|         return $this->view(); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     /** | ||||
|      * 删除 | ||||
|      * @return Json | ||||
|      */ | ||||
|     public function del() | ||||
|     { | ||||
|         if (!$this->request->isPost()) { | ||||
|             return $this->json(4000, '非法请求'); | ||||
|         } | ||||
| 
 | ||||
|         $ids = $this->request->param('ids/a', []); | ||||
|         if(!empty(CategoryModel::findOne([["pid","in",$ids]]))){ | ||||
|             return $this->json(5001,"该栏目还有下级 不能删除"); | ||||
|         } | ||||
|         CategoryModel::destroy($ids); | ||||
|         return $this->json(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 列表 | ||||
|      * | ||||
|      * @return Json|View | ||||
|      * @throws DataNotFoundException | ||||
|      * @throws DbException | ||||
|      * @throws ModelNotFoundException | ||||
|      */ | ||||
|     public function index() | ||||
|     { | ||||
|         if ($this->request->isPost()) { | ||||
|             $menus = CategoryModel::getList(); | ||||
|             $res   = [ | ||||
|                 'code'  => 0, | ||||
|                 'msg'   => 'success', | ||||
|                 'count' => $menus->count(), | ||||
|                 'data'  => $menus->toArray(), | ||||
|             ]; | ||||
|             return json($res); | ||||
|         } | ||||
|         return $this->view(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * @param  array  $selected | ||||
|      * @param  array  $disabled | ||||
|      * @return false|string | ||||
|      * @throws DataNotFoundException | ||||
|      * @throws DbException | ||||
|      * @throws ModelNotFoundException | ||||
|      */ | ||||
|     private function categoryJson(array $selected = [], array $disabled = []) | ||||
|     { | ||||
|         $categoryList[] = ['name' => '顶级分类', 'id' => 0, 'disabled' => false, 'selected' => in_array(0, $selected)]; | ||||
|         $list           = CategoryModel::getListByPid(); | ||||
|         $list           = $list->toArray(); | ||||
|         foreach ($list as $k => $m) { | ||||
|             $list[$k]['selected'] = in_array($m['id'], $selected); | ||||
|             $list[$k]['disabled'] = in_array($m['id'], $disabled); | ||||
|         } | ||||
|         $list         = CmsRepository::getInstance()->buildMenuChild(0, $list); | ||||
|         $categoryList = array_merge($categoryList, CmsRepository::getInstance()->handleSelectedList($list)); | ||||
|         return json_encode($categoryList, JSON_UNESCAPED_UNICODE); | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,185 @@ | |||
| <?php | ||||
| 
 | ||||
| 
 | ||||
| namespace app\controller\manager; | ||||
| 
 | ||||
| use app\model\CommentRule; | ||||
| use Exception; | ||||
| use think\exception\ValidateException; | ||||
| use think\facade\Config as CConfig; | ||||
| use think\response\Json; | ||||
| 
 | ||||
| /** | ||||
|  * 额外配置 | ||||
|  * Class Config | ||||
|  * @package app\controller\manager | ||||
|  */ | ||||
| class Config extends Base | ||||
| { | ||||
|     private string $extraPath = ''; | ||||
| 
 | ||||
|     protected function initialize() | ||||
|     { | ||||
|         parent::initialize(); | ||||
| 
 | ||||
|         $this->extraPath = config_path() . 'extra/'; | ||||
|         if (!is_dir($this->extraPath)) { | ||||
|             if (is_writable(config_path())) { | ||||
|                 mkdir($this->extraPath, 0777, true); | ||||
|             } else { | ||||
|                 halt('请联系系统管理人员配置文件夹读写权限!请添加'.$this->extraPath.'文件夹的读写权限'); | ||||
|             } | ||||
|         } elseif (!is_writable($this->extraPath)) { | ||||
|             halt('请联系系统管理人员配置文件夹读写权限!请添加'.$this->extraPath.'文件夹的读写权限'); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     public function other() | ||||
|     { | ||||
|         if ($this->request->isPost()) { | ||||
|             $data = input("post."); | ||||
|             unset($data['_token']); | ||||
|             $php  = var_export($data, true); | ||||
|             file_put_contents($this->extraPath . 'other.php', '<?php' . PHP_EOL . 'return ' . $php . ';'); | ||||
|             return $this->json(); | ||||
|         } else { | ||||
|             CConfig::load('extra/other', 'other'); | ||||
|             $this->data['item'] = config('other'); | ||||
|             return $this->view(); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     public function wechat() | ||||
|     { | ||||
|         if ($this->request->isPost()) { | ||||
| 
 | ||||
|             $data = input("post."); | ||||
| 
 | ||||
|             unset($data['_token']); | ||||
|             $php  = var_export($data, true); | ||||
|             file_put_contents($this->extraPath . 'wechat.php', '<?php' . PHP_EOL . 'return ' . $php . ';'); | ||||
|             return $this->json(); | ||||
|         } else { | ||||
|             CConfig::load('extra/wechat', 'wechat'); | ||||
|             $this->data['item'] = config('wechat'); | ||||
|             return $this->view(); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     public function alipay() | ||||
|     { | ||||
|         if ($this->request->isPost()) { | ||||
|             $data = input("post."); | ||||
|             unset($data['_token']); | ||||
|             $php  = var_export($data, true); | ||||
|             file_put_contents($this->extraPath . 'alipay.php', '<?php' . PHP_EOL . 'return ' . $php . ';'); | ||||
|             return $this->json(); | ||||
|         } else { | ||||
|             CConfig::load('extra/alipay', 'alipay'); | ||||
|             $this->data['item'] = config('alipay'); | ||||
|             return $this->view(); | ||||
|         } | ||||
|     } | ||||
|     public function commentRule() | ||||
|     { | ||||
|         if ($this->request->isPost()) { | ||||
|             $page = input('param.page/d', 1); | ||||
|             $size = input('param.size/d', 10); | ||||
|             $items = CommentRule::findList([],[], $page, $size); | ||||
|             return $this->json(0, 'ok', $items); | ||||
|         } | ||||
|         return $this->view(); | ||||
|     } | ||||
| 
 | ||||
|     public function delCommentRule() | ||||
|     { | ||||
|         if ($this->request->isPost()) { | ||||
|             $ids = input('post.ids/a', []); | ||||
|             if (empty($ids)) { | ||||
|                 $ids[] = input('post.id/d'); | ||||
|             } | ||||
|             CommentRule::deleteByIds($ids); | ||||
|             return $this->json(); | ||||
|         } | ||||
|         return $this->json(4001, '非法请求!'); | ||||
|     } | ||||
|     public function addCommentRule() | ||||
|     { | ||||
|         if ($this->request->isPost()) { | ||||
|             $item = input('post.item'); | ||||
| 
 | ||||
|             $validate = $this->validateByApi($item, [ | ||||
|                 'rule|规则'     => 'require', | ||||
|                 'state|状态'      => 'require', | ||||
|             ]); | ||||
| 
 | ||||
|             if ($validate !== true) { | ||||
|                 return $validate; | ||||
|             } | ||||
| 
 | ||||
|             try { | ||||
|                 $item['create_time'] =  date('Y-m-d H:i:s'); | ||||
|                 CommentRule::create($item); | ||||
|                 return $this->json(); | ||||
|             } catch (ValidateException $e) { | ||||
|                 return $this->json(4001, $e->getError()); | ||||
|             } | ||||
|         } | ||||
|         return $this->view(); | ||||
|     } | ||||
|     /** | ||||
|      * 单个字段编辑 | ||||
|      * | ||||
|      * @return Json | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public function modifyCommentRule(): Json | ||||
|     { | ||||
|         if ($this->request->isPost()) { | ||||
|             $item     = input('post.'); | ||||
|             $validate = $this->validateByApi($item, [ | ||||
|                 'field' => 'require', | ||||
|                 'value' => 'require', | ||||
|             ]); | ||||
| 
 | ||||
|             if ($validate !== true) { | ||||
|                 return $validate; | ||||
|             } | ||||
| 
 | ||||
|             if (!$info = CommentRule::findById($item['id'])) { | ||||
|                 return $this->json(4001, '记录不存在'); | ||||
|             } | ||||
| 
 | ||||
|             $update = [$item['field'] => $item['value']]; | ||||
| 
 | ||||
|             try { | ||||
|                 $info->save($update); | ||||
|                 return $this->json(); | ||||
|             } catch (ValidateException $e) { | ||||
|                 return $this->json(4001, $e->getError()); | ||||
|             } | ||||
|         } | ||||
|         return $this->json(4000, '非法请求'); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|     public function __call($name, $args) | ||||
|     { | ||||
|         if ($this->request->isPost()) { | ||||
|             try { | ||||
|                 $data = input("post."); | ||||
|                 $php = var_export($data, true); | ||||
|                 file_put_contents(config_path().'extra/'.$name.'.php', '<?php'.PHP_EOL.'return '.$php.';'); | ||||
|                 return $this->json(); | ||||
|             } catch (Exception $e) { | ||||
|                 return $this->json(4001, $e->getMessage()); | ||||
|             } | ||||
|         } else { | ||||
|             CConfig::load('extra/'.$name, $name); | ||||
|             $this->data['item']   = config($name); | ||||
|             $this->data['action'] = $name; | ||||
|             return $this->view('manager/config/'.$name); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,11 @@ | |||
| <?php | ||||
| namespace app\controller\manager; | ||||
| 
 | ||||
| class Error | ||||
| { | ||||
|     public function jump() | ||||
|     { | ||||
|         $param = request()->param(); | ||||
|         return view()->assign($param); | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,143 @@ | |||
| <?php | ||||
| namespace app\controller\manager; | ||||
| 
 | ||||
| use app\model\{File as MFile, Archives, Block, Category, Link, Slide, Log}; | ||||
| use app\service\Tool; | ||||
| 
 | ||||
| class File extends Base | ||||
| { | ||||
|     protected $noNeedLogin = ['delPath', 'del', 'unuse', 'getAllFilesInUse', 'list', 'index']; | ||||
|     //删除磁盘上的文件
 | ||||
|     public function delPath() | ||||
|     { | ||||
|         if ($this->request->isPost()) { | ||||
|             $paths = input('post.paths/a'); | ||||
|             if(!empty($paths)){ | ||||
|                 foreach($paths as $path){ | ||||
|                     Tool::delFile($path); | ||||
|                 } | ||||
|                 Log::write('file', 'delPath', '批量删除了磁盘文件,涉及到的文件路径为:' . implode(',', $paths)); | ||||
|                 return $this->json(); | ||||
|             } | ||||
|             return $this->json(2, '待删除文件列表为空'); | ||||
|         } | ||||
|         return $this->json(1, '非法请求!'); | ||||
|     } | ||||
|     //删除文件记录
 | ||||
|     public function del() | ||||
|     { | ||||
|         if ($this->request->isPost()) { | ||||
|             $ids = input('post.ids/a'); | ||||
|             if(empty($ids) || !is_array($ids)) { | ||||
|                 return $this->json(2, '参数错误,请核对之后再操作!'); | ||||
|             } | ||||
|             $items = MFile::getListByIds($ids); | ||||
|             if(!empty($items)){ | ||||
|                 $delIds = []; | ||||
|                 foreach($items as $item){ | ||||
|                     $delIds[] = $item['id']; | ||||
|                     if($item['type'] == MFile::IMG){ | ||||
|                         Tool::delFile($item['src'], 1); | ||||
|                     }else{ | ||||
|                         Tool::delFile($item['src']); | ||||
|                     } | ||||
|                 } | ||||
|                 MFile::destroy($delIds); | ||||
|                 Log::write('file', 'del', '批量删除了文件,涉及到的文件ID为:' . implode(',', $delIds)); | ||||
|                 return $this->json(); | ||||
|             }else{ | ||||
|                 return $this->json(3, '待删除文件列表为空'); | ||||
|             } | ||||
|         } | ||||
|         return $this->json(1, '非法请求!'); | ||||
|     } | ||||
|     /** | ||||
|      * 未使用文件列表, | ||||
|      * 1. 遍历数据库中使用的图片视频及文件路径 | ||||
|      * 2. 遍历上传目录中的文件 | ||||
|      * 3. 数据对比,找出存在目录中的文件&不在数据库中的文件 | ||||
|      * 4. 页面上显示查找出来的文件 | ||||
|     */ | ||||
|     public function unuse() | ||||
|     { | ||||
|         $filesInUse = $this->getAllFilesInUse();    //数据库中在使用的文件
 | ||||
|         $rootPath = app()->getRootPath(); | ||||
|         $uploadPath = $rootPath . 'storage'; | ||||
|         $uploadedFiles = getAllFilesByPath($uploadPath, $rootPath); //磁盘上上传的文件
 | ||||
|         $files = MFile::getAll(); | ||||
|         $dbUploadedFiles = [];  //数据库中上传的文件
 | ||||
|         foreach($files as $file){ | ||||
|             $src = trim($file['src']); | ||||
|             if(!empty($src)){ | ||||
|                 $key = getKeyByPath($src); | ||||
|                 $dbUploadedFiles[$key] = $file; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         $uploadedNotInUseFiles = array_diff_key($uploadedFiles, $filesInUse);   //磁盘上上传未使用的文件
 | ||||
|         $dbUploadedNotInUseFiles = array_diff_key($dbUploadedFiles, $filesInUse);    //数据库中上传未使用的文件
 | ||||
|         $bothNotInUseFiles = array_intersect_key($uploadedNotInUseFiles, $dbUploadedNotInUseFiles);  //磁盘和数据库中,两边都未使用
 | ||||
|         $this->data['uploadedNotInUseFiles'] = $uploadedNotInUseFiles; | ||||
|         $this->data['dbUploadedNotInUseFiles'] = $dbUploadedNotInUseFiles; | ||||
|         $this->data['bothNotInUseFilesKey'] = array_keys($bothNotInUseFiles); | ||||
|         return $this->view(); | ||||
|     } | ||||
| 
 | ||||
|     //获取所有在使用的文件
 | ||||
|     private function getAllFilesInUse() | ||||
|     { | ||||
|         $files = []; | ||||
|         $blockFiles = Block::getFilesInUse(); | ||||
|         if(!empty($blockFiles)){ | ||||
|             $files = array_merge($files, $blockFiles); | ||||
|         } | ||||
|         $slideFiles = Slide::getFilesInUse(); | ||||
|         if(!empty($slideFiles)){ | ||||
|             $files = array_merge($files, $slideFiles); | ||||
|         } | ||||
|         $linkFiles = Link::getFilesInUse(); | ||||
|         if(!empty($linkFiles)){ | ||||
|             $files = array_merge($files, $linkFiles); | ||||
|         } | ||||
|         $categoryFiles = Category::getFilesInUse(); | ||||
|         if(!empty($categoryFiles)){ | ||||
|             $files = array_merge($files, $categoryFiles); | ||||
|         } | ||||
|         $articleFiles = Archives::getFilesInUse(); | ||||
|         if(!empty($articleFiles)){ | ||||
|             $files = array_merge($files, $articleFiles); | ||||
|         } | ||||
|         return $files; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     //ajax获取文件列表
 | ||||
|     public function list() | ||||
|     { | ||||
|         if($this->request->isAjax()){ | ||||
|             $page = input('param.page/d', 1); | ||||
|             $size = input('param.size/d', 20); | ||||
|             if(!is_integer($page) || $page < 1){ | ||||
|                 $page = 1; | ||||
|             } | ||||
|             if (!is_integer($size) || $size < 1) { | ||||
|                 $size = 20; | ||||
|             } | ||||
|             $type = input('param.type', ''); | ||||
|             if(!in_array($type, array_keys(MFile::getTypes()))){ | ||||
|                 $type = ''; | ||||
|             } | ||||
|             $items = MFile::getList($type, $page, $size); | ||||
|             return $this->json(0, 'ok', $items); | ||||
|         } | ||||
|         return $this->json(1, '无此操作'); | ||||
|     } | ||||
|     //列表
 | ||||
|     public function index() | ||||
|     { | ||||
|         $items = MFile::getListPage(); | ||||
|         $this->data['items'] = $items; | ||||
|         $this->data['types'] = MFile::getTypes(); | ||||
|         return $this->view(); | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,141 @@ | |||
| <?php | ||||
| namespace app\controller\manager; | ||||
| 
 | ||||
| use app\model\{AuthGroup, AuthRule, Log}; | ||||
| use app\validate\AuthGroup as VAuthGroup; | ||||
| use think\exception\ValidateException; | ||||
| 
 | ||||
| /** | ||||
|  * 角色管理控制器 | ||||
|  */ | ||||
| class Group extends Base | ||||
| { | ||||
|     /** | ||||
|      * 角色、分组删除 | ||||
|      */ | ||||
|     public function del() | ||||
|     { | ||||
|         if ($this->request->isPost()) { | ||||
|             $id = input('post.id/d'); | ||||
|             if (is_numeric($id) === true && $id > 0) { | ||||
|                 $item = AuthGroup::getById($id); | ||||
|                 if(!empty($item)){ | ||||
|                     AuthGroup::destroy($id); | ||||
|                     Log::write('group', 'del', '删除角色,ID:' . $id . ',名称:' . $item['title']); | ||||
|                     return $this->json(); | ||||
|                 } | ||||
|             } | ||||
|             return $this->json(2, '传入参数错误,请核对之后再操作!'); | ||||
|         } | ||||
|         return $this->json(1, '非法请求!'); | ||||
|     } | ||||
|     /** | ||||
|      * 角色、分组权限分配 | ||||
|      */ | ||||
|     public function rule() | ||||
|     { | ||||
|         if($this->request->isPost()){ | ||||
|             $rules = input('post.rules/a'); | ||||
|             $groupId = input('post.group_id/d'); | ||||
|             if (is_array($rules) && (is_numeric($groupId) === true && $groupId > 0)) { | ||||
|                 $group = AuthGroup::getById($groupId); | ||||
|                 if(empty($group)){ | ||||
|                     return $this->json(2, '无此角色信息,请核对之后再操作!'); | ||||
|                 } | ||||
|                 AuthGroup::updateRules($groupId, $rules); | ||||
|                 // 重置该角色对应的权限缓存
 | ||||
|                 AuthGroup::resetGroupRulesCache($groupId); | ||||
|                 Log::write('group', 'rule', '角色分配权限,ID:' . $groupId . ',名称:' . $group['title']); | ||||
|                 return $this->json(); | ||||
|             }else{ | ||||
|                 return $this->json(3, '传入参数错误,请核对之后再操作!'); | ||||
|             } | ||||
|         } else { | ||||
|             $groupId = input('param.group_id/d'); | ||||
|             $group = AuthGroup::getById($groupId); | ||||
|             if(!empty($group)){ | ||||
|                 $rules = AuthRule::getListTree(); | ||||
|                 $this->data['group_id'] = $groupId; | ||||
|                 $this->data['group'] = $group; | ||||
|                 $this->data['rules'] = $rules; | ||||
|                 return $this->view(); | ||||
|             }else{ | ||||
|                 return $this->json(1, '无此角色信息,请核对之后再操作!'); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     /** | ||||
|      * 角色、分组添加 | ||||
|      * @param int $status 1:正常;0:禁止 | ||||
|      */ | ||||
|     public function add() | ||||
|     { | ||||
|         if($this->request->isPost()){ | ||||
|             $title = trim(input('post.title')); | ||||
|             $status = input('post.status/d'); | ||||
|             if (!empty($title) && (is_numeric($status) === true) && ($status == 1 || $status == 0)) { | ||||
|                 $item = [ | ||||
|                     'title' => $title, | ||||
|                     'status' => $status | ||||
|                 ]; | ||||
|                 try { | ||||
|                     validate(VAuthGroup::class)->check($item); | ||||
|                     $group = AuthGroup::create($item); | ||||
|                     Log::write('group', 'add', "角色新增,ID:{$group->id} ,标题:{$group->title}"); | ||||
|                     return $this->json(); | ||||
|                 } catch (ValidateException $e) { | ||||
|                     return $this->json(2, $e->getError()); | ||||
|                 } | ||||
|             } | ||||
|             return $this->json(1, '传入参数错误,请核对之后再操作!'); | ||||
|         }else{ | ||||
|             return $this->view(); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 角色、分组编辑 | ||||
|      */ | ||||
|     public function edit() | ||||
|     { | ||||
|         if($this->request->isPost()){ | ||||
|             $title = trim(input('post.title')); | ||||
|             $status = input('post.status/d'); | ||||
|             $id  = input('post.id/d'); | ||||
|             if (!empty($title) && ($status == 1 || $status == 0) && (is_numeric($id) === true && $id > 0)) { | ||||
|                 $item = [ | ||||
|                     'title' => $title, | ||||
|                     'status' => $status | ||||
|                 ]; | ||||
|                 try { | ||||
|                     validate(VAuthGroup::class)->check($item); | ||||
|                     AuthGroup::updateById($id, $item); | ||||
|                     Log::write('group', 'edit', "角色编辑,ID:{$id} ,标题:{$item['title']}"); | ||||
|                     return $this->json(); | ||||
|                 } catch (ValidateException $e) { | ||||
|                     return $this->json(2, $e->getError()); | ||||
|                 } | ||||
|             } | ||||
|             return $this->json(1, '传入参数错误,请核对之后再操作!'); | ||||
|         }else{ | ||||
|             $id  = input('param.id/d'); | ||||
|             if (is_numeric($id) === true && $id > 0) { | ||||
|                 $item = AuthGroup::getById($id); | ||||
|                 $this->data['item'] = $item; | ||||
|                 return $this->view(); | ||||
|             } | ||||
|             return $this->json(1, '传入参数错误,请核对之后再操作!'); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 所有角色分组信息 | ||||
|      * @return void | ||||
|      */ | ||||
|     public function index() | ||||
|     { | ||||
|         $list = AuthGroup::select()->toArray(); | ||||
|         $this->data['list'] = $list; | ||||
|         return $this->view(); | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,86 @@ | |||
| <?php | ||||
| 
 | ||||
| namespace app\controller\manager; | ||||
| 
 | ||||
| use app\model\AccountRecord; | ||||
| use app\model\Overview; | ||||
| use app\model\AccountRole; | ||||
| use app\model\Appointment; | ||||
| use app\model\Account; | ||||
| use app\repository\CmsRepository; | ||||
| use Exception; | ||||
| use think\db\exception\DataNotFoundException; | ||||
| use think\db\exception\DbException; | ||||
| use think\db\exception\ModelNotFoundException; | ||||
| use think\response\Json; | ||||
| use think\response\View; | ||||
| use app\model\Member; | ||||
| use app\model\Menu; | ||||
| 
 | ||||
| class Index extends Base | ||||
| { | ||||
|     //TODO 权限未完善
 | ||||
|     protected $noNeedLogin = ['index', 'init']; | ||||
| 
 | ||||
|     /** | ||||
|      * 后台初始页面 随后进入dashboard页面 | ||||
|      * | ||||
|      * @return View | ||||
|      * @throws DataNotFoundException | ||||
|      * @throws DbException | ||||
|      * @throws ModelNotFoundException | ||||
|      */ | ||||
|     public function index(): View | ||||
|     { | ||||
|         $auth               = session('auth'); | ||||
|         $this->data['user'] = Member::findById($auth['user_id'] ?? 0, ['id', 'username', 'nickname', 'mobile']); | ||||
|         return $this->view(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 控制台 | ||||
|      * | ||||
|      * @return Json|View | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public function dashboard() | ||||
|     { | ||||
|         return $this->view(); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     /** | ||||
|      * 菜单初始化 | ||||
|      * | ||||
|      * @return Json | ||||
|      */ | ||||
|     public function init(): Json | ||||
|     { | ||||
|         $res             = []; | ||||
|         $res['homeInfo'] = ['title' => '控制台', 'href' => "manager/index/dashboard"]; | ||||
|         $res['logoInfo'] = ['title' => '恒美植发', 'href' => "", 'image' => '/static/manager/image/logo.png']; | ||||
| 
 | ||||
|         $menus = CmsRepository::getInstance()->getMenuList(Menu::TYPE_MENU, Menu::SHOW_YES)->toArray(); | ||||
|         foreach ($menus as $k => $m) { | ||||
|             $menus[$k]['icon'] = !empty($m['icon']) ? 'fa '.$m['icon'] : ''; | ||||
|             $menus[$k]['href'] = ltrim($m['href'], '/'); | ||||
|         } | ||||
|         $menus           = CmsRepository::getInstance()->buildMenuChild(0, $menus, 'child'); | ||||
|         $res['menuInfo'] = $menus; | ||||
| 
 | ||||
|         return json($res); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 缓存清理 | ||||
|      * | ||||
|      * @return Json | ||||
|      */ | ||||
|     public function clear(): Json | ||||
|     { | ||||
|         $res = ['code' => 1, 'msg' => '服务端清理缓存成功']; | ||||
|         sleep(2); | ||||
| 
 | ||||
|         return json($res); | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,76 @@ | |||
| <?php | ||||
| 
 | ||||
| namespace app\controller\manager; | ||||
| 
 | ||||
| use app\service\Jwt; | ||||
| use Exception; | ||||
| use app\model\{Member, AuthRule, LoginLog}; | ||||
| use app\controller\BaseController; | ||||
| use think\response\Json; | ||||
| use think\response\View; | ||||
| 
 | ||||
| class Login extends BaseController | ||||
| { | ||||
|     protected $noNeedLogin = ['index']; | ||||
| 
 | ||||
|     /** | ||||
|      * @return View|Json | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public function index() | ||||
|     { | ||||
|         if (request()->isPost()) { | ||||
|             $param    = input('post.data'); | ||||
|             $username = trim($param['username']); | ||||
|             $password = trim($param['password']); | ||||
|             $captcha  = trim($param['captcha'] ?? ''); | ||||
|             if (!captcha_check($captcha)) { | ||||
|                 return $this->json(4001, '验证码错误'.$captcha); | ||||
|             } | ||||
| 
 | ||||
|             if (empty($username) || empty($password)) { | ||||
|                 return $this->json(4001, '用户名和密码不能为空'); | ||||
|             } | ||||
|             $member = Member::getByUserName($username); | ||||
|             if (empty($member)) { | ||||
|                 return $this->json(4002, '用户名或密码错误'); | ||||
|             } | ||||
|             if ($member['password'] != md5($password.$username)) { | ||||
|                 return $this->json(4003, '用户名或密码错误'); | ||||
|             } | ||||
|             if ($member['status'] != Member::STATUS_NORMAL) { | ||||
|                 return $this->json(4004, '账号已被禁用'); | ||||
|             } | ||||
| 
 | ||||
|             $userInfo = [ | ||||
|                 'user_id'    => $member['id'], | ||||
|                 'username'   => $member['username'], | ||||
|                 'nickname'   => $member['nickname'], | ||||
|                 'account_id' => $member['account_id'],//绑定的前台用户ID
 | ||||
|             ]; | ||||
| 
 | ||||
|             $jwtToken = Jwt::generate($userInfo, env('app.expire', 7200)); | ||||
| 
 | ||||
|             $userInfo['token'] = $jwtToken;//jwt生成token
 | ||||
| 
 | ||||
|             //记录最后登陆时间
 | ||||
|             $ip   = request()->ip(); | ||||
|             $time = time(); | ||||
|             Member::updateById($member['id'], [ | ||||
|                 'login_time' => $time, | ||||
|                 'login_ip'   => $ip | ||||
|             ]); | ||||
|             LoginLog::create([ | ||||
|                 'member_id'   => $member['id'], | ||||
|                 'name'        => $member['username'], | ||||
|                 'ip'          => $ip, | ||||
|                 'create_time' => $time | ||||
|             ]); | ||||
|             session('auth', $userInfo); | ||||
|             return $this->json(0, 'success', ['url' => '/manager']); | ||||
|         } | ||||
| 
 | ||||
|         $viewData = []; | ||||
|         return view()->assign($viewData); | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,21 @@ | |||
| <?php | ||||
| namespace app\controller\manager; | ||||
| 
 | ||||
| use app\controller\BaseController; | ||||
| use think\response\Redirect; | ||||
| 
 | ||||
| class Logout extends BaseController | ||||
| { | ||||
|     protected $noNeedLogin = ['index']; | ||||
| 
 | ||||
|     /** | ||||
|      * 退出 | ||||
|      * | ||||
|      * @return Redirect | ||||
|      */ | ||||
|     public function index(): Redirect | ||||
|     { | ||||
|         session(null); | ||||
|         return redirect(url('/manager/login/index')); | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,411 @@ | |||
| <?php | ||||
| 
 | ||||
| namespace app\controller\manager; | ||||
| 
 | ||||
| use app\model\Log; | ||||
| use app\model\Member as MemberModel; | ||||
| use app\model\Role as RoleModel; | ||||
| use app\model\Business as BusinessModel; | ||||
| use app\repository\BusinessRepository; | ||||
| use Exception; | ||||
| use tauthz\facade\Enforcer; | ||||
| use think\db\exception\DataNotFoundException; | ||||
| use think\db\exception\DbException; | ||||
| use think\db\exception\ModelNotFoundException; | ||||
| use think\exception\ValidateException; | ||||
| use think\facade\Db; | ||||
| use think\response\Json; | ||||
| use think\response\Redirect; | ||||
| use think\response\View; | ||||
| 
 | ||||
| /** | ||||
|  * (后台)人员管理 | ||||
|  * | ||||
|  * Class Member | ||||
|  * @package app\controller\manager | ||||
|  */ | ||||
| class Member extends Base | ||||
| { | ||||
|     /** | ||||
|      * 删除 | ||||
|      * | ||||
|      * @return Json | ||||
|      */ | ||||
|     public function del(): Json | ||||
|     { | ||||
|         if ($this->request->isPost()) { | ||||
|             $ids = input('post.ids/a', []); | ||||
|             if (empty($ids)) { | ||||
|                 $ids[] = input('post.id/d'); | ||||
|             } | ||||
|             MemberModel::deleteByIds($ids); | ||||
|             foreach ($ids as $id) { | ||||
|                 Enforcer::deleteRolesForUser($id); | ||||
|             } | ||||
|             Log::write(get_class().'Del', 'del', '涉及到的ID为:'.implode(',', $ids)); | ||||
|             return $this->json(); | ||||
|         } | ||||
|         return $this->json(4001, '非法请求!'); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 个人详情 | ||||
|      * | ||||
|      * @return Json|View|Redirect | ||||
|      * @throws DataNotFoundException | ||||
|      * @throws DbException | ||||
|      * @throws ModelNotFoundException | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public function profile() | ||||
|     { | ||||
|         $id = $this->auth['user_id'] ?? 0; | ||||
| 
 | ||||
|         if (!$item = MemberModel::findById($id)) { | ||||
|             if ($this->request->isAjax()) { | ||||
|                 return $this->json(4001, '记录不存在'); | ||||
|             } | ||||
|             return $this->error('记录不存在'); | ||||
|         } | ||||
| 
 | ||||
|         if ($this->request->isPost()) { | ||||
|             $post = input('post.'); | ||||
| 
 | ||||
|             $validate = $this->validateByApi($post, [ | ||||
|                 'mobile|手机号'  => 'require|unique:member,mobile,'.$id, | ||||
|                 'nickname|昵称' => 'require|chsAlphaNum|min:2|max:10', | ||||
|                 'remark|备注信息' => 'max:255', | ||||
|             ]); | ||||
| 
 | ||||
|             if ($validate !== true) { | ||||
|                 return $validate; | ||||
|             } | ||||
| 
 | ||||
|             if (!checkMobile($post['mobile'])) { | ||||
|                 return $this->json(4002, '请输入正确的手机号码'); | ||||
|             } | ||||
| 
 | ||||
|             try { | ||||
|                 $item->save($post); | ||||
|                 return $this->json(); | ||||
|             } catch (ValidateException $e) { | ||||
|                 return $this->json(4001, $e->getError()); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         $this->data['item'] = $item; | ||||
| 
 | ||||
|         return $this->view(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 编辑 | ||||
|      * | ||||
|      * @return Json|View | ||||
|      * @throws DataNotFoundException | ||||
|      * @throws DbException | ||||
|      * @throws ModelNotFoundException | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public function edit() | ||||
|     { | ||||
|         $id = input('id/d', 0); | ||||
| 
 | ||||
|         if (!$info = MemberModel::findById($id)) { | ||||
|             return $this->json(4001, '记录不存在'); | ||||
|         } | ||||
| 
 | ||||
|         if ($this->request->isPost()) { | ||||
|             $item = input('post.'); | ||||
| 
 | ||||
|             $validate = $this->validateByApi($item, [ | ||||
|                 'mobile|手机号'  => 'require|unique:member,mobile,'.$id, | ||||
|                 'nickname|昵称' => 'require|chsAlphaNum|min:2|max:10', | ||||
|                 'remark|备注信息' => 'max:255', | ||||
|             ]); | ||||
| 
 | ||||
|             if ($validate !== true) { | ||||
|                 return $validate; | ||||
|             } | ||||
| 
 | ||||
|             if (!checkMobile($item['mobile'])) { | ||||
|                 return $this->json(4002, '请输入正确的手机号码'); | ||||
|             } | ||||
| 
 | ||||
|             $roles = []; | ||||
|             if ($item['roles']) { | ||||
|                 $roles = $item['roles']; | ||||
|                 $item['roles'] = implode(',', $item['roles']); | ||||
|             } | ||||
| 
 | ||||
| 
 | ||||
|             Db::startTrans(); | ||||
|             try { | ||||
|                 //之前关联的商家不为空 并且已经改变  吧之前的商家 从代理商变成普通商家
 | ||||
|                 if ($info['business_code'] != $item['business_code']) { | ||||
|                     if(!empty($info['business_code']) ){ | ||||
|                         $oldBusiness = BusinessRepository::getInstance()->findOneByWhere(["code" => $info['business_code']]); | ||||
|                         if (!empty($oldBusiness)) { | ||||
|                             $oldBusiness->save(["is_agency" => BusinessModel::COMMON_OFF]); | ||||
|                         } | ||||
|                     } | ||||
|                     //如果改变了关联商家
 | ||||
|                     if(!empty($item['business_code'])){ | ||||
|                         $Business = BusinessRepository::getInstance()->findOneByWhere(["code" => $item['business_code']]); | ||||
|                         if (empty($Business)) { | ||||
|                             Db::rollback(); | ||||
|                             return $this->json(4001, "指定商家不存在"); | ||||
|                         } | ||||
|                         $Business->save(["is_agency" => BusinessModel::COMMON_ON]); | ||||
|                     } | ||||
|                 } | ||||
| 
 | ||||
|                 $info->save($item); | ||||
|                 //删除所有角色
 | ||||
|                 Enforcer::deleteRolesForUser($id); | ||||
|                 //新增角色
 | ||||
|                 foreach ($roles as $role) { | ||||
|                     Enforcer::addRoleForUser($id, $role); | ||||
|                 } | ||||
|                 Db::commit(); | ||||
|                 return $this->json(); | ||||
|             } catch (ValidateException $e) { | ||||
|                 Db::rollback(); | ||||
|                 return $this->json(4001, $e->getError()); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         $this->data['item'] = $info; | ||||
|         $this->data['roleJson'] = $this->roleJson(explode(',', $info['roles'])); | ||||
| 
 | ||||
|         $this->data['business'] = BusinessRepository::getInstance()->getBusinessAll(); | ||||
| 
 | ||||
|         return $this->view(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 单个字段编辑 | ||||
|      * | ||||
|      * @return Json | ||||
|      * @throws DataNotFoundException | ||||
|      * @throws DbException | ||||
|      * @throws ModelNotFoundException | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public function modify(): Json | ||||
|     { | ||||
|         if ($this->request->isPost()) { | ||||
|             $item     = input('post.'); | ||||
|             $validate = $this->validateByApi($item, [ | ||||
|                 'field' => 'require', | ||||
|                 'value' => 'require', | ||||
|             ]); | ||||
| 
 | ||||
|             if ($validate !== true) { | ||||
|                 return $validate; | ||||
|             } | ||||
| 
 | ||||
|             if (!$info = MemberModel::findById($item['id'])) { | ||||
|                 return $this->json(4001, '记录不存在'); | ||||
|             } | ||||
| 
 | ||||
|             $update = [$item['field'] => $item['value']]; | ||||
| 
 | ||||
|             try { | ||||
|                 $info->save($update); | ||||
|                 return $this->json(); | ||||
|             } catch (ValidateException $e) { | ||||
|                 return $this->json(4001, $e->getError()); | ||||
|             } | ||||
|         } | ||||
|         return $this->json(4000, '非法请求'); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 添加 | ||||
|      * | ||||
|      * @return Json|View | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public function add() | ||||
|     { | ||||
|         if ($this->request->isPost()) { | ||||
|             $item = input('post.'); | ||||
| 
 | ||||
|             $validate = $this->validateByApi($item, [ | ||||
|                 'username|用户名' => 'require|alphaDash|min:4|max:16|unique:member', | ||||
|                 'mobile|手机号'   => 'require|unique:member', | ||||
|                 'nickname|昵称'  => 'require|chsAlphaNum|min:2|max:10', | ||||
|                 'password|密码'  => 'require|min:4|max:16', | ||||
|                 'remark|备注信息'  => 'max:255', | ||||
|             ]); | ||||
| 
 | ||||
|             if ($validate !== true) { | ||||
|                 return $validate; | ||||
|             } | ||||
| 
 | ||||
|             if (!checkMobile($item['mobile'])) { | ||||
|                 return $this->json(4002, '请输入正确的手机号码'); | ||||
|             } | ||||
| 
 | ||||
|             $roles = []; | ||||
|             if ($item['roles']) { | ||||
|                 $roles = $item['roles']; | ||||
|                 $item['roles'] = implode(',', $item['roles']); | ||||
|             } | ||||
| 
 | ||||
|             Db::startTrans(); | ||||
|             try { | ||||
|                 $item['password'] = md5($item['password'].$item['username']); | ||||
|                 $member = MemberModel::create($item); | ||||
|                 foreach ($roles as $role) { | ||||
|                     Enforcer::addRoleForUser($member['id'], $role); | ||||
|                 } | ||||
|                 Db::commit(); | ||||
|                 return $this->json(); | ||||
|             } catch (ValidateException $e) { | ||||
|                 Db::rollback(); | ||||
|                 return $this->json(4001, $e->getError()); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         $this->data['roleJson'] = $this->roleJson(); | ||||
|         return $this->view(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 修改密码 | ||||
|      * | ||||
|      * @return Json|View|Redirect | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public function password() | ||||
|     { | ||||
|         $id = input('id/d', 0); | ||||
| 
 | ||||
|         if (!$item = MemberModel::findById($id)) { | ||||
|             if ($this->request->isAjax()) { | ||||
|                 return $this->json(4001, '记录不存在'); | ||||
|             } | ||||
|             return $this->error('记录不存在'); | ||||
|         } | ||||
| 
 | ||||
|         if ($this->request->isPost()) { | ||||
|             $post     = input('post.'); | ||||
|             $validate = $this->validateByApi($post, [ | ||||
|                 'password|密码' => 'require|confirm', | ||||
|             ]); | ||||
| 
 | ||||
|             if ($validate !== true) { | ||||
|                 return $validate; | ||||
|             } | ||||
| 
 | ||||
|             $password = md5($post['password'].$item['username']); | ||||
| 
 | ||||
|             try { | ||||
|                 $item->save(['password' => $password]); | ||||
|                 return $this->json(); | ||||
|             } catch (ValidateException $e) { | ||||
|                 return $this->json(4001, $e->getError()); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         $this->data['item'] = $item; | ||||
| 
 | ||||
|         return $this->view(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 个人修改密码 | ||||
|      * | ||||
|      * @return Json|View | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public function myPassword() | ||||
|     { | ||||
|         $id = $this->auth['user_id'] ?? 0; | ||||
|         if (!$item = MemberModel::findById($id)) { | ||||
|             return $this->json(4001, '记录不存在'); | ||||
|         } | ||||
| 
 | ||||
|         if ($this->request->isPost()) { | ||||
|             $post     = input('post.'); | ||||
|             $validate = $this->validateByApi($post, [ | ||||
|                 'old-password|旧密码' => 'require', | ||||
|                 'password|密码'      => 'require|confirm', | ||||
|             ]); | ||||
| 
 | ||||
|             if ($validate !== true) { | ||||
|                 return $validate; | ||||
|             } | ||||
| 
 | ||||
|             if ($item['password'] !== md5($post['old-password'].$item['username'])) { | ||||
|                 return $this->json(4002, '原始密码错误'); | ||||
|             } | ||||
| 
 | ||||
|             $password = md5($post['password'].$item['username']); | ||||
| 
 | ||||
|             try { | ||||
|                 $item->save(['password' => $password]); | ||||
|                 return $this->json(); | ||||
|             } catch (ValidateException $e) { | ||||
|                 return $this->json(4001, $e->getError()); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         $this->data['item'] = $item; | ||||
|         return $this->view(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 列表 | ||||
|      * | ||||
|      * @return View|Json | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public function index() | ||||
|     { | ||||
|         if ($this->request->isPost()) { | ||||
|             $page         = input('page/d', 1); | ||||
|             $limit        = input('size/d', 20); | ||||
|             $searchParams = input('searchParams'); | ||||
|             $where        = []; | ||||
|             if ($searchParams) { | ||||
|                 foreach ($searchParams as $key => $param) { | ||||
|                     if (!empty($param)) { | ||||
|                         $where[] = [$key, 'like', '%'.$param.'%']; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             $items = MemberModel::findList($where, [], $page, $limit, function ($q) { | ||||
|                 return $q->order('id', 'desc'); | ||||
|             }); | ||||
| 
 | ||||
|             return $this->json(0, '操作成功', $items); | ||||
|         } | ||||
|         return $this->view(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 构造角色json数据 | ||||
|      * | ||||
|      * @param  array  $selected | ||||
|      * @return false|string | ||||
|      * @throws DataNotFoundException | ||||
|      * @throws DbException | ||||
|      * @throws ModelNotFoundException | ||||
|      */ | ||||
|     private function roleJson(array $selected = []) | ||||
|     { | ||||
|         $roles    = RoleModel::where('status', RoleModel::STATUS_NORMAL) | ||||
|             ->order('sort', 'desc') | ||||
|             ->select() | ||||
|             ->toArray(); | ||||
|         foreach ($roles as $k => $m) { | ||||
|             $roles[$k]['checked'] = in_array($m['id'], $selected); | ||||
|             $roles[$k]['spread']  = true; | ||||
|         } | ||||
|         return json_encode($roles, JSON_UNESCAPED_UNICODE); | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,263 @@ | |||
| <?php | ||||
| 
 | ||||
| namespace app\controller\manager; | ||||
| 
 | ||||
| use app\repository\CmsRepository; | ||||
| use app\model\Log; | ||||
| use app\model\Menu as MenuModel; | ||||
| 
 | ||||
| use app\validate\MenuValidate; | ||||
| use Exception; | ||||
| use think\db\exception\DataNotFoundException; | ||||
| use think\db\exception\DbException; | ||||
| use think\db\exception\ModelNotFoundException; | ||||
| use think\exception\ValidateException; | ||||
| use think\facade\Db; | ||||
| use think\response\Json; | ||||
| use think\response\View; | ||||
| 
 | ||||
| /** | ||||
|  * 菜单管理 | ||||
|  * | ||||
|  * Class Menu | ||||
|  * @package app\controller\manager | ||||
|  */ | ||||
| class Menu extends Base | ||||
| { | ||||
| 
 | ||||
|     /** | ||||
|      * 删除 | ||||
|      * | ||||
|      * @return Json | ||||
|      */ | ||||
|     public function del(): Json | ||||
|     { | ||||
|         if ($this->request->isPost()) { | ||||
|             $ids = input('post.ids/a', []); | ||||
|             if (empty($ids)) { | ||||
|                 $ids[] = input('post.id/d'); | ||||
|             } | ||||
|             $repo = CmsRepository::getInstance(); | ||||
|             if ($repo->hasChildrenMenuByIds($ids)) { | ||||
|                 return $this->json(4002, '待删除数据存在子数据'); | ||||
|             } | ||||
|             $repo->delMenuByIds($ids); | ||||
|             Log::write('menuDel', 'del', '删除了菜单,涉及到的ID为:'.implode(',', $ids)); | ||||
|             return $this->json(); | ||||
|         } | ||||
|         return $this->json(4001, '非法请求!'); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 规则 | ||||
|      * | ||||
|      * @return string[] | ||||
|      */ | ||||
|     private function rule(): array | ||||
|     { | ||||
|         return [ | ||||
|             'pid|父级菜单'    => 'require|number', | ||||
|             'title|标题'    => 'require|max:100', | ||||
|             'name|路由标识'   => 'require', | ||||
|             'remark|备注信息' => 'max:255', | ||||
|         ]; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     /** | ||||
|      * 编辑 | ||||
|      * | ||||
|      * @return Json|View | ||||
|      * @throws DataNotFoundException | ||||
|      * @throws DbException | ||||
|      * @throws ModelNotFoundException | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public function edit() | ||||
|     { | ||||
|         $id = input('id/d', 0); | ||||
| 
 | ||||
|         if (!$info = MenuModel::findById($id)) { | ||||
|             return $this->json(4001, '记录不存在'); | ||||
|         } | ||||
| 
 | ||||
|         if ($this->request->isPost()) { | ||||
|             $item     = input('post.'); | ||||
|             $validate = $this->validateByApi($item, $this->rule()); | ||||
|             if ($validate !== true) { | ||||
|                 return $validate; | ||||
|             } | ||||
| 
 | ||||
|             try { | ||||
|                 $oldPath      = $info['path']; | ||||
|                 $item['path'] = MenuModel::getPath($item['pid']); | ||||
|                 $info->save($item); | ||||
| 
 | ||||
|                 //刷新所有路径
 | ||||
|                 $oldPath = $oldPath.','.$id; | ||||
|                 $newPath = $item['path'].','.$id; | ||||
|                 if ($oldPath != $newPath) { | ||||
|                     MenuModel::refreshPath(); | ||||
|                 } | ||||
|                 return $this->json(); | ||||
|             } catch (ValidateException $e) { | ||||
|                 return $this->json(4001, $e->getError()); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         $disabled               = MenuModel::getAllChildrenIds($id); | ||||
|         $disabled[]             = $id; | ||||
|         $this->data['menuList'] = $this->menuJson([$info['pid']], $disabled); | ||||
|         $this->data['item']     = $info; | ||||
| 
 | ||||
|         return $this->view(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 单个字段编辑 | ||||
|      * | ||||
|      * @return Json | ||||
|      * @throws DataNotFoundException | ||||
|      * @throws DbException | ||||
|      * @throws ModelNotFoundException | ||||
|      */ | ||||
|     public function modify(): Json | ||||
|     { | ||||
|         if ($this->request->isPost()) { | ||||
|             $item     = input('post.'); | ||||
|             $validate = new MenuValidate(); | ||||
|             if (!$validate->scene('menu_modify')->check($item)) { | ||||
|                 return $this->json(4002, $validate->getError()); | ||||
|             } | ||||
| 
 | ||||
|             if (!$info = MenuModel::findById($item['id'])) { | ||||
|                 return $this->json(4001, '记录不存在'); | ||||
|             } | ||||
| 
 | ||||
|             $update = [$item['field'] => $item['value']]; | ||||
| 
 | ||||
|             try { | ||||
|                 $info->save($update); | ||||
|                 return $this->json(); | ||||
|             } catch (ValidateException $e) { | ||||
|                 return $this->json(4001, $e->getError()); | ||||
|             } | ||||
|         } | ||||
|         return $this->json(4000, '非法请求'); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 添加 | ||||
|      * | ||||
|      * @return Json|View | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public function add() | ||||
|     { | ||||
|         $id = input('id/d', 0); | ||||
| 
 | ||||
|         if ($this->request->isPost()) { | ||||
|             $item     = input('post.'); | ||||
|             $validate = $this->validateByApi($item, $this->rule()); | ||||
|             if ($validate !== true) { | ||||
|                 return $validate; | ||||
|             } | ||||
|             try { | ||||
|                 $item['path'] = MenuModel::getPath($item['pid']); | ||||
|                 MenuModel::create($item); | ||||
|                 return $this->json(); | ||||
|             } catch (ValidateException $e) { | ||||
|                 return $this->json(4001, $e->getError()); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         $selected               = $id > 0 ? [$id] : []; | ||||
|         $this->data['menuList'] = $this->menuJson($selected); | ||||
| 
 | ||||
|         return $this->view(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 常规权限生成 | ||||
|      * | ||||
|      * @return Json|View | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public function generate() | ||||
|     { | ||||
|         $id = input('id/d', 0); | ||||
| 
 | ||||
|         if ($this->request->isPost()) { | ||||
|             $id = input('id/d', 0); | ||||
|             if (!$item = MenuModel::findById($id)) { | ||||
|                 return $this->json(4002, '记录不存在'); | ||||
|             } | ||||
| 
 | ||||
|             if ($item['type'] != MenuModel::TYPE_MENU) { | ||||
|                 return $this->json(4003, '仅菜单类型可操作'); | ||||
|             } | ||||
| 
 | ||||
|             Db::startTrans(); | ||||
|             try { | ||||
|                 //自动生成常规操作
 | ||||
|                 MenuModel::generate($id, $item['name'], $item['path']); | ||||
|                 Db::commit(); | ||||
|                 return $this->json(); | ||||
|             } catch (ValidateException $e) { | ||||
|                 Db::rollback(); | ||||
|                 return $this->json(4001, $e->getError()); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         $selected               = $id > 0 ? [$id] : []; | ||||
|         $this->data['menuList'] = $this->menuJson($selected); | ||||
| 
 | ||||
|         return $this->view(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 列表 | ||||
|      * | ||||
|      * @return View|Json | ||||
|      */ | ||||
|     public function index() | ||||
|     { | ||||
|         if ($this->request->isPost()) { | ||||
|             $menus = CmsRepository::getInstance()->getMenuList(); | ||||
|             $menus->each(function ($item) { | ||||
|                 if ($item['type'] == 'menu') { | ||||
|                     $item->open = false; | ||||
|                 } | ||||
|             }); | ||||
|             $res = [ | ||||
|                 'code'  => 0, | ||||
|                 'msg'   => 'success', | ||||
|                 'count' => $menus->count(), | ||||
|                 'data'  => $menus->toArray(), | ||||
|             ]; | ||||
|             return json($res); | ||||
|         } | ||||
|         return $this->view(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * xmSelect插件 json数据 | ||||
|      * | ||||
|      * @param  array  $selected | ||||
|      * @param  array  $disabled | ||||
|      * @return false|string | ||||
|      */ | ||||
|     private function menuJson(array $selected = [], array $disabled = []) | ||||
|     { | ||||
|         $categoryList[] = ['title' => '顶级菜单', 'id' => 0, 'prefix' => '', 'disabled' => false, 'open' => true, 'selected' => in_array(0, $selected)]; | ||||
|         $menus          = CmsRepository::getInstance()->getMenuList(); | ||||
|         $menus          = $menus->toArray(); | ||||
|         foreach ($menus as $k => $m) { | ||||
|             $menus[$k]['selected'] = in_array($m['id'], $selected); | ||||
|             $menus[$k]['disabled'] = in_array($m['id'], $disabled); | ||||
|         } | ||||
|         $menus        = CmsRepository::getInstance()->buildMenuChild(0, $menus); | ||||
|         $categoryList = array_merge($categoryList, CmsRepository::getInstance()->handleSelectedList($menus)); | ||||
|         return json_encode($categoryList, JSON_UNESCAPED_UNICODE); | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,165 @@ | |||
| <?php | ||||
| namespace app\controller\manager; | ||||
| 
 | ||||
| use app\model\{Model as MModel, Log}; | ||||
| use app\validate\Model as VModel; | ||||
| use think\exception\ValidateException; | ||||
| 
 | ||||
| class Model extends Base  | ||||
| { | ||||
|     //删除模型
 | ||||
|     public function del() | ||||
|     { | ||||
|         if($this->request->isPost()){ | ||||
|             $ids = input('post.ids/a'); | ||||
|             if(is_array($ids)) { | ||||
|                 $idsArr = $ids; | ||||
|             } else { | ||||
|                 $idsArr = array_filter(explode(',', $ids)); | ||||
|             } | ||||
|             if(count($idsArr) == 0) { | ||||
|                 return $this->json(1, '无效请求,参数错误!'); | ||||
|             } | ||||
|             $items = MModel::getListByIds($idsArr); | ||||
|             if(!empty($items)){ | ||||
|                 $delIds = []; | ||||
|                 foreach($items as $item){ | ||||
|                     $delIds[] = $item['id']; | ||||
|                 } | ||||
|                 MModel::destroy($delIds); | ||||
|                 Log::write('model', 'del', "模型删除,ID:" . implode(',', $ids)); | ||||
|                 return $this->json(); | ||||
|             } | ||||
|             return $this->json(2, '无效请求,参数错误!'); | ||||
|         } | ||||
|         return $this->json(1, '非法请求!'); | ||||
|     } | ||||
| 
 | ||||
|     //编辑模型
 | ||||
|     public function edit() | ||||
|     { | ||||
|         if($this->request->isPost()){ | ||||
|             $item = []; | ||||
|             $item['name'] = input('post.name'); | ||||
|             $item['template'] = input('post.template'); | ||||
|             $item['manager'] = input('post.manager'); | ||||
|             $id = input('post.id/d'); | ||||
|             if(is_numeric($id) && $id > 0) { | ||||
|                 $model = MModel::getById($id); | ||||
|                 if(empty($model)){ | ||||
|                     return $this->json(2, '无此模型数据!'); | ||||
|                 } | ||||
|                 try { | ||||
|                     validate(VModel::class)->check($item); | ||||
|                     MModel::updateById($id, $item); | ||||
|                     Log::write('model', 'edit', "模型编辑,ID:{$id}, 标题:{$item['name']}"); | ||||
|                     return $this->json(); | ||||
|                 } catch (ValidateException $e) { | ||||
|                     return $this->json(3, $e->getError()); | ||||
|                 } | ||||
|             } | ||||
|             return $this->json(1, '无效请求,参数错误!'); | ||||
|         }else{ | ||||
|             $id = input('param.id/d'); | ||||
|             if (is_numeric($id) && $id > 0) { | ||||
|                 $item = MModel::getById($id); | ||||
|                 $this->data['item'] = $item; | ||||
|                 return $this->view(); | ||||
|             } | ||||
|             return $this->json(1,'传入参数错误,请核对之后再操作!'); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 添加模型 | ||||
|      */ | ||||
|     public function add() | ||||
|     { | ||||
|         if($this->request->isPost()){ | ||||
|             $item = []; | ||||
|             $item['name'] = input('post.name'); | ||||
|             $item['template'] = input('post.template'); | ||||
|             $item['manager'] = input('post.manager'); | ||||
|             try { | ||||
|                 validate(VModel::class)->check($item); | ||||
|                 $model = MModel::create($item); | ||||
|                 Log::write('model', 'add', "模型新增,ID:{$model->id}, 标题:{$item['name']}"); | ||||
|                 return $this->json(); | ||||
|             } catch (ValidateException $e) { | ||||
|                 return $this->json(2, $e->getError()); | ||||
|             } | ||||
|         }else { | ||||
|             return $this->view(); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 模型列表 | ||||
|      */ | ||||
|     public function index() | ||||
|     { | ||||
|         $items = MModel::getList(); | ||||
|         $this->data['items'] = $items; | ||||
|         return $this->view(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 排序 | ||||
|      */ | ||||
|     public function sort() | ||||
|     { | ||||
|         if($this->request->isPost()){ | ||||
|             $id = input('post.id/d'); | ||||
|             $sort = input('post.sort'); | ||||
|             $num = input('post.num/d', 1); | ||||
|             if($num <= 0){ | ||||
|                 $num = 1; | ||||
|             } | ||||
|             if(!in_array($sort, ['up', 'down'], true)){ | ||||
|                 return $this->json(2, '参数错误'); | ||||
|             } | ||||
|             $item = MModel::getById($id); | ||||
|             if(empty($item)) { | ||||
|                 return $this->json(3, '无此模型!'); | ||||
|             } | ||||
|             if($sort == 'up'){ | ||||
|                 $where = "sort < {$item['sort']}"; | ||||
|                 $order = "sort desc"; | ||||
|             }else{ | ||||
|                 $where = "sort > {$item['sort']}"; | ||||
|                 $order = "sort asc"; | ||||
|             } | ||||
|             $forSortItems = MModel::getListByWhereAndOrder($where, $order, $num); | ||||
|             if(!empty($forSortItems)){ | ||||
|                 $updateData = []; | ||||
|                 $forSortCount = count($forSortItems); | ||||
|                 for($i = 0; $i < $forSortCount; $i++){ | ||||
|                     if($i == 0){ | ||||
|                         $updateData[] = [ | ||||
|                             'id' => $forSortItems[$i]['id'], | ||||
|                             'sort' => $item['sort'] | ||||
|                         ]; | ||||
|                     }else{ | ||||
|                         $updateData[] = [ | ||||
|                             'id' => $forSortItems[$i]['id'], | ||||
|                             'sort' => $forSortItems[$i - 1]['sort'] | ||||
|                         ]; | ||||
|                     } | ||||
|                 } | ||||
|                 $updateData[] = [ | ||||
|                     'id' => $item['id'], | ||||
|                     'sort' => $forSortItems[$i - 1]['sort'] | ||||
|                 ]; | ||||
|                 if(!empty($updateData)){ | ||||
|                     $model = new MModel(); | ||||
|                     $model->saveAll($updateData); | ||||
|                     $sortStr = $sort == 'up' ? '上移' : '下调'; | ||||
|                     Log::write('model', 'sort', "模型排序,ID:{$id} ,标题:{$item['name']},{$sortStr}了{$num}位"); | ||||
|                     return $this->json(); | ||||
|                 } | ||||
|             } | ||||
|             return $this->json(4, '无须调整排序!'); | ||||
|         } | ||||
|         return $this->json(1, '非法请求!'); | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,467 @@ | |||
| <?php | ||||
| namespace app\controller\manager; | ||||
| 
 | ||||
| use app\model\{Category, Block, Log}; | ||||
| use app\validate\Block as VBlock; | ||||
| use think\exception\ValidateException; | ||||
| use app\service\Tool; | ||||
| 
 | ||||
| class Page extends Base | ||||
| { | ||||
|     //源码,代码
 | ||||
|     public function code() | ||||
|     { | ||||
|         if($this->request->isPost()){ | ||||
|             $item = input('post.item/a'); | ||||
|             $categoryId = input('post.category_id/d'); | ||||
|             $id = input('post.id/d'); | ||||
|             $item['keyword'] = Tool::trimSpace($item['keyword']); | ||||
|             try{ | ||||
|                 validate(VBlock::class)->check($item); | ||||
|                 if(empty($item['value'])){ | ||||
|                     return $this->json(2, '内容不可为空!'); | ||||
|                 } | ||||
|                 $block = Block::getByKeyword($item['keyword'], $categoryId); | ||||
|                 if($id){ | ||||
|                     if(!empty($block) && $block['id'] != $id){ | ||||
|                         return $this->json(3, '键值已存在,请更改键值'); | ||||
|                     } | ||||
|                     Block::updateById($id, $item); | ||||
|                     Log::write('page', 'code', "单页代码编辑,ID:{$id}, 键值:{$item['keyword']}"); | ||||
|                 }else{ | ||||
|                     if($categoryId <= 0){ | ||||
|                         return $this->json(4, '栏目参数错误!'); | ||||
|                     } | ||||
|                     if(!empty($block)){ | ||||
|                         return $this->json(3, '键值已存在,请更改键值'); | ||||
|                     } | ||||
|                     $item['category_id'] = $categoryId; | ||||
|                     $item['type'] = Block::CODE; | ||||
|                     $block = Block::create($item); | ||||
|                     Log::write('page', 'code', "单页代码新增,ID:{$block->id}, 键值:{$item['keyword']}"); | ||||
|                 } | ||||
|                 return $this->json(); | ||||
|             } catch (ValidateException $e){ | ||||
|                 return $this->json(1, $e->getError()); | ||||
|             } | ||||
|         }else{ | ||||
|             $id = input('param.id/d'); | ||||
|             if($id <= 0){    //添加
 | ||||
|                 $categoryId = input('param.category_id/d'); | ||||
|                 $category = Category::getById($categoryId); | ||||
|                 if(empty($category)){ | ||||
|                     $url = url('manager.content/index')->__toString(); | ||||
|                     return $this->error('无此栏目', $url); | ||||
|                 } | ||||
|             }else{    //修改
 | ||||
|                 $item = Block::getById($id); | ||||
|                 if(empty($item)){ | ||||
|                     return $this->error('无此代码块!'); | ||||
|                 } | ||||
|                 $categoryId = $item['category_id']; | ||||
|                 $this->data['item'] = $item; | ||||
|             } | ||||
|             $this->data['categoryId'] = $categoryId; | ||||
|             return $this->view(); | ||||
|         } | ||||
|     } | ||||
|     //排序
 | ||||
|     public function sort() | ||||
|     { | ||||
|         if($this->request->isPost()){ | ||||
|             $id = input('post.id/d'); | ||||
|             $sort = input('post.sort'); | ||||
|             $num = input('post.num/d', 1); | ||||
|             if($num <= 0){ | ||||
|                 $num = 1; | ||||
|             } | ||||
|             if(!in_array($sort, ['up', 'down'], true)){ | ||||
|                 return $this->json(2, '参数错误'); | ||||
|             } | ||||
|             $item = Block::getById($id); | ||||
|             if(empty($item)){ | ||||
|                 return $this->json(3, '无此块信息'); | ||||
|             } | ||||
|             if($sort == 'up'){ | ||||
|                 $where = "category_id='{$item['category_id']}' and sort < {$item['sort']}"; | ||||
|                 $order = "sort desc"; | ||||
|             }else{ | ||||
|                 $where = "category_id='{$item['category_id']}' and sort > {$item['sort']}"; | ||||
|                 $order = "sort asc"; | ||||
|             } | ||||
|             $forSortItems = Block::getListByWhereAndOrder($where, $order, $num); | ||||
|             if(!empty($forSortItems)){ | ||||
|                 $updateData = []; | ||||
|                 $forSortCount = count($forSortItems); | ||||
|                 for($i = 0; $i < $forSortCount; $i++){ | ||||
|                     if($i == 0){ | ||||
|                         $updateData[] = [ | ||||
|                             'id' => $forSortItems[$i]['id'], | ||||
|                             'sort' => $item['sort'] | ||||
|                         ]; | ||||
|                     }else{ | ||||
|                         $updateData[] = [ | ||||
|                             'id' => $forSortItems[$i]['id'], | ||||
|                             'sort' => $forSortItems[$i - 1]['sort'] | ||||
|                         ]; | ||||
|                     } | ||||
|                 } | ||||
|                 $updateData[] = [ | ||||
|                     'id' => $item['id'], | ||||
|                     'sort' => $forSortItems[$i - 1]['sort'] | ||||
|                 ]; | ||||
|                 if(!empty($updateData)){ | ||||
|                     $model = new Block(); | ||||
|                     $model->saveAll($updateData); | ||||
|                     $sortStr = $sort == 'up' ? '上移' : '下调'; | ||||
|                     Log::write('page', 'sort', "单页区块排序,ID:{$id} ,键值:{$item['keyword']},{$sortStr}了{$num}位"); | ||||
|                     return $this->json(); | ||||
|                 } | ||||
|             } | ||||
|             return $this->json(4, '无须调整排序!'); | ||||
|         } | ||||
|         return $this->error('无此操作'); | ||||
|     } | ||||
|      | ||||
|     //删除
 | ||||
|     public function del() | ||||
|     { | ||||
|         if ($this->request->isAjax()) { | ||||
|             $id = input('post.id/d'); | ||||
|             $item = Block::getById($id); | ||||
|             if(!empty($item)){ | ||||
|                 Block::destroy($id); | ||||
|                 Log::write('page', 'del', "单页区块删除,ID:{$id} ,键值:{$item['keyword']}"); | ||||
|                 return $this->json(); | ||||
|             } | ||||
|             return $this->json(1, 'fail'); | ||||
|         } | ||||
|         return $this->error('无此操作'); | ||||
|     } | ||||
|     //图片
 | ||||
|     public function img() | ||||
|     { | ||||
|         if($this->request->isPost()){ | ||||
|             $item = input('post.item/a'); | ||||
|             $img = trim(input('post.img')); | ||||
|             $categoryId = input('post.category_id/d'); | ||||
|             if (!empty($img) && $img == 'null') { | ||||
|                 $img = ''; | ||||
|             } | ||||
|             $id = input('post.id/d'); | ||||
|             $item['keyword'] = Tool::trimSpace($item['keyword']); | ||||
|             try{ | ||||
|                 validate(VBlock::class)->check($item); | ||||
|                 $block = Block::getByKeyword($item['keyword'], $categoryId); | ||||
|                 if($id){ | ||||
|                     if(!empty($block) && $block['id'] != $id){ | ||||
|                         return $this->json(4, '键值已存在,请更改键值'); | ||||
|                     } | ||||
|                     if(!empty($img)){ | ||||
|                         $item['value'] = $img; | ||||
|                     } | ||||
|                     Block::updateById($id, $item); | ||||
|                     Log::write('page', 'img', "单页图片编辑,ID:{$id} ,键值:{$item['keyword']}"); | ||||
|                 }else{ | ||||
|                     if(!empty($block)){ | ||||
|                         return $this->json(4, '键值已存在,请更改键值'); | ||||
|                     } | ||||
|                     if($categoryId <= 0){ | ||||
|                         return $this->json(2, '栏目参数错误!!'); | ||||
|                     } | ||||
|                     if(empty($img)){ | ||||
|                         return $this->json(3, '图片不可为空'); | ||||
|                     } | ||||
|                     $item['value'] = $img; | ||||
|                     $item['type'] = Block::IMG; | ||||
|                     $item['category_id'] = $categoryId; | ||||
|                     $block = Block::create($item); | ||||
|                     Log::write('page', 'img', "单页图片新增,ID:{$block->id} ,键值:{$item['keyword']}"); | ||||
|                 } | ||||
|                 return $this->json(); | ||||
|             } catch (ValidateException $e){ | ||||
|                 return $this->json(1, $e->getError()); | ||||
|             } | ||||
|         }else{ | ||||
|             $id = input('param.id/d'); | ||||
|             if($id <= 0){    //添加
 | ||||
|                 $categoryId = input('param.category_id/d'); | ||||
|                 $category = Category::getById($categoryId); | ||||
|                 if(empty($category)){ | ||||
|                     $url = url('manager.content/index')->__toString(); | ||||
|                     return $this->error('无此栏目', $url); | ||||
|                 } | ||||
|             }else{    //修改
 | ||||
|                 $item = Block::getById($id); | ||||
|                 if(empty($item)){ | ||||
|                     return $this->error('无此图片!'); | ||||
|                 } | ||||
|                 $categoryId = $item['category_id']; | ||||
|                 $this->data['item'] = $item; | ||||
|             } | ||||
|             if(isset($item) && $item['width'] && $item['height']){ | ||||
|                 $imgSize = $item['width'].'px X '.$item['height'].'px'; | ||||
|             }else{ | ||||
|                 $imgSize = ''; | ||||
|             } | ||||
|             $this->data['categoryId'] = $categoryId; | ||||
|             $this->data['imgSize'] = $imgSize; | ||||
|             $this->data['groupId'] = session('auth.groupId'); | ||||
|             return $this->view(); | ||||
|         } | ||||
|     } | ||||
|     //文字块
 | ||||
|     public function block() | ||||
|     { | ||||
|         if($this->request->isPost()){ | ||||
|             $item = input('post.item/a'); | ||||
|             $categoryId = input('post.category_id/d'); | ||||
|             $id = input('post.id/d'); | ||||
|             $item['keyword'] = Tool::trimSpace($item['keyword']); | ||||
|             try{ | ||||
|                 validate(VBlock::class)->check($item); | ||||
|                 if(empty($item['value'])){ | ||||
|                     return $this->json(1, '内容不可为空!'); | ||||
|                 } | ||||
|                 $block = Block::getByKeyword($item['keyword'], $categoryId); | ||||
|                 if($id){ | ||||
|                     if(!empty($block) && $block['id'] != $id){ | ||||
|                         return $this->json(4, '键值已存在,请更改键值'); | ||||
|                     } | ||||
|                     Block::updateById($id, $item); | ||||
|                     Log::write('page', 'block', "单页文字块编辑,ID:{$id} ,键值:{$item['keyword']}"); | ||||
|                 }else{ | ||||
|                     if($categoryId <= 0){ | ||||
|                         return $this->json(2, '栏目参数错误!'); | ||||
|                     } | ||||
|                     if(!empty($block)){ | ||||
|                         return $this->json(4, '键值已存在,请更改键值'); | ||||
|                     } | ||||
|                     $item['category_id'] = $categoryId; | ||||
|                     $block = Block::create($item); | ||||
|                     Log::write('page', 'block', "单页文字块新增,ID:{$block->id} ,键值:{$item['keyword']}"); | ||||
|                 } | ||||
|                 return $this->json(); | ||||
|             } catch (ValidateException $e){ | ||||
|                 return $this->json(1, $e->getError()); | ||||
|             } | ||||
|         }else{ | ||||
|             $id = input('param.id/d'); | ||||
|             if($id <= 0){    //添加
 | ||||
|                 $categoryId = input('param.category_id/d'); | ||||
|                 $category = Category::getById($categoryId); | ||||
|                 if(empty($category)){ | ||||
|                     $url = url('manager.content/index')->__toString(); | ||||
|                     return $this->error('无此栏目', $url); | ||||
|                 } | ||||
|             }else{    //修改
 | ||||
|                 $item = Block::getById($id); | ||||
|                 if(empty($item)){ | ||||
|                     return $this->error('无此文字块!'); | ||||
|                 } | ||||
|                 $categoryId = $item['category_id']; | ||||
|                 $this->data['item'] = $item; | ||||
|             } | ||||
|             $this->data['categoryId'] = $categoryId; | ||||
|             return $this->view(); | ||||
|         } | ||||
|     } | ||||
|     //富文本内容
 | ||||
|     public function text() | ||||
|     { | ||||
|         if($this->request->isPost()){ | ||||
|             $item = input('post.item/a'); | ||||
|             $categoryId = input('post.category_id/d'); | ||||
|             $item['keyword'] = Tool::trimSpace($item['keyword']); | ||||
|             try{ | ||||
|                 validate(VBlock::class)->check($item); | ||||
|                 if(empty($item['value'])){ | ||||
|                     return $this->json(1, '内容不可为空!'); | ||||
|                 } | ||||
|                 $block = Block::getByKeyword($item['keyword'], $categoryId); | ||||
|                 $id = input('post.id/d'); | ||||
|                 if($id){ | ||||
|                     if(!empty($block) && $block['id'] != $id){ | ||||
|                         return $this->json(4, '键值已存在,请更改'); | ||||
|                     } | ||||
|                     Block::updateById($id, $item); | ||||
|                     Log::write('page', 'text', "单页富文本编辑,ID:{$id} ,键值:{$item['keyword']}"); | ||||
|                 }else{ | ||||
|                     if($categoryId <= 0){ | ||||
|                         return $this->json(2, '栏目参数错误!'); | ||||
|                     } | ||||
|                     if(!empty($block)){ | ||||
|                         return $this->json(4, '键值已存在,请更改键值'); | ||||
|                     } | ||||
|                     $item['category_id'] = $categoryId; | ||||
|                     $item['type'] = Block::TEXT; | ||||
|                     $block = Block::create($item); | ||||
|                     Log::write('page', 'text', "单页富文本新增,ID:{$block->id} ,键值:{$item['keyword']}"); | ||||
|                 } | ||||
|                 return $this->json(); | ||||
|             } catch (ValidateException $e){ | ||||
|                 return $this->json(1, $e->getError()); | ||||
|             } | ||||
|         }else{ | ||||
|             $id = input('param.id/d'); | ||||
|             if($id <= 0){    //添加
 | ||||
|                 $categoryId = input('param.category_id/d'); | ||||
|                 $category = Category::getById($categoryId); | ||||
|                 if(empty($category)){ | ||||
|                     $url = url('manager.content/index')->__toString(); | ||||
|                     return $this->error('无此栏目', $url); | ||||
|                 } | ||||
|             }else{    //修改
 | ||||
|                 $item = Block::getById($id); | ||||
|                 if(empty($item)){ | ||||
|                     return $this->error('无此富文本!'); | ||||
|                 } | ||||
|                 $categoryId = $item['category_id']; | ||||
|                 $this->data['item'] = $item; | ||||
|             } | ||||
|             $this->data['categoryId'] = $categoryId; | ||||
|             return $this->view(); | ||||
|         } | ||||
|     } | ||||
|     //组图
 | ||||
|     public function group() | ||||
|     { | ||||
|         if($this->request->isPost()){ | ||||
|             $item = input('post.item/a'); | ||||
|             $imgs = input('post.img/a'); | ||||
|             $categoryId = input('post.category_id/d'); | ||||
|             if (!empty($imgs) && is_array($imgs)) { | ||||
|                 $item['value'] = json_encode($imgs); | ||||
|             } else { | ||||
|                 $item['value'] = ''; | ||||
|             } | ||||
|             $item['keyword'] = Tool::trimSpace($item['keyword']); | ||||
|             try{ | ||||
|                 validate(VBlock::class)->check($item); | ||||
|                 $block = Block::getByKeyword($item['keyword'], $categoryId); | ||||
|                 $id = input('post.id/d'); | ||||
|                 if($id){ | ||||
|                     if(!empty($block) && $block['id'] != $id){ | ||||
|                         return $this->json(4, '键值已存在,请更改'); | ||||
|                     } | ||||
|                     Block::updateById($id, $item); | ||||
|                     Log::write('page', 'group', "单页组图编辑,ID:{$id} ,键值:{$item['keyword']}"); | ||||
|                 }else{ | ||||
|                     if($categoryId <= 0){ | ||||
|                         return $this->json(2, '栏目参数错误!'); | ||||
|                     } | ||||
|                     if(!empty($block)){ | ||||
|                         return $this->json(4, '键值已存在,请更改键值'); | ||||
|                     } | ||||
|                     $item['category_id'] = $categoryId; | ||||
|                     $item['type'] = Block::GROUP; | ||||
|                     $block = Block::create($item); | ||||
|                     Log::write('page', 'group', "单页组图新增,ID:{$block->id} ,键值:{$item['keyword']}"); | ||||
|                 } | ||||
|                 return $this->json(); | ||||
|             } catch (ValidateException $e){ | ||||
|                 return $this->json(1, $e->getError()); | ||||
|             } | ||||
|         }else{ | ||||
|             $id = input('param.id/d'); | ||||
|             if($id <= 0){    //添加
 | ||||
|                 $categoryId = input('param.category_id/d'); | ||||
|                 $category = Category::getById($categoryId); | ||||
|                 if(empty($category)){ | ||||
|                     $url = url('manager.content/index')->__toString(); | ||||
|                     return $this->error('无此栏目', $url); | ||||
|                 } | ||||
|             }else{    //修改
 | ||||
|                 $item = Block::getById($id); | ||||
|                 if(empty($item)){ | ||||
|                     return $this->error('无此组图!'); | ||||
|                 } | ||||
|                 $categoryId = $item['category_id']; | ||||
|                 $this->data['item'] = $item; | ||||
|             } | ||||
|             $this->data['categoryId'] = $categoryId; | ||||
|             if(isset($item) && $item['width'] && $item['height']){ | ||||
|                 $imgSize = $item['width'].'px X '.$item['height'].'px'; | ||||
|             }else{ | ||||
|                 $imgSize = ''; | ||||
|             } | ||||
|             $this->data['imgSize'] = $imgSize; | ||||
|             $this->data['groupId'] = session('auth.groupId'); | ||||
|             return $this->view(); | ||||
|         } | ||||
|     } | ||||
|     //视频
 | ||||
|     public function video() | ||||
|     { | ||||
|         if($this->request->isPost()){ | ||||
|             $item = input('post.item/a'); | ||||
|             $img = trim(input('post.img')); | ||||
|             $video = trim(input('post.video')); | ||||
|             $categoryId = input('post.category_id/d'); | ||||
|             $item['keyword'] = Tool::trimSpace($item['keyword']); | ||||
|             try{ | ||||
|                 validate(VBlock::class)->check($item); | ||||
|                 $block = Block::getByKeyword($item['keyword'], $categoryId); | ||||
|                 $id = input('post.id/d'); | ||||
|                 if($id){ | ||||
|                     if(!empty($block) && $block['id'] != $id){ | ||||
|                         return $this->json(4, '键值已存在,请更改'); | ||||
|                     } | ||||
|                     if(!empty($img)){ | ||||
|                         $item['img'] = $img; | ||||
|                     } | ||||
|                     if(!empty($video)){ | ||||
|                         $item['value'] = $video; | ||||
|                     } | ||||
|                     Block::updateById($id, $item); | ||||
|                     Log::write('page', 'video', "单页视频编辑,ID:{$id} ,键值:{$item['keyword']}"); | ||||
|                 }else{ | ||||
|                     if($categoryId <= 0){ | ||||
|                         return $this->json(2, '栏目参数错误!'); | ||||
|                     } | ||||
|                     if(!empty($block)){ | ||||
|                         return $this->json(3, '键值已存在,请更改键值'); | ||||
|                     } | ||||
|                     if(empty($video)){ | ||||
|                         return $this->json(3, '视频不可为空'); | ||||
|                     } | ||||
|                     $item['category_id'] = $categoryId; | ||||
|                     $item['type'] = Block::VIDEO; | ||||
|                     $item['value'] = $video; | ||||
|                     $item['img'] = $img; | ||||
|                     $block = Block::create($item); | ||||
|                     Log::write('page', 'video', "单页视频新增,ID:{$block->id} ,键值:{$item['keyword']}"); | ||||
|                 } | ||||
|                 return $this->json(); | ||||
|             } catch (ValidateException $e){ | ||||
|                 return $this->json(1, $e->getError()); | ||||
|             } | ||||
|         }else{ | ||||
|             $id = input('param.id/d'); | ||||
|             if($id <= 0){    //添加
 | ||||
|                 $categoryId = input('param.category_id/d'); | ||||
|                 $category = Category::getById($categoryId); | ||||
|                 if(empty($category)){ | ||||
|                     $url = url('manager.content/index')->__toString(); | ||||
|                     return $this->error('无此栏目', $url); | ||||
|                 } | ||||
|             }else{    //修改
 | ||||
|                 $item = Block::getById($id); | ||||
|                 if(empty($item)){ | ||||
|                     return $this->error('无此视频!'); | ||||
|                 } | ||||
|                 $categoryId = $item['category_id']; | ||||
|                 $this->data['item'] = $item; | ||||
|             } | ||||
|             $this->data['categoryId'] = $categoryId; | ||||
|             if(isset($item) && $item['width'] && $item['height']){ | ||||
|                 $imgSize = $item['width'].'px X '.$item['height'].'px'; | ||||
|             }else{ | ||||
|                 $imgSize = ''; | ||||
|             } | ||||
|             $this->data['imgSize'] = $imgSize; | ||||
|             $this->data['groupId'] = session('auth.groupId'); | ||||
|             return $this->view(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,270 @@ | |||
| <?php | ||||
| 
 | ||||
| namespace app\controller\manager; | ||||
| 
 | ||||
| use app\model\Log; | ||||
| use app\model\Menu; | ||||
| use app\model\Menu as MenuModel; | ||||
| use app\model\Role as RoleModel; | ||||
| use app\model\Rules; | ||||
| use app\repository\CmsRepository; | ||||
| use Exception; | ||||
| use think\db\exception\DataNotFoundException; | ||||
| use think\db\exception\DbException; | ||||
| use think\db\exception\ModelNotFoundException; | ||||
| use think\exception\ValidateException; | ||||
| use think\facade\Db; | ||||
| use think\response\Json; | ||||
| use think\response\View; | ||||
| 
 | ||||
| /** | ||||
|  * 角色管理 | ||||
|  * | ||||
|  * Class Role | ||||
|  * @package app\controller\manager | ||||
|  */ | ||||
| class Role extends Base | ||||
| { | ||||
| 
 | ||||
|     /** | ||||
|      * 删除 | ||||
|      * | ||||
|      * @return Json | ||||
|      */ | ||||
|     public function del(): Json | ||||
|     { | ||||
|         if ($this->request->isPost()) { | ||||
|             $ids = input('post.ids/a', []); | ||||
|             if (empty($ids)) { | ||||
|                 $ids[] = input('post.id/d'); | ||||
|             } | ||||
|             RoleModel::deleteByIds($ids); | ||||
|             Log::write(get_class().'Del', 'del', '涉及到的ID为:'.implode(',', $ids)); | ||||
|             return $this->json(); | ||||
|         } | ||||
|         return $this->json(4001, '非法请求!'); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 编辑 | ||||
|      * | ||||
|      * @return Json|View | ||||
|      * @throws DataNotFoundException | ||||
|      * @throws DbException | ||||
|      * @throws ModelNotFoundException | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public function edit() | ||||
|     { | ||||
|         $id = input('id/d', 0); | ||||
| 
 | ||||
|         if (!$info = RoleModel::findById($id)) { | ||||
|             return $this->json(4001, '记录不存在'); | ||||
|         } | ||||
| 
 | ||||
|         if ($this->request->isPost()) { | ||||
|             $item     = input('post.'); | ||||
|             $validate = $this->validateByApi($item, [ | ||||
|                 'title' => 'require', | ||||
|             ]); | ||||
| 
 | ||||
|             if ($validate !== true) { | ||||
|                 return $validate; | ||||
|             } | ||||
| 
 | ||||
|             try { | ||||
|                 $info->save($item); | ||||
|                 return $this->json(); | ||||
|             } catch (ValidateException $e) { | ||||
|                 return $this->json(4001, $e->getError()); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         $this->data['item'] = $info; | ||||
| 
 | ||||
|         return $this->view(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 单个字段编辑 | ||||
|      * | ||||
|      * @return Json | ||||
|      * @throws DataNotFoundException | ||||
|      * @throws DbException | ||||
|      * @throws ModelNotFoundException | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public function modify(): Json | ||||
|     { | ||||
|         if ($this->request->isPost()) { | ||||
|             $item     = input('post.'); | ||||
|             $validate = $this->validateByApi($item, [ | ||||
|                 'field' => 'require', | ||||
|                 'value' => 'require', | ||||
|             ]); | ||||
| 
 | ||||
|             if ($validate !== true) { | ||||
|                 return $validate; | ||||
|             } | ||||
| 
 | ||||
|             if (!$info = RoleModel::findById($item['id'])) { | ||||
|                 return $this->json(4001, '记录不存在'); | ||||
|             } | ||||
| 
 | ||||
|             $update = [$item['field'] => $item['value']]; | ||||
| 
 | ||||
|             try { | ||||
|                 $info->save($update); | ||||
|                 return $this->json(); | ||||
|             } catch (ValidateException $e) { | ||||
|                 return $this->json(4001, $e->getError()); | ||||
|             } | ||||
|         } | ||||
|         return $this->json(4000, '非法请求'); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 添加 | ||||
|      * | ||||
|      * @return Json|View | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public function add() | ||||
|     { | ||||
|         if ($this->request->isPost()) { | ||||
|             $item = input('post.'); | ||||
| 
 | ||||
|             $validate = $this->validateByApi($item, [ | ||||
|                 'title' => 'require', | ||||
|             ]); | ||||
| 
 | ||||
|             if ($validate !== true) { | ||||
|                 return $validate; | ||||
|             } | ||||
| 
 | ||||
|             try { | ||||
|                 RoleModel::create($item); | ||||
|                 return $this->json(); | ||||
|             } catch (ValidateException $e) { | ||||
|                 return $this->json(4001, $e->getError()); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         return $this->view(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 角色权限 | ||||
|      * | ||||
|      * @return Json|View | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public function rule() | ||||
|     { | ||||
|         $id = input('id/d', 0); | ||||
| 
 | ||||
|         if (!$item = RoleModel::findById($id)) { | ||||
|             return $this->json(4001, '记录不存在'); | ||||
|         } | ||||
| 
 | ||||
|         if ($this->request->isPost()) { | ||||
|             $ids    = input('post.ids'); | ||||
|             $roleUpdate = $ids;//角色更新数据
 | ||||
|             $ids    = explode(',', $ids); | ||||
| 
 | ||||
|             Db::startTrans(); | ||||
|             try { | ||||
|                 //查询角色已有权限
 | ||||
|                 $hasRules = Rules::where('ptype', 'p')->where('v0', $id)->select()->toArray(); | ||||
|                 //角色最新权限列表
 | ||||
|                 $currentRules = MenuModel::where('id', 'in', $ids)->field('name')->select()->toArray(); | ||||
| 
 | ||||
|                 foreach ($currentRules as &$rule) { | ||||
|                     $route = explode(':', $rule['name']); | ||||
|                     $v1 = $route[0]; | ||||
|                     $v2 = $route[1] ?? 'index'; | ||||
| 
 | ||||
|                     $rule['ptype'] = 'p'; | ||||
|                     $rule['v0'] = $id; | ||||
|                     $rule['v1'] = $v1; | ||||
|                     $rule['v2'] = $v2; | ||||
|                 } | ||||
| 
 | ||||
|                 foreach ($hasRules as $k => $has) { | ||||
|                     foreach ($currentRules as $m => $current) { | ||||
|                         if ($has['ptype'] == $current['ptype'] && $has['v0'] == $current['v0'] && $has['v1'] == $current['v1'] && $has['v2'] == $current['v2']) { | ||||
|                             unset($currentRules[$m]);//删除当前权限列表已存在的 currentRules剩下的就是需要添加的记录
 | ||||
|                             unset($hasRules[$k]);//删除已有权限中存在的 hasRules剩下的就是需要删除的记录
 | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
| 
 | ||||
|                 $insert = $currentRules;//需要添加的数据
 | ||||
|                 $delete = $hasRules;//需要删除的数据
 | ||||
| 
 | ||||
|                 $deleteIds = array_column($delete, 'id');//需要删除的ID
 | ||||
|                 (new Rules())->saveAll($insert); | ||||
|                 (new Rules())->where('id', 'in', $deleteIds)->delete(); | ||||
|                 cache('tauthz', null);//权限缓存清空
 | ||||
| 
 | ||||
|                 $item->save(['rules' => $roleUpdate]); | ||||
|                 Db::commit(); | ||||
|                 return $this->json(); | ||||
|             } catch (ValidateException $e) { | ||||
|                 Db::rollback(); | ||||
|                 return $this->json(4001, $e->getError()); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         $selected = explode(',', $item['rules']); | ||||
| 
 | ||||
|         $this->data['authJson'] = $this->authJson($selected); | ||||
|         $this->data['item']     = $item; | ||||
| 
 | ||||
|         return $this->view(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 构造json数据 | ||||
|      * | ||||
|      * @param  array  $selected | ||||
|      * @return false|string | ||||
|      * @throws DataNotFoundException | ||||
|      * @throws DbException | ||||
|      * @throws ModelNotFoundException | ||||
|      */ | ||||
|     private function authJson(array $selected = []) | ||||
|     { | ||||
|         $menus = Menu::field("id,pid,title,sort") | ||||
|             ->where('status', Menu::STATUS_NORMAL) | ||||
|             ->order('sort', 'desc') | ||||
|             ->order('id', 'asc') | ||||
|             ->select()->toArray(); | ||||
|         foreach ($menus as $k => $m) { | ||||
|             $menus[$k]['checked'] = in_array($m['id'], $selected); | ||||
|             $menus[$k]['open']    = true; | ||||
|         } | ||||
|         $menus = CmsRepository::getInstance()->buildMenuChild(0, $menus); | ||||
|         return json_encode($menus, JSON_UNESCAPED_UNICODE); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 列表 | ||||
|      * | ||||
|      * @return View|Json | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public function index() | ||||
|     { | ||||
|         if ($this->request->isPost()) { | ||||
|             $page  = input('page/d', 1); | ||||
|             $limit = input('size/d', 20); | ||||
|             $items = RoleModel::findList([], [], $page, $limit, function ($q) { | ||||
|                 return $q->order('sort', 'desc')->order('id', 'asc'); | ||||
|             }); | ||||
| 
 | ||||
|             return $this->json(0, '操作成功', $items); | ||||
|         } | ||||
|         return $this->view(); | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,183 @@ | |||
| <?php | ||||
| namespace app\controller\manager; | ||||
| 
 | ||||
| use app\model\{AuthRule, AuthGroup, Log}; | ||||
| use app\validate\AuthRule as VAuthRule; | ||||
| use Exception; | ||||
| use think\exception\ValidateException; | ||||
| use think\response\Json; | ||||
| 
 | ||||
| class Rule extends Base | ||||
| { | ||||
|     /** | ||||
|      * 权限排序 | ||||
|      * 暂不允许父级变更 | ||||
|      * | ||||
|      * @return Json | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public function sort() | ||||
|     { | ||||
|         if ($this->request->isAjax()) { | ||||
|             $id = input('post.id'); | ||||
|             $sort = input('post.sort'); | ||||
|             $num = input('post.num/d', 1); | ||||
|             if($num <= 0){ | ||||
|                 $num = 1; | ||||
|             } | ||||
|             if(!in_array($sort, ['up', 'down'], true)){ | ||||
|                 return $this->json(2, '参数错误'); | ||||
|             } | ||||
|             $item = AuthRule::getById($id); | ||||
|             if(empty($item)){ | ||||
|                 return $this->json(3, '权限不存在'); | ||||
|             } | ||||
|             if($sort == 'up'){ | ||||
|                 $where = "parent_id = {$item['parent_id']} and sort < {$item['sort']}"; | ||||
|                 $order = "sort desc"; | ||||
|             }else{ | ||||
|                 $where = "parent_id = {$item['parent_id']} and sort > {$item['sort']}"; | ||||
|                 $order = "sort asc"; | ||||
|             } | ||||
|             $forSortItems = AuthRule::getListByWhereAndOrder($where, $order, $num); | ||||
|             if(!empty($forSortItems)){ | ||||
|                 $updateData = []; | ||||
|                 $forSortCount = count($forSortItems); | ||||
|                 for($i = 0; $i < $forSortCount; $i++){ | ||||
|                     if($i == 0){ | ||||
|                         $updateData[] = [ | ||||
|                             'id' => $forSortItems[$i]['id'], | ||||
|                             'sort' => $item['sort'] | ||||
|                         ]; | ||||
|                     }else{ | ||||
|                         $updateData[] = [ | ||||
|                             'id' => $forSortItems[$i]['id'], | ||||
|                             'sort' => $forSortItems[$i - 1]['sort'] | ||||
|                         ]; | ||||
|                     } | ||||
|                 } | ||||
|                 $updateData[] = [ | ||||
|                     'id' => $item['id'], | ||||
|                     'sort' => $forSortItems[$i - 1]['sort'] | ||||
|                 ]; | ||||
|                 if(!empty($updateData)){ | ||||
|                     $model = new AuthRule(); | ||||
|                     $model->saveAll($updateData); | ||||
|                     $sortStr = $sort == 'up' ? '上移' : '下调'; | ||||
|                     Log::write('rule', 'sort', "权限排序,ID:{$id} ,标题:{$item['title']},{$sortStr}了{$num}位"); | ||||
|                     return $this->json(); | ||||
|                 } | ||||
|             } | ||||
|             return $this->json(4, '无须调整排序!'); | ||||
|         } | ||||
|         return $this->json(1, '非法请求!'); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 权限删除 | ||||
|      */ | ||||
|     public function del() | ||||
|     { | ||||
|         if ($this->request->isAjax()) { | ||||
|             $ids = input('post.ids/a'); | ||||
|             $items = AuthRule::where('id', 'in', $ids)->select(); | ||||
|             if(!$items){ | ||||
|                 return $this->json(1, '无此权限'); | ||||
|             } | ||||
|             if(AuthRule::where('parent_id', 'in', $ids)->count()){ | ||||
|                 return $this->json(2, '当前权限有下级权限,不可删除'); | ||||
|             } | ||||
|             AuthRule::destroy($ids); | ||||
|             AuthGroup::resetGroupRulesCache(); | ||||
|             $ids = implode(',', $ids); | ||||
|             Log::write('rule', 'del', "权限删除,ID:{$ids}"); | ||||
|             return $this->json(); | ||||
|         } | ||||
|         return $this->json(1, '非法请求!'); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 权限修改 | ||||
|      */ | ||||
|     public function edit() | ||||
|     { | ||||
|         if($this->request->isPost()){ | ||||
|             $item = input('post.item/a'); | ||||
|             $id = input('post.id'); | ||||
|             $rule = AuthRule::getById($id); | ||||
|             if(empty($rule)){ | ||||
|                 return $this->json(1, '请选择正确的权限'); | ||||
|             } | ||||
|             $rule2 = AuthRule::getByName($item['name']); | ||||
|             if(!empty($rule2) && $rule2['id'] != $id){ | ||||
|                 return $this->json(2, '已存在相同权限['.$item['name'].']'); | ||||
|             } | ||||
|             try { | ||||
|                 validate(VAuthRule::class)->check($item); | ||||
|                 AuthRule::updateById($id, $item); | ||||
|                 AuthGroup::resetGroupRulesCache(); | ||||
|                 Log::write('rule', 'edit', "权限编辑,ID:{$id}, 标题:{$item['title']}"); | ||||
|                 return $this->json(); | ||||
|             } catch (ValidateException $e) { | ||||
|                 return $this->json(3, $e->getError()); | ||||
|             } | ||||
|         } | ||||
|         $id = input('param.id/d'); | ||||
|         $rule = AuthRule::getById($id); | ||||
|         if(empty($rule)){ | ||||
|             return $this->json(1,'无此权限信息,请核对之后再操作!'); | ||||
|         }else{ | ||||
|             $this->data['item'] = $rule; | ||||
|             if($rule['parent_id'] > 0){ | ||||
|                 $parent = AuthRule::getById($rule['parent_id']); | ||||
|                 $this->data['parent'] = $parent; | ||||
|             } | ||||
|             return $this->view(); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 权限添加 | ||||
|      */ | ||||
|     public function add() | ||||
|     { | ||||
|         if($this->request->isPost()){ | ||||
|             $item = input('post.item/a'); | ||||
|             try { | ||||
|                 validate(VAuthRule::class)->check($item); | ||||
|                 $rule = AuthRule::getByName($item['name']); | ||||
|                 if(!empty($rule)){ | ||||
|                     return $this->json(1, '已存在相同权限'); | ||||
|                 } | ||||
|                 $rule = AuthRule::create($item); | ||||
|                 //基本权限的话需要重置所有已有角色权限缓存
 | ||||
|                 if ($item['is_base'] > 0) { | ||||
|                     AuthGroup::resetGroupRulesCache(); | ||||
|                 } else { | ||||
|                     AuthGroup::resetGroupRulesCache(1); | ||||
|                 } | ||||
|                 Log::write('rule', 'add', "权限新增,ID:{$rule->id}, 标题:{$item['title']}"); | ||||
|                 return $this->json(); | ||||
|             } catch (ValidateException $e) { | ||||
|                 return $this->json(2, $e->getError()); | ||||
|             } | ||||
|         } | ||||
|         $parentId = input('param.parent_id/d',0); | ||||
|         if($parentId > 0){ | ||||
|             $parent = AuthRule::getById($parentId); | ||||
|             $this->data['parent'] = $parent; | ||||
|         } | ||||
|         $this->data['parentId'] = $parentId; | ||||
|         return $this->view(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 权限列表(全部) | ||||
|      */ | ||||
|     public function index() | ||||
|     { | ||||
|         $list = AuthRule::getListTree(); | ||||
|         $this->data['items'] = $list; | ||||
|         return $this->view(); | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,277 @@ | |||
| <?php | ||||
| 
 | ||||
| namespace app\controller\manager; | ||||
| 
 | ||||
| use app\model\Log; | ||||
| use app\repository\CmsRepository; | ||||
| use app\repository\OperationRepository; | ||||
| use app\validate\Slide as VSlide; | ||||
| use Exception; | ||||
| use think\db\exception\DataNotFoundException; | ||||
| use think\db\exception\DbException; | ||||
| use think\db\exception\ModelNotFoundException; | ||||
| use think\exception\ValidateException; | ||||
| use think\response\Json; | ||||
| use think\response\View; | ||||
| 
 | ||||
| class Slide extends Base | ||||
| { | ||||
|     /** | ||||
|      * 编辑 | ||||
|      * | ||||
|      * @return Json|View | ||||
|      * @throws DbException | ||||
|      * @throws ModelNotFoundException | ||||
|      */ | ||||
|     public function edit() | ||||
|     { | ||||
|         $id = $this->request->param('id/d', 0); | ||||
| 
 | ||||
|         if (!$slide = OperationRepository::getInstance()->findSlideById($id)) { | ||||
|             return $this->json(4001, '数据不存在'); | ||||
|         } | ||||
| 
 | ||||
|         if ($this->request->isPost()) { | ||||
|             $item     = input('post.item/a'); | ||||
|             $validate = new VSlide(); | ||||
|             if (!$validate->scene('slide')->check($item)) { | ||||
|                 return $this->json(4002, $validate->getError()); | ||||
|             } | ||||
| 
 | ||||
|             unset($item['id']); | ||||
|             OperationRepository::getInstance()->updateSlide($item, $id); | ||||
|             return $this->json(); | ||||
|         } | ||||
| 
 | ||||
|         $this->data['item'] = $slide; | ||||
|         $this->data['positionsJson']    = $this->xmSelectPositionsJson([$slide['position']]); | ||||
|         $this->data['id']   = $id; | ||||
| 
 | ||||
|         return $this->view(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 添加 | ||||
|      * | ||||
|      * @return View|Json | ||||
|      */ | ||||
|     public function add() | ||||
|     { | ||||
|         $repo = OperationRepository::getInstance(); | ||||
| 
 | ||||
|         if ($this->request->isPost()) { | ||||
|             $item     = input('post.item/a'); | ||||
|             $validate = new VSlide(); | ||||
|             if (!$validate->scene('slide')->check($item)) { | ||||
|                 return $this->json(4002, $validate->getError()); | ||||
|             } | ||||
| 
 | ||||
|             $item['type']       = $item['type'] ?? 'img'; | ||||
|             $repo->createSlide($item); | ||||
|             return $this->json(); | ||||
|         } | ||||
| 
 | ||||
|         $this->data['positionsJson']    = $this->xmSelectPositionsJson(); | ||||
|         return $this->view(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 轮播图列表 | ||||
|      * | ||||
|      * @return Json|View | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public function index() | ||||
|     { | ||||
|         $repo = OperationRepository::getInstance(); | ||||
|         if ($this->request->isPost()) { | ||||
|             $position   = $this->request->param('position/s', ''); | ||||
|             $page       = $this->request->param('page/d', 1); | ||||
|             $size       = $this->request->param('size/d', 30); | ||||
| 
 | ||||
|             $whereMap   = []; | ||||
|             $orders     = ['sort'=>'asc']; | ||||
|             if (!empty($position)) { | ||||
|                 $whereMap[] = ['position', '=', $position]; | ||||
|             } | ||||
| 
 | ||||
|             $list = $repo->slideList($whereMap, [], $page, $size, null, $orders); | ||||
| 
 | ||||
|             return $this->json(0, 'success', $list); | ||||
|         } | ||||
| 
 | ||||
|         $this->data['positions'] = $repo->slidePositions(); | ||||
|         return $this->view(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 排序 | ||||
|      * @return Json | ||||
|      */ | ||||
|     public function sort() | ||||
|     { | ||||
|         if (!$this->request->isPost()) { | ||||
|             return $this->json(4000, '非法请求'); | ||||
|         } | ||||
|         try { | ||||
|             $id     = $this->request->param('id/d', 0); | ||||
|             $sort   = $this->request->param('sort/d', 0); | ||||
|             OperationRepository::getInstance()->updateSlide(['sort'=>$sort], $id); | ||||
|         } catch (Exception $e) { | ||||
|             return $this->json(4001, '排序失败'); | ||||
|         } | ||||
|         return $this->json(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 删除 | ||||
|      * @return Json | ||||
|      */ | ||||
|     public function del() | ||||
|     { | ||||
|         if (!$this->request->isPost()) { | ||||
|             return $this->json(4000, '非法请求'); | ||||
|         } | ||||
| 
 | ||||
|         $ids = $this->request->param('ids/a', []); | ||||
|         if (empty($ids)) { | ||||
|             $ids[] = $this->request->param('id/d', 0); | ||||
|             $ids = array_filter($ids); | ||||
|         } | ||||
| 
 | ||||
|         if (count($ids)) { | ||||
|             OperationRepository::getInstance()->deleteSlides($ids); | ||||
|             Log::write(get_class(), 'del', '删除了轮播图,涉及到的ID为:'.implode(',', $ids)); | ||||
|         } | ||||
|         return $this->json(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 显示位置下拉选项数据 | ||||
|      * | ||||
|      * @param array $selected | ||||
|      * @param array $disabled | ||||
|      * @return false|string | ||||
|      */ | ||||
|     private function xmSelectPositionsJson(array $selected = [], array $disabled = []) | ||||
|     { | ||||
|         $positionList = OperationRepository::getInstance()->slidePositions(); | ||||
|         foreach ($positionList as $k => $item) { | ||||
|             $positionList[$k]['selected'] = in_array($item['key'], $selected); | ||||
|             $positionList[$k]['disabled'] = in_array($item['key'], $disabled); | ||||
|         } | ||||
|         $positionList = CmsRepository::getInstance()->handleSelectedList($positionList); | ||||
|         return json_encode($positionList, JSON_UNESCAPED_UNICODE); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 轮播图显示位置管理 | ||||
|      * | ||||
|      */ | ||||
|     public function position() | ||||
|     { | ||||
|         $repo = OperationRepository::getInstance(); | ||||
| 
 | ||||
|         if ($this->request->isPost()) { | ||||
|             $list = $repo->slidePositionList([], [], 1, 0); | ||||
| 
 | ||||
|             return $this->json(0, 'success', $list); | ||||
|         } | ||||
|         return $this->view(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 添加显示位置信息 | ||||
|      * | ||||
|      * @return Json|View | ||||
|      */ | ||||
|     public function addPosition() | ||||
|     { | ||||
|         $repo = OperationRepository::getInstance(); | ||||
| 
 | ||||
|         if ($this->request->isPost()) { | ||||
|             $item     = input('post.item/a'); | ||||
|             try { | ||||
|                 $this->validate($item, [ | ||||
|                     'title|标题' => 'max:250', | ||||
|                     'key|位置标识' => 'require|max:100|alphaDash' | ||||
|                 ]); | ||||
|             } catch (ValidateException $e) { | ||||
|                 return $this->json(4002, $e->getError()); | ||||
|             } | ||||
| 
 | ||||
|             if ($repo->slidePositionExists($item['key'])) { | ||||
|                 return $this->json(4003, '当前位置标识已存在!'); | ||||
|             } | ||||
| 
 | ||||
|             $repo->createSlidePosition($item); | ||||
|             return $this->json(); | ||||
|         } | ||||
| 
 | ||||
|         return $this->view(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 编辑显示位置信息 | ||||
|      * | ||||
|      * @return Json|View | ||||
|      * @throws DbException | ||||
|      * @throws ModelNotFoundException | ||||
|      * @throws DataNotFoundException | ||||
|      */ | ||||
|     public function editPosition() | ||||
|     { | ||||
|         $id = $this->request->param('id/d', 0); | ||||
| 
 | ||||
|         if (!$position = OperationRepository::getInstance()->findSlidePositionById($id)) { | ||||
|             return $this->json(4001, '数据不存在'); | ||||
|         } | ||||
| 
 | ||||
|         if ($this->request->isPost()) { | ||||
|             $item     = input('post.item/a'); | ||||
|             try { | ||||
|                 $this->validate($item, [ | ||||
|                     'title|标题' => 'max:250' | ||||
|                 ]); | ||||
|             } catch (ValidateException $e) { | ||||
|                 return $this->json(4002, $e->getError()); | ||||
|             } | ||||
| 
 | ||||
|             unset($item['id']); | ||||
|             unset($item['key']); | ||||
|             OperationRepository::getInstance()->updateSlidePosition($item, $id); | ||||
|             return $this->json(); | ||||
|         } | ||||
| 
 | ||||
|         $this->data['item'] = $position; | ||||
|         $this->data['id']   = $id; | ||||
| 
 | ||||
|         return $this->view(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 删除显示位置信息 | ||||
|      * @return Json | ||||
|      */ | ||||
|     public function delPosition() | ||||
|     { | ||||
|         if (!$this->request->isPost()) { | ||||
|             return $this->json(4000, '非法请求'); | ||||
|         } | ||||
| 
 | ||||
|         $ids = $this->request->param('ids/a', []); | ||||
|         if (empty($ids)) { | ||||
|             $ids[] = $this->request->param('id/d', 0); | ||||
|             $ids = array_filter($ids); | ||||
|         } | ||||
| 
 | ||||
|         if (count($ids)) { | ||||
|             OperationRepository::getInstance()->deleteSlidePositions($ids); | ||||
|             Log::write(get_class(), 'delPosition', '删除了轮播显示位置,涉及到的ID为:'.implode(',', $ids)); | ||||
|         } | ||||
| 
 | ||||
|         return $this->json(); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
| } | ||||
|  | @ -0,0 +1,63 @@ | |||
| <?php | ||||
| 
 | ||||
| namespace app\controller\manager; | ||||
| 
 | ||||
| use app\service\Tool; | ||||
| use app\model\{System as MSystem, Log}; | ||||
| use app\service\Image; | ||||
| use think\facade\Cache; | ||||
| 
 | ||||
| class System extends Base | ||||
| { | ||||
|     /** | ||||
|      * 获取当前系统设置 | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function index() | ||||
|     { | ||||
|         if ($this->request->isPost()) { | ||||
|             $item = input('post.item/a'); | ||||
|             $img  = input('post.img'); | ||||
|             $system = MSystem::getSystem(); | ||||
|             if (empty($system)) { | ||||
|                 if(!empty($img)){ | ||||
|                     $item['mark_img'] = $img; | ||||
|                 } | ||||
|                 $system = MSystem::create($item); | ||||
|                 Log::write('system', 'index', "系统设置,ID:{$system->id}"); | ||||
|             } else { | ||||
|                 if (!empty($img)) { | ||||
|                     Image::delImg($system['mark_img']); | ||||
|                     $item['mark_img'] = $img; | ||||
|                 } | ||||
|                 MSystem::update($item, ['id' => $system['id']]); | ||||
|                 Log::write('system', 'index', "系统设置,ID:{$system['id']}"); | ||||
|             } | ||||
|             return $this->json(); | ||||
|         } else { | ||||
|             $item = MSystem::getSystem(); | ||||
|             $positions = Image::getMarkPosition(); | ||||
|              | ||||
|             $this->data['item'] = $item; | ||||
|             $this->data['positions'] = $positions; | ||||
|             return $this->view(); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     public function other() | ||||
|     { | ||||
|         return $this->view(); | ||||
|     } | ||||
| 
 | ||||
|     public function clearCache() | ||||
|     { | ||||
|         Cache::clear(); | ||||
|         $cachePath = app()->getRuntimePath().'cache'; | ||||
|         $tempPath = app()->getRuntimePath().'temp'; | ||||
|         Tool::removeByPath($cachePath); | ||||
|         Tool::removeByPath($tempPath); | ||||
|         clearstatcache(); | ||||
|         return $this->json(); | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,221 @@ | |||
| <?php | ||||
| 
 | ||||
| namespace app\controller\manager; | ||||
| 
 | ||||
| use app\service\Image; | ||||
| use app\model\{System, File}; | ||||
| use app\validate\Upload as VUpload; | ||||
| use think\facade\{Filesystem, Config, Lang}; | ||||
| use think\Image as TImage; | ||||
| use app\controller\BaseController; | ||||
| 
 | ||||
| class Upload extends BaseController | ||||
| { | ||||
|     protected $noNeedLogin = ['video', 'file', 'image', 'wangImage']; | ||||
|     private $isCompress = true; | ||||
|     private $validate; | ||||
|     private $uploadPath; | ||||
|     private $videoUploadPath; | ||||
|     private $uploadPathIsWritable = 0; | ||||
|     private $videoUploadPathIsWritable = 0; | ||||
|     private $DIRECTORY_SEPARATOR = "/"; | ||||
|     public function __construct() | ||||
|     { | ||||
|         $system = System::getSystem(); | ||||
|         if (!empty($system)) { | ||||
|             $this->isCompress = $system['compress'] ?? true; | ||||
|         } | ||||
|         $this->validate        = new VUpload(); | ||||
|         $this->uploadPath      = Config::get('filesystem.disks.local.url'); | ||||
|         $this->videoUploadPath = Config::get('filesystem.disks.video.url'); | ||||
|         if (is_writable(app()->getRootPath().'public'.$this->uploadPath)) { | ||||
|             $this->uploadPathIsWritable = 1; | ||||
|         } | ||||
|         if (is_writable(app()->getRootPath().'public'.$this->videoUploadPath)) { | ||||
|             $this->videoUploadPathIsWritable = 1; | ||||
|         } | ||||
|         $this->DIRECTORY_SEPARATOR = DIRECTORY_SEPARATOR == "\\" ? "/" : DIRECTORY_SEPARATOR; | ||||
|         ini_set('max_execution_time', '0'); | ||||
|         ini_set("memory_limit", '-1'); | ||||
|         set_time_limit(0); | ||||
|     } | ||||
| 
 | ||||
|     //视频上传
 | ||||
|     public function video() | ||||
|     { | ||||
|         $video = request()->file('video_video'); | ||||
|         if (!$this->videoUploadPathIsWritable) { | ||||
|             return $this->json(1, '上传文件夹需要写入权限'); | ||||
|         } | ||||
|         if ($this->validate->checkVideo($video)) { | ||||
|             $md5 = $video->md5();//文件md5
 | ||||
|             if ($fileItem = File::where('md5', $md5)->find()) { | ||||
|                 $return['src']          = $fileItem['src']; | ||||
|                 $fileItem['updated_at'] = date('Y-m-d H:i:s'); | ||||
|                 $fileItem->save(); | ||||
|                 return $this->json(200, '该文件已存在 路径为:'.$fileItem['path'], $return); | ||||
|             } | ||||
| 
 | ||||
|             $path    = request()->param('path/s', '');//指定路径 基于public下  若为空则默认
 | ||||
|             $hasPath = !empty($path); | ||||
| 
 | ||||
|             // 去除以/storage/开头的部分  如/storage/20210808/test => 20210808/test
 | ||||
|             $path     = ltrim(trim($path, $this->DIRECTORY_SEPARATOR), \app\model\Attachment::ROOT_NAME . $this->DIRECTORY_SEPARATOR); | ||||
|             $datePath = $hasPath ? $path : 'videos'.$this->DIRECTORY_SEPARATOR.date('Ymd');//自定义目录
 | ||||
|             $src      = Filesystem::putFile($datePath, $video, 'uniqid'); | ||||
| 
 | ||||
|             $src = $this->uploadPath.'/'.$src; | ||||
|             $return['src'] = $src; | ||||
|             File::add($video, $src, $md5, 'video');    //加入上传文件表
 | ||||
|             return $this->json(0, 'ok', $return); | ||||
|         } else { | ||||
| 
 | ||||
|             $errorMsg = Lang::get($this->validate->getError()); | ||||
|             return $this->json(1, $errorMsg); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     //文件上传(通用)
 | ||||
|     public function file() | ||||
|     { | ||||
|         $file     = request()->file('file_file'); | ||||
|         $md5      = $file->md5();//文件md5
 | ||||
|         $fileName = $file->getOriginalName();//原始文件名
 | ||||
|         if ($fileItem = File::where('md5', $md5)->find()) { | ||||
|             $return['src']          = $fileItem['src']; | ||||
|             $return['name']         = $fileName; | ||||
|             $fileItem['updated_at'] = date('Y-m-d H:i:s'); | ||||
|             return $this->json(200, '该文件已存在 路径为:'.$fileItem['path'], $return); | ||||
|         } | ||||
|         if ($this->validate->checkFile($file)) { | ||||
|             try { | ||||
|                 if (!$this->uploadPathIsWritable) { | ||||
|                     throw new \Exception('上传文件夹需要写入权限'); | ||||
|                 } | ||||
|                 $src            = Filesystem::putFile(date('Ymd'), $file, 'uniqid'); | ||||
|                 $src            = $this->uploadPath.$this->DIRECTORY_SEPARATOR.$src; | ||||
|                 $return['src']  = $src; | ||||
|                 $return['name'] = $fileName; | ||||
|                 File::add($file, $src, $md5, 'file');    //加入上传文件表
 | ||||
|             } catch (\Exception $e) { | ||||
|                 return $this->json(1, $e->getMessage()); | ||||
|             } | ||||
|             return $this->json(0, 'ok', $return); | ||||
|         } else { | ||||
|             $errorMsg = Lang::get($this->validate->getError()); | ||||
|             return $this->json(1, $errorMsg); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     //图片上传(通用)
 | ||||
|     public function image() | ||||
|     { | ||||
|         // 字段名 image-image避免冲突 layui组件自动生成的隐藏file input框中name容易重名冲突
 | ||||
|         $image   = request()->file('image_image'); | ||||
|         $md5     = $image->md5();//文件md5
 | ||||
|         $type    = request()->param('type/s', ''); | ||||
|         $path    = request()->param('path/s', '');//指定路径 基于public下  若为空则默认
 | ||||
|         $hasPath = !empty($path); | ||||
| 
 | ||||
|         if ($this->validate->checkImage($image)) { | ||||
|             $info   = @getimagesize($image->getPathname()); | ||||
|             $width  = $info[0] ?? 0; | ||||
|             $height = $info[1] ?? 0; | ||||
| 
 | ||||
|             // 海报限制大小 750 * 1334
 | ||||
|             switch ($type) { | ||||
|                 case 'porter': | ||||
|                     if ($width != 750 || $height != 1334) { | ||||
|                         return $this->json(1, '海报背景图尺寸大小固定为:750 * 1334'); | ||||
|                     } | ||||
|                     break; | ||||
|             } | ||||
| 
 | ||||
|             if ($fileItem = File::where('md5', $md5)->find()) { | ||||
|                 $return['src']          = $fileItem['src']; | ||||
|                 $fileItem['updated_at'] = date('Y-m-d H:i:s'); | ||||
| 
 | ||||
|                 return $this->json(200, '该文件已存在 路径为:'.$fileItem['path'], $return); | ||||
|             } | ||||
| 
 | ||||
|             try { | ||||
|                 if (!$this->uploadPathIsWritable) { | ||||
|                     throw new \Exception('上传文件夹需要写入权限'); | ||||
|                 } | ||||
| 
 | ||||
|                 // 去除以/storage/开头的部分  如/storage/20210808/test => 20210808/test
 | ||||
|                 if (strpos(trim($path, $this->DIRECTORY_SEPARATOR), \app\model\Attachment::ROOT_NAME.$this->DIRECTORY_SEPARATOR) === 0) { | ||||
|                     $path = substr(trim($path, $this->DIRECTORY_SEPARATOR), strlen(\app\model\Attachment::ROOT_NAME.$this->DIRECTORY_SEPARATOR)); | ||||
|                 } | ||||
| 
 | ||||
|                 $datePath = $hasPath ? $path : date('Ymd');//自定义目录
 | ||||
|                 $datePath = ($datePath == $this->DIRECTORY_SEPARATOR."storage") ? $this->DIRECTORY_SEPARATOR : $datePath; | ||||
|                 $src      = Filesystem::putFile($datePath, $image, 'uniqid'); | ||||
| 
 | ||||
|                 $src      = $this->uploadPath . $this->DIRECTORY_SEPARATOR . $src; | ||||
|                 $suffix   = strtolower($image->getOriginalExtension()); | ||||
|                 if ($suffix == 'gif') { | ||||
|                     $return['thumb_src'] = $src;    //TODO获取GIF缩略图
 | ||||
|                 } else { | ||||
|                     $return['thumb_src'] = Image::getThumb($src, 100, 100, TImage::THUMB_SCALING);   //上传返回缩略图宽度为100
 | ||||
|                 } | ||||
|                 $return['src'] = $src; | ||||
|                 if ($this->isCompress) { | ||||
|                     Image::resize($src); | ||||
|                 } | ||||
|                 File::add($image, $src, $md5);    //加入上传文件表
 | ||||
|             } catch (\Exception $e) { | ||||
|                 return $this->json(1, $e->getMessage()); | ||||
|             } | ||||
|             return $this->json(0, 'ok', $return); | ||||
|         } else { | ||||
|             $errorMsg = Lang::get($this->validate->getError()); | ||||
|             return $this->json(1, $errorMsg); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     //富文本编辑器商城图片
 | ||||
|     public function wangImage() | ||||
|     { | ||||
| 
 | ||||
|         $imageArr = request()->file('wang_img'); // 该方式,前端js上传方法中字段名称必须以数组形式传参 如 wang_img[] = 值
 | ||||
|         $errno    = 0; | ||||
|         $data     = []; | ||||
| 
 | ||||
|         if (!$this->uploadPathIsWritable) { | ||||
|             $errno  = 1; | ||||
|             $data[] = '上传文件夹需要写入权限'; | ||||
|         } else { | ||||
|             foreach ($imageArr as $image) { | ||||
|                 $md5 = $image->md5();//文件md5
 | ||||
|                 if ($fileItem = File::where('md5', $md5)->find()) { | ||||
|                     $return['src']          = $fileItem['src']; | ||||
|                     $fileItem['updated_at'] = date('Y-m-d H:i:s'); | ||||
| 
 | ||||
|                     $data[] = $fileItem['src']; | ||||
|                     $fileItem->save(); | ||||
|                     continue; | ||||
|                 } | ||||
| 
 | ||||
|                 if ($this->validate->checkImage($image)) { | ||||
|                     $src    = Filesystem::putFile(date('Ymd'), $image, 'uniqid'); | ||||
|                     $src    = $this->uploadPath.$this->DIRECTORY_SEPARATOR.$src; | ||||
|                     $data[] = $src; | ||||
|                     if ($this->isCompress) { | ||||
|                         Image::resize($src); | ||||
|                     } | ||||
|                     File::add($image, $src, $md5);    //加入上传文件表
 | ||||
|                 } else { | ||||
|                     $errno  = 1; | ||||
|                     $data   = []; | ||||
|                     $data[] = Lang::get($this->validate->getError()); | ||||
|                     break; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         $return['errno'] = $errno; | ||||
|         $return['data']  = $data; | ||||
|         return json($return); | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,24 @@ | |||
| <?php | ||||
| // 事件定义文件
 | ||||
| return [ | ||||
|     //事件标识
 | ||||
|     'bind'      => [ | ||||
| //        'UserLogin' => 'app\event\UserLogin',
 | ||||
|     ], | ||||
| 
 | ||||
|     //监听事件
 | ||||
|     'listen'    => [ | ||||
|         'AppInit'  => [], | ||||
|         'HttpRun'  => [], | ||||
|         'HttpEnd'  => [], | ||||
|         'LogLevel' => [], | ||||
|         'LogWrite' => [], | ||||
|     ], | ||||
| 
 | ||||
|     //订阅事件
 | ||||
|     'subscribe' => [ | ||||
|         'app\subscribe\Spu', | ||||
|         'app\subscribe\Order', | ||||
|         'app\subscribe\Coupon', | ||||
|     ], | ||||
| ]; | ||||
|  | @ -0,0 +1,10 @@ | |||
| <?php | ||||
| 
 | ||||
| namespace app\exception; | ||||
| 
 | ||||
| use Exception; | ||||
| 
 | ||||
| class ApiRedirectException extends Exception | ||||
| { | ||||
| 
 | ||||
| } | ||||
|  | @ -0,0 +1,8 @@ | |||
| <?php | ||||
| 
 | ||||
| namespace app\exception; | ||||
| 
 | ||||
| class RepositoryException extends \Exception | ||||
| { | ||||
| 
 | ||||
| } | ||||
|  | @ -0,0 +1,7 @@ | |||
| <?php | ||||
| namespace app\exception; | ||||
| 
 | ||||
| class TraitException extends \Exception | ||||
| { | ||||
| 
 | ||||
| } | ||||
|  | @ -0,0 +1,37 @@ | |||
| <?php | ||||
| namespace app\job; | ||||
| 
 | ||||
| use app\repository\AccountRepository; | ||||
| use think\queue\Job; | ||||
| 
 | ||||
| class NotifySms | ||||
| { | ||||
|     public function fire(Job $job, $data){ | ||||
| 
 | ||||
|         //短信通知列表
 | ||||
|         if ($data) { | ||||
|             foreach ($data as $item) { | ||||
|                 echo sprintf("短信发送成功!phone:%s time:%s \n", $item['mobile'], date('Y-m-d H:i:s')); | ||||
|                 sleep(mt_rand(1,3)); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
| //        if ($job->attempts() > 3) {
 | ||||
| //            //通过这个方法可以检查这个任务已经重试了几次了
 | ||||
| //            echo sprintf('发送短信失败过多');
 | ||||
| //        }
 | ||||
| 
 | ||||
| 
 | ||||
|         //如果任务执行成功后 记得删除任务,不然这个任务会重复执行,直到达到最大重试次数后失败后,执行failed方法
 | ||||
|         $job->delete(); | ||||
| 
 | ||||
|         // 也可以重新发布这个任务
 | ||||
| //        $job->release(3); //$delay为延迟时间
 | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     public function failed($data){ | ||||
| 
 | ||||
|         // ...任务达到最大重试次数后,失败了
 | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,10 @@ | |||
| <?php | ||||
| // 全局中间件定义文件
 | ||||
| return [ | ||||
|     // 全局请求缓存
 | ||||
|     // \think\middleware\CheckRequestCache::class,
 | ||||
|     // 多语言加载
 | ||||
|     //\think\middleware\LoadLangPack::class,
 | ||||
|     // Session初始化
 | ||||
|     \think\middleware\SessionInit::class, | ||||
| ];   | ||||
|  | @ -0,0 +1,35 @@ | |||
| <?php | ||||
| namespace app\middleware; | ||||
| 
 | ||||
| use Closure; | ||||
| use app\service\Jwt as JwtService; | ||||
| 
 | ||||
| /** | ||||
|  * API登录认证(需要先调用JWT解析用户信息) | ||||
|  * Class ApiLogin | ||||
|  * @package app\middleware | ||||
|  */ | ||||
| class ApiLogin | ||||
| { | ||||
|     public function handle($request, Closure $next) { | ||||
|         $authorization = $request->authorization ?? ''; | ||||
|         if (empty($authorization)) { | ||||
|             return json(['code' => 6001, 'msg' => '请填写token']); | ||||
|         } | ||||
|         if (!JwtService::validate($authorization)) { | ||||
|             return json(['code' => 6001, 'msg' => 'token验证失败或已失效']); | ||||
|         } | ||||
| 
 | ||||
|         $userInfo = $request->user ?? []; | ||||
|         if (!isset($userInfo['user_id']) || empty($userInfo['user_id'])) { | ||||
|             return json(['code' => 6001, 'msg' => 'token已失效']); | ||||
|         } | ||||
| 
 | ||||
|         // 自定义过期时间校验。
 | ||||
|         if(isset($userInfo['expire_time']) && time() >= $userInfo['expire_time']) { | ||||
|             return json(['code' => 6001, 'msg' => 'token已失效']); | ||||
|         } | ||||
| 
 | ||||
|         return $next($request); | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,50 @@ | |||
| <?php | ||||
| 
 | ||||
| namespace app\middleware; | ||||
| 
 | ||||
| use Closure; | ||||
| use app\model\AuthRule; | ||||
| use tauthz\facade\Enforcer; | ||||
| use think\facade\Cache; | ||||
| 
 | ||||
| class Auth | ||||
| { | ||||
|     public function handle($request, Closure $next) | ||||
|     { | ||||
|         $auth = session('auth'); | ||||
|         if (!$auth) { | ||||
|             return redirect(url('manager.login/index')); | ||||
|         } | ||||
| 
 | ||||
|         $module = 'manager'; | ||||
|         $controller = unCamelize(request()->controller()); | ||||
|         $controller = str_replace($module.'.', '', $controller); | ||||
|         $controller = str_replace('.', '/', $controller);//兼容多层级目录  如 /manager/test/article/index
 | ||||
|         $action     = unCamelize(request()->action()); | ||||
|         $roles = Enforcer::getRolesForUser($auth['user_id']); | ||||
| //        $per = Enforcer::getPermissionsForUser($roles[0]);
 | ||||
| //        var_dump($controller);
 | ||||
| //        var_dump($action);
 | ||||
| //        var_dump($roles);
 | ||||
| //        var_dump($per);
 | ||||
| //        exit;
 | ||||
| //        return $next($request);//暂时停用权限校验
 | ||||
| //        var_dump($controller);
 | ||||
| //        var_dump($action);
 | ||||
| //        var_dump(Enforcer::hasPermissionForUser(1, $controller, 'group-make'));exit;
 | ||||
| 
 | ||||
|         foreach ($roles as $role) { | ||||
|             // TODO 关注批量权限检测是否可用
 | ||||
|             //只需要有一个角色具有权限就放通 此处第一个参数不是用户 而是 角色 此方法是检测用户|角色是否具有某个权限的公用方法
 | ||||
|             if (Enforcer::hasPermissionForUser($role, $controller, $action)) { | ||||
|                 return $next($request); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         if (request()->isAjax()) { | ||||
|             return json(['code' => 4001, 'msg' => '没有权限']); | ||||
|         } else { | ||||
|             return view('/manager/error/jump')->assign('msg', '很抱歉,您还没有权限,请联系管理员开通!'); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,56 @@ | |||
| <?php | ||||
| namespace app\middleware; | ||||
| 
 | ||||
| use Closure; | ||||
| use think\Request; | ||||
| 
 | ||||
| /** | ||||
|  * CSRF校验 | ||||
|  */ | ||||
| class Csrf | ||||
| { | ||||
|     public function handle(Request $request, Closure $next) | ||||
|     { | ||||
|         if($request->isPost()){ | ||||
|             $check = $request->checkToken(); | ||||
|             if(false === $check) { | ||||
| //                return $this->csrfError($request);
 | ||||
|             } | ||||
|         } | ||||
|         return $next($request); | ||||
|     } | ||||
| 
 | ||||
|     protected function csrfError($request, $msg = '非法请求, 用户身份认证失败!') | ||||
|     { | ||||
|         if($request->isAjax()) { | ||||
|             return json(['code' => 401, 'msg' => $msg], 200); | ||||
|         } else { | ||||
|             $referer = $_SERVER['HTTP_REFERER'] ?? null; | ||||
|             if (empty($referer)) { | ||||
|                 $url = '/'; | ||||
|             } else { | ||||
|                 $domain = $request->domain(); | ||||
|                 $urlInfo = parse_url($referer); | ||||
|                 $scheme = $urlInfo['scheme'] ?? ''; | ||||
|                 $requestSrc = ''; | ||||
|                 if (!empty($scheme)) { | ||||
|                     $requestSrc = $scheme.'://'.($urlInfo['host'] ?? ''); | ||||
|                 } | ||||
|                 if($domain != $requestSrc) { | ||||
|                     $url = '/'; | ||||
|                 } else { | ||||
|                     $url = 'javascript:history.back(-1);'; | ||||
|                 } | ||||
|             } | ||||
|             $errorData = [ | ||||
|                 'code'=> 401, | ||||
|                 'msg' => $msg, | ||||
|                 'data' => [], | ||||
|                 'wait' => 5, | ||||
|                 'url' => $url | ||||
|             ]; | ||||
|             return view('error/400', $errorData); | ||||
|             // 返回401视图 response type has html、json、jsonp、xml、file、view、redirect
 | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,37 @@ | |||
| <?php | ||||
| namespace app\middleware; | ||||
| 
 | ||||
| use Closure; | ||||
| use app\service\Jwt as JwtService; | ||||
| 
 | ||||
| /** | ||||
|  * 根据TOKEN解析用户信息 | ||||
|  * | ||||
|  * Class JWT | ||||
|  * @package app\middleware | ||||
|  */ | ||||
| class JWT | ||||
| { | ||||
|     public function handle($request, Closure $next) | ||||
|     { | ||||
|         $authorization = $request->header('Authorization'); | ||||
|         $tokenStr      = $request->param('token/s', ''); | ||||
| 
 | ||||
|         if ($authorization) { | ||||
|             $authorization = str_replace('Bearer ', '', $authorization); | ||||
|         } | ||||
| 
 | ||||
|         //优先取header中token
 | ||||
|         $token      = $authorization ?: $tokenStr; | ||||
|         $userInfo   = []; | ||||
|         if (!empty($token)) { | ||||
|             $userInfo = JwtService::parse($token);//token中携带的简易用户信息
 | ||||
|         } | ||||
| 
 | ||||
|         $request->user          = $userInfo; | ||||
|         // authorization用于移交ApiLogin认证
 | ||||
|         $request->authorization = $token; | ||||
| 
 | ||||
|         return $next($request); | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,25 @@ | |||
| <?php | ||||
| 
 | ||||
| namespace app\middleware; | ||||
| 
 | ||||
| use Closure; | ||||
| use think\Request; | ||||
| 
 | ||||
| /** | ||||
|  * 前台登录验证 | ||||
|  * | ||||
|  * Class Login | ||||
|  * @package app\middleware | ||||
|  */ | ||||
| class Login | ||||
| { | ||||
|     public function handle(Request  $request, Closure $next) | ||||
|     { | ||||
|         if (!session('frontend_auth')) { | ||||
|             $url = $request->url(true); | ||||
|             return redirect(url('login/index').'?url='.urlencode($url)); | ||||
|         } | ||||
| 
 | ||||
|         return $next($request); | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,11 @@ | |||
| <?php | ||||
| 
 | ||||
| namespace app\model; | ||||
| 
 | ||||
| use Exception; | ||||
| use think\exception\ValidateException; | ||||
| 
 | ||||
| class Account extends Base | ||||
| { | ||||
| 
 | ||||
| } | ||||
|  | @ -0,0 +1,69 @@ | |||
| <?php | ||||
| 
 | ||||
| namespace app\model; | ||||
| 
 | ||||
| use Exception; | ||||
| use think\exception\ValidateException; | ||||
| 
 | ||||
| class Attachment extends Base | ||||
| { | ||||
|     protected $name = 'file'; | ||||
| 
 | ||||
|     public const TYPE_DIR   = 'dir';//目录
 | ||||
|     public const TYPE_IMG   = 'image';//图片
 | ||||
|     public const TYPE_VIDEO = 'video';//视频
 | ||||
|     public const TYPE_FILE  = 'file';//文件
 | ||||
| 
 | ||||
|     public const ROOT_NAME = 'storage';//根目录名称
 | ||||
|     public const ROOT_PATH = "/".self::ROOT_NAME;//文件存放根路径
 | ||||
| 
 | ||||
|     public static function list(): array | ||||
|     { | ||||
|         $where[] = ['src', 'like', '%'.self::ROOT_PATH."/"]; | ||||
|         return self::findList($where); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 路径目录处理  会逐级检查路径上所有目录是否存在 不存在的目录全部创建[创建到数据库] | ||||
|      * | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public static function pathDirHandle(string $path): bool | ||||
|     { | ||||
|         $pathInfo       = pathinfo($path); | ||||
|         $fullPath = isset($pathInfo['extension']) ? $pathInfo['dirname'] : $pathInfo['dirname']."/".$pathInfo['filename']; | ||||
| 
 | ||||
|         // 全路径 如 /storage/dir1/dir2/dir3/dir4/  注意前后都有/
 | ||||
|         $fullPath = $fullPath."/"; | ||||
| 
 | ||||
|         $pathArr = explode("/", trim($fullPath, "/")); | ||||
| 
 | ||||
|         $insert = []; | ||||
|         $now    = date('Y-m-d H:i:s'); | ||||
|         try { | ||||
|             // 检测全路径上所有目录是否存在 不存在则创建
 | ||||
|             foreach ($pathArr as $k => $p) { | ||||
|                 $currentPath = '/'; | ||||
|                 $currentArr  = array_slice($pathArr, 0, $k); | ||||
|                 if ($currentArr) { | ||||
|                     $currentPath = "/".implode('/', $currentArr)."/"; | ||||
|                 } | ||||
|                 if ($currentPath != '/' && self::where('path', $currentPath)->where('name', $p)->count() <= 0) { | ||||
|                     $arr               = []; | ||||
|                     $arr['path']       = $currentPath; | ||||
|                     $arr['name']       = $p; | ||||
|                     $arr['created_at'] = $now; | ||||
|                     $arr['is_dir']     = self::COMMON_ON; | ||||
|                     $arr['type']       = self::TYPE_DIR; | ||||
| 
 | ||||
|                     $insert[] = $arr; | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             (new self())->saveAll($insert); | ||||
|             return true; | ||||
|         } catch (Exception $e) { | ||||
|             return false; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,388 @@ | |||
| <?php | ||||
| 
 | ||||
| namespace app\model; | ||||
| 
 | ||||
| use Exception; | ||||
| use think\Collection; | ||||
| use think\db\exception\DataNotFoundException; | ||||
| use think\db\exception\DbException; | ||||
| use think\db\exception\ModelNotFoundException; | ||||
| use think\Model; | ||||
| use think\Paginator; | ||||
| 
 | ||||
| class Base extends Model | ||||
| { | ||||
|     protected $autoWriteTimestamp = false; | ||||
| 
 | ||||
|     // 布尔值数字关系
 | ||||
|     public const BOOL_FALSE = 0; | ||||
|     public const BOOL_TRUE  = 1; | ||||
| 
 | ||||
|     public const COMMON_ON  = 1; | ||||
|     public const COMMON_OFF = 0; | ||||
| 
 | ||||
|     //根据Id列表获取列表
 | ||||
|     public static function getListByIds($ids) | ||||
|     { | ||||
|         if (count($ids) == 0 || empty($ids)) { | ||||
|             return []; | ||||
|         } | ||||
|         return self::where('id', 'in', $ids)->select()->toArray(); | ||||
|     } | ||||
| 
 | ||||
|     //根据ID获取单条数据
 | ||||
|     public static function getById($id) | ||||
|     { | ||||
|         if ($id <= 0) { | ||||
|             return []; | ||||
|         } | ||||
|         return self::where('id', $id)->findOrEmpty()->toArray(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 通过ID查找记录 | ||||
|      * | ||||
|      * @param  int  $id | ||||
|      * @param  array  $fields | ||||
|      * @param  callable|null  $call | ||||
|      * @return array|Model|null | ||||
|      * @throws DataNotFoundException | ||||
|      * @throws DbException | ||||
|      * @throws ModelNotFoundException | ||||
|      */ | ||||
|     public static function findById(int $id, array $fields = [], callable $call = null) | ||||
|     { | ||||
|         $q = self::when(!empty($fields), function ($q) use ($fields) { | ||||
|             $q->field($fields); | ||||
|         }); | ||||
|         if ($call !== null) { | ||||
|             $q = $call($q); | ||||
|         } | ||||
|         return $q->find($id); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 查找单个记录 | ||||
|      * | ||||
|      * @param  array  $where | ||||
|      * @param  array  $fields | ||||
|      * @param  callable|null  $call | ||||
|      * @return array|Model|null | ||||
|      * @throws DataNotFoundException | ||||
|      * @throws DbException | ||||
|      * @throws ModelNotFoundException | ||||
|      */ | ||||
|     public static function findOne(array $where = [], array $fields = [], callable $call = null) | ||||
|     { | ||||
|         $q = self::when(!empty($fields), function ($q) use ($fields) { | ||||
|             $q->field($fields); | ||||
|         })->where($where); | ||||
| 
 | ||||
|         if ($call !== null) { | ||||
|             $q = $call($q); | ||||
|         } | ||||
|         return $q->find(); | ||||
|     } | ||||
| 
 | ||||
|     //根据ID更新数据
 | ||||
|     public static function updateById($id, $data) | ||||
|     { | ||||
|         return self::where('id', $id)->update($data); | ||||
|     } | ||||
| 
 | ||||
|     //根据where条件和排序获取记录
 | ||||
|     public static function getListByWhereAndOrder($where, $order, $limit = 1) | ||||
|     { | ||||
|         return self::where($where) | ||||
|             ->order($order) | ||||
|             ->limit($limit) | ||||
|             ->select() | ||||
|             ->toArray(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 根据ID删除数据 | ||||
|      * | ||||
|      * @param  int  $id | ||||
|      * @return bool | ||||
|      */ | ||||
|     public static function deleteById(int $id): bool | ||||
|     { | ||||
|         return self::where('id', $id)->delete(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 根据ID列表删除数据 | ||||
|      * | ||||
|      * @param  array  $ids | ||||
|      * @return bool | ||||
|      */ | ||||
|     public static function deleteByIds(array $ids): bool | ||||
|     { | ||||
|         return self::whereIn('id', $ids)->delete(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 排序 | ||||
|      * | ||||
|      * @param  int  $id  调整ID | ||||
|      * @param  string  $type  本次操作类型 向上、向下 | ||||
|      * @param  int  $num  移动位数 | ||||
|      * @param  string  $listType  列表的排序方式 默认为降序 | ||||
|      * @param  array  $where  额外条件 如限制在指定分类下 where[] = ['category_id', '=', 6] | ||||
|      * @return array | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public static function sort(int $id, string $type, int $num = 1, string $listType = 'desc', array $where = []): array | ||||
|     { | ||||
|         $res  = ['code' => 0, 'msg' => 'success']; | ||||
|         $item = self::getById($id); | ||||
| 
 | ||||
|         if (!$item) { | ||||
|             $res['code'] = 1; | ||||
|             $res['msg']  = '记录不存在'; | ||||
|             return $res; | ||||
|         } | ||||
| 
 | ||||
|         if ($listType == 'desc') { | ||||
|             if ($type == 'down') { | ||||
|                 $where[] = ['sort', '<', $item['sort']]; | ||||
|                 $order   = "sort desc"; | ||||
|             } else { | ||||
|                 $where[] = ['sort', '>', $item['sort']]; | ||||
|                 $order   = "sort asc"; | ||||
|             } | ||||
|         } else { | ||||
|             if ($type == 'up') { | ||||
|                 $where[] = ['sort', '<', $item['sort']]; | ||||
|                 $order   = "sort desc"; | ||||
|             } else { | ||||
|                 $where[] = ['sort', '>', $item['sort']]; | ||||
|                 $order   = "sort asc"; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         $forSortItems = self::getListByWhereAndOrder($where, $order, $num); | ||||
|         if (!empty($forSortItems)) { | ||||
|             $updateData   = []; | ||||
|             $forSortCount = count($forSortItems); | ||||
|             for ($i = 0; $i < $forSortCount; $i++) { | ||||
|                 if ($i == 0) { | ||||
|                     $updateData[] = [ | ||||
|                         'id'   => $forSortItems[$i]['id'], | ||||
|                         'sort' => $item['sort'] | ||||
|                     ]; | ||||
|                 } else { | ||||
|                     $updateData[] = [ | ||||
|                         'id'   => $forSortItems[$i]['id'], | ||||
|                         'sort' => $forSortItems[$i - 1]['sort'] | ||||
|                     ]; | ||||
|                 } | ||||
|             } | ||||
|             $updateData[] = [ | ||||
|                 'id'   => $item['id'], | ||||
|                 'sort' => $forSortItems[$i - 1]['sort'] | ||||
|             ]; | ||||
| 
 | ||||
|             if (!empty($updateData)) { | ||||
|                 $obj = new static(); | ||||
|                 $obj->saveAll($updateData); | ||||
|                 return $res; | ||||
|             } | ||||
|         } | ||||
|         $res['code'] = 1; | ||||
|         $res['msg']  = '无需调整'; | ||||
|         return $res; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 查询列表 [带分页 适用于后台] | ||||
|      * | ||||
|      * @param  array  $data  查询数据 格式如下 | ||||
|      * [ | ||||
|      *   'fields' => ['id','title','desc'],//查询字段
 | ||||
|      *   'where'  => [ | ||||
|      *                  ['name', 'like', '%thinkphp%'], | ||||
|      *                  ['title', 'like', '%thinkphp%'], | ||||
|      *                  ['id', '>', 0], | ||||
|      *                  ['status', '=', 1], | ||||
|      *               ],//查询条件
 | ||||
|      *   'order'  => ['order'=>'desc','id'=>'desc'],//排序
 | ||||
|      *   'size' => 50,//每页数量
 | ||||
|      * ] | ||||
|      * @param  array  $pageParams  分页参数 具体参考:https://www.kancloud.cn/manual/thinkphp6_0/1037638 | ||||
|      * @param  callable|null  $callback  复杂查询条件 使用闭包查询 此时建议data留空 | ||||
|      * @return Paginator | ||||
|      * @throws DbException | ||||
|      */ | ||||
|     public static function findListWithPaginate(array $data = [], array $pageParams = [], callable $callback = null): Paginator | ||||
|     { | ||||
|         $q      = new static(); | ||||
|         $fields = isset($data['fields']) && !empty($data['fields']) ? $data['fields'] : []; | ||||
|         $where  = isset($data['where']) && !empty($data['where']) ? $data['where'] : []; | ||||
|         $order  = isset($data['order']) && !empty($data['order']) ? $data['order'] : []; | ||||
|         $limit  = $data['size'] ?? 20; | ||||
| 
 | ||||
|         if (count($where)) { | ||||
|             $q = $q->where($where); | ||||
|         } | ||||
| 
 | ||||
|         if (count($fields)) { | ||||
|             $q = $q->field($fields); | ||||
|         } | ||||
| 
 | ||||
|         if ($callback) { | ||||
|             $q = $callback($q); | ||||
|         } | ||||
| 
 | ||||
|         if (count($order)) { | ||||
|             $q = $q->order($order); | ||||
|         } | ||||
| 
 | ||||
|         $pageParams['list_rows'] = $limit; | ||||
| 
 | ||||
|         return $q->paginate($pageParams); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 查询列表 | ||||
|      * | ||||
|      * @param  array  $simpleWhere  简易查询条件 | ||||
|      * @param  array  $fields  查询字段 []表示全部 | ||||
|      * @param  int  $page  默认第一页 0不限制 | ||||
|      * @param  int  $limit  限制条数 0不限制 | ||||
|      * @param  callable|null  $callback  复杂的条件 使用闭包查询 | ||||
|      * @param  array  $orders 键值对,排序 | ||||
|      * @return array | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public static function findList(array $simpleWhere = [], array $fields = [], int $page = 1, int $limit = 0, callable $callback = null, array $orders = []): array | ||||
|     { | ||||
|         $q    = new static(); | ||||
|         $data = [ | ||||
|             'total'   => 0, | ||||
|             'current' => $page, | ||||
|             'size'    => $limit, | ||||
|             'list'    => new Collection(), | ||||
|         ]; | ||||
| 
 | ||||
|         if (count($fields)) { | ||||
|             $q = $q->field($fields); | ||||
|         } | ||||
| 
 | ||||
|         if (count($simpleWhere)) { | ||||
|             $q = $q->where($simpleWhere); | ||||
|         } | ||||
| 
 | ||||
|         if ($callback) { | ||||
|             $q = $callback($q); | ||||
|         } | ||||
| 
 | ||||
|         $data['total'] = $q->count(); | ||||
| 
 | ||||
|         if ($data['total']) { | ||||
|             if (count($orders)) { | ||||
|                 $q = $q->order($orders); | ||||
|             } | ||||
|             if ($limit) { | ||||
|                 if ($page) { | ||||
|                     $q = $q->page($page); | ||||
|                 } | ||||
|                 $q = $q->limit($limit); | ||||
|             } | ||||
| 
 | ||||
|             $data['list'] = $q->select(); | ||||
|         } | ||||
| 
 | ||||
|         return $data; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 获取路径 | ||||
|      * | ||||
|      * @param  int  $pid | ||||
|      * @return string | ||||
|      * @throws DataNotFoundException | ||||
|      * @throws DbException | ||||
|      * @throws ModelNotFoundException | ||||
|      */ | ||||
|     public static function getPath(int $pid): string | ||||
|     { | ||||
|         if ($pid == 0) { | ||||
|             $path = ',0,'; | ||||
|         } else { | ||||
|             $parent = self::findById($pid); | ||||
|             if (empty($parent)) { | ||||
|                 $path = ',0,'; | ||||
|             } else { | ||||
|                 $path = $parent['path'].$parent['id'].','; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         return $path; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 刷新路径 | ||||
|      * | ||||
|      * @param  int  $pid | ||||
|      * @param  array  $data  默认全部 若data不为空 至少包含[id,path, $pidField] | ||||
|      * @param  string  $pidField  父级ID字段名 默认 pid | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public static function refreshPath(int $pid = 0, array $data = [], string $pidField = 'pid') | ||||
|     { | ||||
|         $data           = !empty($data) ? $data : self::column('id,path,'.$pidField); | ||||
|         $updateAllPaths = []; | ||||
|         self::recursionPath($pid, $data, $updateAllPaths); | ||||
| 
 | ||||
|         (new static())->saveAll($updateAllPaths); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 获取递归最新路径 | ||||
|      * | ||||
|      * @param  int  $pid | ||||
|      * @param  array  $data  全部数据 尽量传全部数据 | ||||
|      * @param  array  $paths | ||||
|      */ | ||||
|     public static function recursionPath(int $pid, array $data, array &$paths = []) | ||||
|     { | ||||
|         foreach ($data as $k => $v) { | ||||
|             if ($pid == $v['pid']) { | ||||
|                 $arr       = []; | ||||
|                 $arr['id'] = $v['id']; | ||||
|                 if ($pid == 0) { | ||||
|                     $arr['path'] = ',0,'; | ||||
|                 } else { | ||||
|                     $arr['path'] = $paths[$v['pid']]['path'].$v['pid'].','; | ||||
|                 } | ||||
|                 $paths[$v['id']] = $arr; | ||||
| 
 | ||||
|                 unset($data[$k]); | ||||
| 
 | ||||
|                 self::recursionPath($v['id'], $data, $paths); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 获取所有后代ID[包含孙级]  仅对拥有path字段的表生效 | ||||
|      * | ||||
|      * @param  int  $id | ||||
|      * @return array | ||||
|      * @throws DataNotFoundException | ||||
|      * @throws DbException | ||||
|      * @throws ModelNotFoundException | ||||
|      */ | ||||
|     public static function getAllChildrenIds(int $id): array | ||||
|     { | ||||
|         $item = self::find($id); | ||||
|         if ($item && isset($item['path'])) { | ||||
|             $path = $item['path'].$id.','; | ||||
|             return self::where('path', 'like', $path.'%')->column('id'); | ||||
|         } else { | ||||
|             return []; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,11 @@ | |||
| <?php | ||||
| 
 | ||||
| namespace app\model; | ||||
| 
 | ||||
| class Business extends Base | ||||
| { | ||||
|     const state_reviewing = 0; | ||||
|     const state_on        = 1; | ||||
|     const state_off       = 2; | ||||
| 
 | ||||
| } | ||||
|  | @ -0,0 +1,16 @@ | |||
| <?php | ||||
| 
 | ||||
| namespace app\model; | ||||
| 
 | ||||
| //商家和用户的链接表
 | ||||
| class BusinessFlow extends Base | ||||
| { | ||||
|     public function account() | ||||
|     { | ||||
|         return $this->hasOne(Account::class,"user_code","user_code"); | ||||
|     } | ||||
|     public function business() | ||||
|     { | ||||
|         return $this->hasOne(Business::class,"code","business_code"); | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,66 @@ | |||
| <?php | ||||
| 
 | ||||
| namespace app\model; | ||||
| 
 | ||||
| use think\Collection; | ||||
| use think\db\exception\DataNotFoundException; | ||||
| use think\db\exception\DbException; | ||||
| use think\db\exception\ModelNotFoundException; | ||||
| 
 | ||||
| /** | ||||
|  * 商家分类 | ||||
|  * Class Disease | ||||
|  * @package app\model | ||||
|  */ | ||||
| class Category extends Base | ||||
| { | ||||
|     /** | ||||
|      * 根据父级ID 获取病种列表 | ||||
|      * | ||||
|      * @param  int  $pid | ||||
|      * @param  string[]  $fields | ||||
|      * @return Disease[]|array|Collection | ||||
|      * @throws DataNotFoundException | ||||
|      * @throws DbException | ||||
|      * @throws ModelNotFoundException | ||||
|      */ | ||||
|     public static function getListByPid(int $pid = 0, array $fields = ['pid', 'name', 'id']) | ||||
|     { | ||||
|         return self::where('pid', $pid)->order('id', 'desc')->field($fields)->select(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 获取全部病种列表 | ||||
|      * | ||||
|      * @return Disease[]|array|Collection | ||||
|      * @throws DataNotFoundException | ||||
|      * @throws DbException | ||||
|      * @throws ModelNotFoundException | ||||
|      */ | ||||
|     public static function getList() | ||||
|     { | ||||
|         return self::field('id,pid,name,commision')->order('id', 'desc')->order('id')->select(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 病种 xmSelect json数据 | ||||
|      * | ||||
|      * @param  int  $pid | ||||
|      * @param  array  $selected | ||||
|      * @param  array  $disabled | ||||
|      * @return array|Disease[]|Collection | ||||
|      * @throws DataNotFoundException | ||||
|      * @throws DbException | ||||
|      * @throws ModelNotFoundException | ||||
|      */ | ||||
|     public static function diseaseXmJson(int $pid = 0, array $selected = [], array $disabled = []) | ||||
|     { | ||||
|         $list = self::getListByPid($pid); | ||||
|         foreach ($list as $k => $m) { | ||||
|             $list[$k]['selected'] = in_array($m['id'], $selected); | ||||
|             $list[$k]['disabled'] = in_array($m['id'], $disabled); | ||||
|         } | ||||
| 
 | ||||
|         return $list; | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,8 @@ | |||
| <?php | ||||
| namespace app\model; | ||||
| 
 | ||||
| class Comment extends Base | ||||
| { | ||||
|     //评论表
 | ||||
| 
 | ||||
| } | ||||
|  | @ -0,0 +1,8 @@ | |||
| <?php | ||||
| namespace app\model; | ||||
| 
 | ||||
| class CommentRule extends Base | ||||
| { | ||||
|     //评论规则表
 | ||||
| 
 | ||||
| } | ||||
|  | @ -0,0 +1,20 @@ | |||
| <?php | ||||
| 
 | ||||
| namespace app\model; | ||||
| 
 | ||||
| use think\Collection; | ||||
| use think\db\exception\DataNotFoundException; | ||||
| use think\db\exception\DbException; | ||||
| use think\db\exception\ModelNotFoundException; | ||||
| 
 | ||||
| /** | ||||
|  * 优惠券 | ||||
|  * Class Coupon | ||||
|  * @package app\model | ||||
|  */ | ||||
| class Coupon extends Base | ||||
| { | ||||
|     //是否验证
 | ||||
|     const is_verificated_on = 1;//1已验证
 | ||||
|     const is_verificated_off = 0;//0未验证
 | ||||
| } | ||||
|  | @ -0,0 +1,21 @@ | |||
| <?php | ||||
| 
 | ||||
| namespace app\model; | ||||
| 
 | ||||
| use think\Collection; | ||||
| use think\db\exception\DataNotFoundException; | ||||
| use think\db\exception\DbException; | ||||
| use think\db\exception\ModelNotFoundException; | ||||
| 
 | ||||
| /** | ||||
|  * 优惠券主表 | ||||
|  * Class CouponMain | ||||
|  * @package app\model | ||||
|  */ | ||||
| class CouponMain extends Base | ||||
| { | ||||
|         const status_on     = 0;//进行中
 | ||||
|         const status_off    = 1;//停止
 | ||||
|         const on_shelf_on   = 0;//上架状态
 | ||||
|         const on_shelf_off  = 1;//下架状态
 | ||||
| } | ||||
|  | @ -0,0 +1,18 @@ | |||
| <?php | ||||
| 
 | ||||
| namespace app\model; | ||||
| 
 | ||||
| use think\Collection; | ||||
| use think\db\exception\DataNotFoundException; | ||||
| use think\db\exception\DbException; | ||||
| use think\db\exception\ModelNotFoundException; | ||||
| 
 | ||||
| /** | ||||
|  * 优惠券类型 | ||||
|  * Class CouponType | ||||
|  * @package app\model | ||||
|  */ | ||||
| class CouponType extends Base | ||||
| { | ||||
| 
 | ||||
| } | ||||
|  | @ -0,0 +1,18 @@ | |||
| <?php | ||||
| 
 | ||||
| namespace app\model; | ||||
| 
 | ||||
| use think\Collection; | ||||
| use think\db\exception\DataNotFoundException; | ||||
| use think\db\exception\DbException; | ||||
| use think\db\exception\ModelNotFoundException; | ||||
| 
 | ||||
| /** | ||||
|  * 扣费记录 | ||||
|  * Class Deduction | ||||
|  * @package app\model | ||||
|  */ | ||||
| class Deduction extends Base | ||||
| { | ||||
| 
 | ||||
| } | ||||
|  | @ -0,0 +1,129 @@ | |||
| <?php | ||||
| 
 | ||||
| namespace app\model; | ||||
| 
 | ||||
| use app\service\AliOss; | ||||
| use Exception; | ||||
| use think\facade\Config; | ||||
| use think\Image; | ||||
| 
 | ||||
| class File extends Base | ||||
| { | ||||
|     const IMG   = 'image'; | ||||
|     const VIDEO = 'video'; | ||||
|     const FILE  = 'file'; | ||||
| 
 | ||||
|     //获取文件类型
 | ||||
|     public static function getTypes() | ||||
|     { | ||||
|         return [ | ||||
|             'image' => '图片', | ||||
|             'video' => '视频', | ||||
|             'file'  => '文件' | ||||
|         ]; | ||||
|     } | ||||
| 
 | ||||
|     //获取文件列表
 | ||||
|     public static function getList($type = '', $page = 1, $per = 20) | ||||
|     { | ||||
|         $limit = ($page - 1) * $per; | ||||
|         if ($type != '') { | ||||
|             if (!in_array($type, array_keys(self::getTypes()))) { | ||||
|                 return []; | ||||
|             } | ||||
|             $items = self::where('type', $type) | ||||
|                 ->order('id desc'); | ||||
|         } else { | ||||
|             $items = self::order('id desc'); | ||||
|         } | ||||
|         $items = $items->limit($limit, $per)->select()->toArray(); | ||||
|         foreach ($items as &$item) { | ||||
|             $item['sizeStr'] = sizeToStr($item['size']); | ||||
|         } | ||||
|         return $items; | ||||
|     } | ||||
| 
 | ||||
|     //获取分页列表
 | ||||
|     public static function getListPage($type = '', $per = 20) | ||||
|     { | ||||
|         if ($type != '') { | ||||
|             if (!in_array($type, array_keys(self::getTypes()))) { | ||||
|                 return []; | ||||
|             } | ||||
|             return self::where('type', $type) | ||||
|                 ->order('id desc') | ||||
|                 ->paginate([ | ||||
|                     'list_rows' => $per, | ||||
|                     'query'     => [ | ||||
|                         'type' => $type | ||||
|                     ] | ||||
|                 ], false); | ||||
|         } else { | ||||
|             return self::order('id desc') | ||||
|                 ->paginate([ | ||||
|                     'list_rows' => $per | ||||
|                 ], false); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     //添加,$w_h图片尺寸大小,单位像素,只对type=img时有效
 | ||||
|     public static function add($file, $src, $md5, $type = 'image') | ||||
|     { | ||||
|         $realPath = public_path().ltrim($src, '/'); | ||||
|         $oss      = false; | ||||
|         if (is_file($realPath) && $type == 'image') { | ||||
|             $img = Image::open($realPath); | ||||
|             list($w, $h) = $img->size(); | ||||
|             $w_h = $w.'px * '.$h.'px'; | ||||
|         } else { | ||||
|             $w_h = ''; | ||||
|         } | ||||
| 
 | ||||
|         $now = date('Y-m-d H:i:s'); | ||||
|         Attachment::pathDirHandle($src); | ||||
| 
 | ||||
|         Config::load('extra/base', 'base'); | ||||
|         $baseConfig = config('base'); | ||||
|         if (isset($baseConfig['oss']) && $baseConfig['oss']!= "false" && $baseConfig['oss']!== false) { | ||||
|             $ossObject = AliOss::instance(); | ||||
|             try { | ||||
|                 $pathInfo = pathinfo($src); | ||||
| 
 | ||||
|                 $ossConfig = AliOss::config(); | ||||
|                 $bucket = $ossConfig['bucket']; | ||||
|                 //是否存在
 | ||||
|                 if (!$ossObject->doesObjectExist($bucket, ltrim($src, '/'))) { | ||||
|                     //创建目录
 | ||||
|                     $ossObject->createObjectDir($bucket, ltrim($pathInfo['dirname'], '/')); | ||||
| 
 | ||||
|                     $ossObject->uploadFile($bucket, ltrim($src, '/'), $realPath); | ||||
|                 } | ||||
|                 $oss = true; | ||||
|             } catch (Exception $e) { | ||||
|                 \think\facade\Log::error('阿里云OSS上传文件失败 '.$e->getMessage()); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         // 将src中路径创建
 | ||||
|         return self::create([ | ||||
|             'type'       => $type, | ||||
|             'name'       => $file->getOriginalName(), | ||||
|             'md5'        => $md5, | ||||
|             'src'        => $src, | ||||
|             'path'       => isset(pathinfo($src)['dirname']) ? pathinfo($src)['dirname'].'/' : '', | ||||
|             'size'       => $file->getSize(), | ||||
|             'suffix'     => $file->getOriginalExtension(), | ||||
|             'mime_type'  => $file->getOriginalMime(), | ||||
|             'created_at' => $now, | ||||
|             'updated_at' => $now, | ||||
|             'is_oss'     => $oss, | ||||
|             'w_h'        => $w_h | ||||
|         ]); | ||||
|     } | ||||
| 
 | ||||
|     //获取所有记录
 | ||||
|     public static function getAll() | ||||
|     { | ||||
|         return self::select()->toArray(); | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,20 @@ | |||
| <?php | ||||
| namespace app\model; | ||||
| 
 | ||||
| class Log extends Base | ||||
| { | ||||
|     //记录操作日志
 | ||||
|     public static function write($controller, $action, $content) | ||||
|     { | ||||
|         $auth = session('auth'); | ||||
|         return self::create([ | ||||
|             'member_id' => $auth['user_id'], | ||||
|             'name' => $auth['username'], | ||||
|             'ip' => request()->ip(), | ||||
|             'create_time' => time(), | ||||
|             'controller' => $controller, | ||||
|             'action' => $action, | ||||
|             'content' => $content | ||||
|         ]); | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,6 @@ | |||
| <?php | ||||
| namespace app\model; | ||||
| 
 | ||||
| class LoginLog extends Base | ||||
| { | ||||
| } | ||||
|  | @ -0,0 +1,81 @@ | |||
| <?php | ||||
| 
 | ||||
| namespace app\model; | ||||
| 
 | ||||
| use think\facade\Db; | ||||
| 
 | ||||
| class Member extends Base | ||||
| { | ||||
|     public const STATUS_NORMAL  = 1;//正常
 | ||||
|     public const STATUS_DISABLE = 0;//禁用
 | ||||
| 
 | ||||
|     public const ANENT_role_id = 2;//角色id 2 为代理商
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|     public static function getList($limit = 40) | ||||
|     { | ||||
|         return self::alias('m') | ||||
|             ->leftjoin('auth_group g', 'g.id=m.group_id') | ||||
|             ->field('m.id,m.username,m.login_time,m.group_id,g.title') | ||||
|             ->order('m.id', 'asc') | ||||
|             ->paginate($limit); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 获取所有代理商 | ||||
|      * */ | ||||
|     public static  function getAgentAll(){ | ||||
| 
 | ||||
|         $subQuery = Db::name('member') | ||||
|             ->field('id,business_code,nickname') | ||||
|             ->whereRaw('(find_in_set("'.Member::ANENT_role_id.'", roles))') | ||||
|             ->buildSql(); | ||||
| 
 | ||||
|        return Db::table($subQuery . ' a') | ||||
|             ->join("business b" ,"a.business_code = b.code") | ||||
|            ->field("a.*") | ||||
|             ->order('a.id', 'desc') | ||||
|             ->select(); | ||||
|     } | ||||
|     /** | ||||
|      * 根据角色分组返回用户 | ||||
|      * @param  int  $groupId  角色分组ID | ||||
|      * @param  int  $limit  每页数量 | ||||
|      */ | ||||
|     public static function getListByGroup($groupId, $limit = 40) | ||||
|     { | ||||
|         return self::alias('m') | ||||
|             ->leftjoin('auth_group g', 'g.id=m.group_id') | ||||
|             ->field('m.id,m.username,m.login_time,m.group_id,g.title') | ||||
|             ->where('m.group_id', '=', $groupId) | ||||
|             ->order('m.id', 'asc') | ||||
|             ->paginate($limit); | ||||
|     } | ||||
| 
 | ||||
|     //根据用户名获取管理账号
 | ||||
|     public static function getByUserName($username) | ||||
|     { | ||||
|         return self::where('username', trim($username)) | ||||
|             ->findOrEmpty() | ||||
|             ->toArray(); | ||||
|     } | ||||
| 
 | ||||
|     //根据ID获取管理账户和相关权限
 | ||||
|     public static function getMemberAndRulesByID($memberId) | ||||
|     { | ||||
|         return self::alias('m') | ||||
|             ->join('auth_group g', 'm.group_id = g.id', 'LEFT') | ||||
|             ->field('m.group_id,g.rules') | ||||
|             ->where('m.id', $memberId) | ||||
|             ->findOrEmpty() | ||||
|             ->toArray(); | ||||
|     } | ||||
| 
 | ||||
|     public static function updateCates($id, $cates) | ||||
|     { | ||||
|         $cates = implode(',', $cates); | ||||
|         $data  = ['cates' => $cates]; | ||||
|         self::updateById($id, $data); | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,71 @@ | |||
| <?php | ||||
| 
 | ||||
| namespace app\model; | ||||
| 
 | ||||
| use Exception; | ||||
| 
 | ||||
| class Menu extends Base | ||||
| { | ||||
|     public const SHOW_YES = 1; | ||||
|     public const SHOW_NO  = 0; | ||||
| 
 | ||||
|     public const STATUS_NORMAL  = 1; | ||||
|     public const STATUS_DISABLE = 0; | ||||
| 
 | ||||
|     public const TYPE_MENU   = 'menu'; | ||||
|     public const TYPE_ACTION = 'action'; | ||||
| 
 | ||||
|     /** | ||||
|      * 默认操作 | ||||
|      * | ||||
|      * @return string[] | ||||
|      */ | ||||
|     public static function defaultAction(): array | ||||
|     { | ||||
|         return [ | ||||
|             'index'  => '查看', | ||||
|             'add'    => '添加', | ||||
|             'edit'   => '编辑', | ||||
|             'del'    => '删除', | ||||
|             'sort'   => '排序', | ||||
|             'modify' => '属性设置', | ||||
|         ]; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 自从生成常规操作权限 | ||||
|      * | ||||
|      * @param  int  $id | ||||
|      * @param  string  $name | ||||
|      * @param  string  $path | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public static function generate(int $id, string $name, string $path) | ||||
|     { | ||||
|         $actions = self::defaultAction(); | ||||
|         $delete  = []; | ||||
|         $insert  = []; | ||||
|         $created = date('Y-m-d H:i:s'); | ||||
|         foreach ($actions as $key => $action) { | ||||
|             $name     = explode(':', $name)[0]; | ||||
|             $delete[] = $name.':'.$key; | ||||
| 
 | ||||
|             $arr               = []; | ||||
|             $arr['title']      = $action; | ||||
|             $arr['pid']        = $id; | ||||
|             $arr['name']       = $name.':'.$key; | ||||
|             $arr['type']       = self::TYPE_ACTION; | ||||
|             $arr['path']       = $path.$id.','; | ||||
|             $arr['remark']     = sprintf("自动生成[%s][%s]操作", $name, $action); | ||||
|             $arr['created_at'] = $created; | ||||
| 
 | ||||
|             $insert[] = $arr; | ||||
|         } | ||||
| 
 | ||||
|         //删除已有常规操作
 | ||||
|         self::where('pid', $id)->whereIn('name', $delete)->delete(); | ||||
| 
 | ||||
|         //新增常规操作
 | ||||
|         (new self())->saveAll($insert); | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,18 @@ | |||
| <?php | ||||
| namespace app\model; | ||||
| 
 | ||||
| class Model extends Base  | ||||
| { | ||||
|     //获取模型列表
 | ||||
|     public static function getList() | ||||
|     { | ||||
|         return self::order('sort asc') | ||||
|         ->select() | ||||
|         ->toArray(); | ||||
|     } | ||||
|     public static function onAfterInsert($model) | ||||
|     { | ||||
|         $model->sort = $model->id; | ||||
|         $model->save(); | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,8 @@ | |||
| <?php | ||||
| 
 | ||||
| namespace app\model; | ||||
| 
 | ||||
| class PaymentLog extends Base | ||||
| { | ||||
|     public const TYPE_ORDER      = 'order';//订单支付
 | ||||
| } | ||||
|  | @ -0,0 +1,24 @@ | |||
| <?php | ||||
| 
 | ||||
| namespace app\model; | ||||
| 
 | ||||
| use think\Collection; | ||||
| use think\db\exception\DataNotFoundException; | ||||
| use think\db\exception\DbException; | ||||
| use think\db\exception\ModelNotFoundException; | ||||
| 
 | ||||
| /** | ||||
|  * 充值记录 | ||||
|  * Class Recharge | ||||
|  * @package app\model | ||||
|  */ | ||||
| class Recharge extends Base | ||||
| { | ||||
|     const state_off = 0;//未支付
 | ||||
|     const state_on  = 1;//已支付
 | ||||
| 
 | ||||
|     public function business() | ||||
|     { | ||||
|         return $this->hasOne(Business::class,"code","business_code")->bind(["business_name"]); | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,8 @@ | |||
| <?php | ||||
| namespace app\model; | ||||
| 
 | ||||
| class Role extends Base | ||||
| { | ||||
|     public const STATUS_NORMAL  = 1; //正常
 | ||||
|     public const STATUS_DISABLE = 0;//禁用
 | ||||
| } | ||||
|  | @ -0,0 +1,7 @@ | |||
| <?php | ||||
| namespace app\model; | ||||
| 
 | ||||
| class Rules extends Base | ||||
| { | ||||
| 
 | ||||
| } | ||||
|  | @ -0,0 +1,40 @@ | |||
| <?php | ||||
| 
 | ||||
| namespace app\model; | ||||
| 
 | ||||
| class Slide extends Base | ||||
| { | ||||
|     public static function delByIds($ids) | ||||
|     { | ||||
|         return self::whereIn('id', $ids)->delete(); | ||||
|     } | ||||
| 
 | ||||
|     //获取幻灯片列表
 | ||||
|     public static function getList() | ||||
|     { | ||||
|         return self::order("sort asc") | ||||
|             ->select() | ||||
|             ->toArray(); | ||||
|     } | ||||
| 
 | ||||
|     public static function onAfterInsert($slide) | ||||
|     { | ||||
|         $slide->sort = $slide->id; | ||||
|         $slide->save(); | ||||
|     } | ||||
| 
 | ||||
|     //获取轮播图涉及到的文件
 | ||||
|     public static function getFilesInUse() | ||||
|     { | ||||
|         $items = self::select()->toArray(); | ||||
|         $data  = []; | ||||
|         foreach ($items as $item) { | ||||
|             $src = trim($item['src']); | ||||
|             if (!empty($src)) { | ||||
|                 $key        = getKeyByPath($src); | ||||
|                 $data[$key] = $src; | ||||
|             } | ||||
|         } | ||||
|         return $data; | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,16 @@ | |||
| <?php | ||||
| namespace app\model; | ||||
| 
 | ||||
| /** | ||||
|  * 轮播图显示位置 | ||||
|  * | ||||
|  * Class SlidePosition | ||||
|  * @package app\model | ||||
|  */ | ||||
| class SlidePosition extends Base | ||||
| { | ||||
|     public static function allPosition() | ||||
|     { | ||||
|         return self::select(); | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,54 @@ | |||
| <?php | ||||
| namespace app\model; | ||||
| 
 | ||||
| class System extends Base | ||||
| { | ||||
|     //获取友情链接上传图片尺寸
 | ||||
|     public static function getLinkImageSize() | ||||
|     { | ||||
|         $system = self::getSystem(); | ||||
|         if(!empty($system['link_w']) && !empty($system['link_h'])){ | ||||
|             $linkSize = $system['link_w'] . '像素 X ' . $system['link_h'] . '像素'; | ||||
|         }else{ | ||||
|             $linkSize = ''; | ||||
|         } | ||||
|         return $linkSize; | ||||
|     } | ||||
|     //获取幻灯片上传尺寸
 | ||||
|     public static function getSlideImageSize() | ||||
|     { | ||||
|         $system = self::getSystem(); | ||||
|         if(!empty($system['slide_w']) && !empty($system['slide_h'])){ | ||||
|             $slideSize = $system['slide_w'] . '像素 X ' . $system['slide_h'] . '像素'; | ||||
|         }else{ | ||||
|             $slideSize = ''; | ||||
|         } | ||||
|         if(!empty($system['slide_mobile_w']) && !empty($system['slide_mobile_h'])){ | ||||
|             $slideMobileSize = $system['slide_mobile_w'] . '像素 X ' . $system['slide_mobile_h'] . '像素'; | ||||
|         }else{ | ||||
|             $slideMobileSize = ''; | ||||
|         } | ||||
|         return [ | ||||
|             'slide_size' => $slideSize, | ||||
|             'slide_mobile_size' => $slideMobileSize | ||||
|         ]; | ||||
|     } | ||||
|     //获取文章图片尺寸
 | ||||
|     public static function getArticleImageSize() | ||||
|     { | ||||
|         $system = self::getSystem(); | ||||
|         if(!empty($system['article_w']) && !empty($system['article_h'])){ | ||||
|             $articleSize = $system['article_w'] . '像素 X ' . $system['article_h'] . '像素'; | ||||
|         }else{ | ||||
|             $articleSize = ''; | ||||
|         } | ||||
|         return $articleSize; | ||||
|     } | ||||
|     //获取系统配置信息
 | ||||
|     public static function getSystem() | ||||
|     { | ||||
|         return self::order('id asc') | ||||
|         ->findOrEmpty() | ||||
|         ->toArray(); | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,107 @@ | |||
| <?php | ||||
| 
 | ||||
| namespace app\repository; | ||||
| 
 | ||||
| use app\exception\RepositoryException; | ||||
| 
 | ||||
| use app\service\Repository; | ||||
| use think\db\exception\DataNotFoundException; | ||||
| use think\db\exception\DbException; | ||||
| use think\db\exception\ModelNotFoundException; | ||||
| use think\Model; | ||||
| 
 | ||||
| /** | ||||
|  * 账户域 相关操作(客户账号) | ||||
|  * | ||||
|  * Class AccountRepository | ||||
|  * @package app\repository | ||||
|  * @method self getInstance(Model $model = null) static | ||||
|  */ | ||||
| class AccountRepository extends Repository | ||||
| { | ||||
|     /** | ||||
|      * 获取用户列表 | ||||
|      * | ||||
|      * @throws RepositoryException | ||||
|      */ | ||||
|     public function list(): ?array | ||||
|     { | ||||
|         return $this->findList(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 获取指定账户记录By手机号 | ||||
|      * | ||||
|      * @param  string  $phone | ||||
|      * @param  array  $fields | ||||
|      * @return Model|null | ||||
|      * @throws DataNotFoundException | ||||
|      * @throws DbException | ||||
|      * @throws ModelNotFoundException | ||||
|      */ | ||||
|     public function infoByPhone(string $phone, array $fields = []): ?Model | ||||
|     { | ||||
|         $where[] = ['mobile', '=', $phone]; | ||||
|         return $this->findOneByWhere($where, $fields); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 获取指定账户记录By用户名 | ||||
|      * | ||||
|      * @param  string  $username | ||||
|      * @param  array  $fields | ||||
|      * @return Model|null | ||||
|      * @throws DataNotFoundException | ||||
|      * @throws DbException | ||||
|      * @throws ModelNotFoundException | ||||
|      */ | ||||
|     public function infoByUsername(string $username, array $fields = []): ?Model | ||||
|     { | ||||
|         $where[] = ['username', '=', $username]; | ||||
|         return $this->findOneByWhere($where, $fields); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     /** | ||||
|      * 通过微信小程序的openID查询 | ||||
|      * | ||||
|      * @param  string  $openID | ||||
|      * @return array|Model|null | ||||
|      * @throws DataNotFoundException | ||||
|      * @throws DbException | ||||
|      * @throws ModelNotFoundException | ||||
|      */ | ||||
|     public function findByOpenID(string $openID) | ||||
|     { | ||||
|         return $this->model->where('openid', $openID)->find(); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|     /** | ||||
|      * 修改密码 | ||||
|      * | ||||
|      * @param  int  $accountId | ||||
|      * @param  string  $oldPwd | ||||
|      * @param  string  $newPwd | ||||
|      * @return bool | ||||
|      * @throws RepositoryException | ||||
|      */ | ||||
|     public function modifyPwd(int $accountId, string $oldPwd, string $newPwd): bool | ||||
|     { | ||||
|         if (!$user = $this->findById($accountId)) { | ||||
|             throw new RepositoryException('用户不存在'); | ||||
|         } | ||||
| 
 | ||||
|         if ($user['password'] != md5($oldPwd)) { | ||||
|             throw new RepositoryException('原密码错误'); | ||||
|         } | ||||
| 
 | ||||
|         $user->password = md5($newPwd); | ||||
| 
 | ||||
|         return $user->save(); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| } | ||||
|  | @ -0,0 +1,115 @@ | |||
| <?php | ||||
| 
 | ||||
| namespace app\repository; | ||||
| 
 | ||||
| use app\exception\RepositoryException; | ||||
| use app\model\Business; | ||||
| use app\model\CouponMain; | ||||
| use app\model\Deduction; | ||||
| use app\model\Recharge; | ||||
| use app\service\Repository; | ||||
| use think\Collection; | ||||
| use think\Model; | ||||
| 
 | ||||
| /** | ||||
|  * 商家域 相关操作 | ||||
|  * | ||||
|  * Class BusinessRepository | ||||
|  * @package app\repository | ||||
|  * @method self getInstance(Model $model = null) static | ||||
|  */ | ||||
| class BusinessRepository extends Repository | ||||
| { | ||||
|     /** | ||||
|      * 根据条件查询列表 | ||||
|      * | ||||
|      * @param array $where 查询条件 | ||||
|      * @param int $page 默认第一页 0不限制 | ||||
|      * @param int $limit 限制条数 0不限制 | ||||
|      * @param array $order | ||||
|      * @return array | ||||
|      * @throws RepositoryException | ||||
|      */ | ||||
|     public function businessList(array $where = [], int $page = 1, int $limit = 0, array $order = []) | ||||
|     { | ||||
|         $q = $this->model->alias("a")->field("id")->withJoin(["account" => ["avatar_url", "nick_name"], "business"]); | ||||
|         $data = [ | ||||
|             'total' => 0, | ||||
|             'current' => $page, | ||||
|             'size' => $limit, | ||||
|             'list' => new Collection(), | ||||
|         ]; | ||||
| 
 | ||||
| 
 | ||||
|         if (count($where)) { | ||||
|             $q = $q->where($where); | ||||
|         } | ||||
|         if (count($order)) { | ||||
|             $q = $q->order($order); | ||||
|         } | ||||
|         $data['total'] = $q->count(); | ||||
|         if ($data['total']) { | ||||
|             if ($limit) { | ||||
|                 if ($page) { | ||||
|                     $q = $q->page($page); | ||||
|                 } | ||||
|                 $q = $q->limit($limit); | ||||
|             } | ||||
| 
 | ||||
|             $data['list'] = $q->select(); | ||||
|         } | ||||
| 
 | ||||
|         return $data; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 优惠券列表 | ||||
|      * | ||||
|      * @param string $businessCode 商家code | ||||
|      * @param int $page 默认第一页 0不限制 | ||||
|      * @param int $limit 限制条数 0不限制 | ||||
|      * @param array $order | ||||
|      * @return array | ||||
|      * @throws RepositoryException | ||||
|      */ | ||||
|     public function businessCouponList($where, int $page = 1, int $limit = 0, array $order = ["create_time" => "desc", "id" => "desc"]) | ||||
|     { | ||||
|         return CouponMain::findList($where, [], $page, $limit, null, $order); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 扣费记录 | ||||
|      * | ||||
|      * @param string $businessCode 商家code | ||||
|      * @param int $page 默认第一页 0不限制 | ||||
|      * @param int $limit 限制条数 0不限制 | ||||
|      * @param array $order | ||||
|      * @return array | ||||
|      * @throws RepositoryException | ||||
|      */ | ||||
|     public function businessDeductionList($where, int $page = 1, int $limit = 0, array $order = ["create_time" => "desc", "id" => "desc"]) | ||||
|     { | ||||
|         return Deduction::findList($where, [], $page, $limit, null, $order); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 充值记录 | ||||
|      * | ||||
|      * @param string $businessCode 商家code | ||||
|      * @param int $page 默认第一页 0不限制 | ||||
|      * @param int $limit 限制条数 0不限制 | ||||
|      * @param array $order | ||||
|      * @return array | ||||
|      * @throws RepositoryException | ||||
|      */ | ||||
|     public function businessRechargeList($where, int $page = 1, int $limit = 0, array $order = ["create_time" => "desc", "id" => "desc"]) | ||||
|     { | ||||
|         return Recharge::findList($where, [], $page, $limit, function ($q){ | ||||
|             return $q->withJoin(["business"=>["business_name"]]); | ||||
|         }, $order); | ||||
|     } | ||||
|     /* 获取所有不是代理商的商家*/ | ||||
|     public function getBusinessAll(){ | ||||
|         return   Business:: where("state", Business::state_on)->select(); | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,49 @@ | |||
| <?php | ||||
| 
 | ||||
| namespace app\repository; | ||||
| 
 | ||||
| use app\traits\cms\ArticleTrait; | ||||
| use app\traits\cms\MenuTrait; | ||||
| use app\traits\CmsCategoryTrait; | ||||
| use think\db\exception\DataNotFoundException; | ||||
| use think\db\exception\DbException; | ||||
| use think\db\exception\ModelNotFoundException; | ||||
| use think\Model; | ||||
| use app\service\Repository; | ||||
| 
 | ||||
| /** | ||||
|  * CMS 基础功能仓储 | ||||
|  * | ||||
|  * Class CmsRepository | ||||
|  * @package app\repository | ||||
|  * @method self getInstance(Model $model = null) static | ||||
|  */ | ||||
| class CmsRepository extends Repository | ||||
| { | ||||
|     use CmsCategoryTrait; | ||||
|     use MenuTrait; | ||||
|     use ArticleTrait; | ||||
| 
 | ||||
|     /** | ||||
|      * xmSelect下拉列表格式处理 | ||||
|      * 如 [['title' => 'aa', 'value' => 1, 'selected' => true, 'prefix' => '    ']] | ||||
|      * | ||||
|      * @param  array  $data  待处理的数据 | ||||
|      * @param  string  $symbol  分隔符号 默认   | ||||
|      * @param  int  $repeatNum  重复次数 默认4 | ||||
|      * @return array | ||||
|      */ | ||||
|     public function handleSelectedList(array $data, string $symbol = ' ', int $repeatNum = 4): array | ||||
|     { | ||||
|         $list = []; | ||||
|         foreach ($data as $item) { | ||||
|             $level    = $item['level'] ?? 0; | ||||
|             $arr = $item; | ||||
|             $arr['children'] = $arr['children'] ?? []; | ||||
|             $arr['prefix'] = str_repeat($symbol, $level * $repeatNum); | ||||
|             $list[] = $arr; | ||||
|         } | ||||
| 
 | ||||
|         return $list; | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,32 @@ | |||
| <?php | ||||
| 
 | ||||
| namespace app\repository; | ||||
| 
 | ||||
| use app\exception\RepositoryException; | ||||
| use app\model\CouponMain; | ||||
| use app\service\Repository; | ||||
| use think\Model; | ||||
| 
 | ||||
| /** | ||||
|  * 优惠券 相关操作 | ||||
|  * | ||||
|  * Class CouponRepository | ||||
|  * @package app\repository | ||||
|  * @method self getInstance(Model $model = null) static | ||||
|  */ | ||||
| class CouponRepository extends Repository | ||||
| { | ||||
|     /** | ||||
|      * 优惠券列表 | ||||
|      * | ||||
|      * @param string $businessCode 商家code | ||||
|      * @param array $order | ||||
|      * @return array | ||||
|      * @throws RepositoryException | ||||
|      */ | ||||
|     public function businessCouponModel($where) | ||||
|     { | ||||
|         return CouponMain::where($where); | ||||
|     } | ||||
| 
 | ||||
| } | ||||
|  | @ -0,0 +1,212 @@ | |||
| <?php | ||||
| namespace app\repository; | ||||
| 
 | ||||
| use app\model\SlidePosition; | ||||
| use Exception; | ||||
| use think\Model; | ||||
| use app\model\Slide; | ||||
| use think\Collection; | ||||
| use app\service\Repository; | ||||
| use think\db\exception\DbException; | ||||
| use think\db\exception\DataNotFoundException; | ||||
| use think\db\exception\ModelNotFoundException; | ||||
| 
 | ||||
| /** | ||||
|  * 运营领域 相关 | ||||
|  * | ||||
|  * Class OperationRepository | ||||
|  * @package app\repository | ||||
|  * @method self getInstance(Model $model = null) static | ||||
|  */ | ||||
| class OperationRepository extends Repository | ||||
| { | ||||
|     /** | ||||
|      * 轮播位置 | ||||
|      * | ||||
|      * @return string[][] | ||||
|      */ | ||||
|     public function slidePositions(): array | ||||
|     { | ||||
|         try { | ||||
|             return SlidePosition::allPosition()->toArray(); | ||||
|         } catch (Exception $e) { | ||||
|             return []; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 获取轮播 | ||||
|      * | ||||
|      * @param  int  $id | ||||
|      * @return array|Model|null | ||||
|      * @throws DataNotFoundException | ||||
|      * @throws DbException | ||||
|      * @throws ModelNotFoundException | ||||
|      */ | ||||
|     public function findSlideById(int $id) | ||||
|     { | ||||
|         return Slide::findById($id); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 轮播列表 | ||||
|      * | ||||
|      * @param array $where | ||||
|      * @param array $fields | ||||
|      * @param int $page | ||||
|      * @param int $size | ||||
|      * @param callable|null $call | ||||
|      * @param array $orders | ||||
|      * @return array | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public function slideList(array $where=[],  array $fields=[], int $page=1, int $size=20, callable $call=null, array $orders=[]): array | ||||
|     { | ||||
|         return Slide::findList($where, $fields, $page, $size, $call, $orders); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 更新轮播 | ||||
|      * | ||||
|      * @param  array  $data | ||||
|      * @param  int  $id | ||||
|      * @return bool | ||||
|      * @throws DataNotFoundException | ||||
|      * @throws DbException | ||||
|      * @throws ModelNotFoundException | ||||
|      */ | ||||
|     public function updateSlide(array $data, int $id): bool | ||||
|     { | ||||
|         $item = (new Slide())->where('id', $id)->find(); | ||||
|         if ($item) { | ||||
|             return $item->save($data); | ||||
|         } | ||||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 创建轮播 | ||||
|      * | ||||
|      * @param array $data | ||||
|      * @return Slide | ||||
|      */ | ||||
|     public function createSlide(array $data): Slide | ||||
|     { | ||||
|         $data['created_at'] = date('y-m-d H:i:s'); | ||||
|         return Slide::create($data); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 删除轮播图 | ||||
|      * | ||||
|      * @param array $ids | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function deleteSlides(array $ids): bool | ||||
|     { | ||||
|         return Slide::deleteByIds($ids); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 轮播位置是否存在 | ||||
|      * | ||||
|      * @param  string  $position | ||||
|      * @param  int  $exceptId 需要排除的显示位置ID | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function slidePositionExists(string $position, int $exceptId = 0): bool | ||||
|     { | ||||
|         return (new SlidePosition())->when($exceptId > 0, function ($q) use ($exceptId) { | ||||
|                 $q->where('id', '<>', $exceptId); | ||||
|             })->where('key', $position)->count() > 0; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 根据显示位置查询相关的轮播图信息 | ||||
|      * | ||||
|      * @param string $position 轮播图位置标识 | ||||
|      * @param int $size 限制查询数量 | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public function slideListByPosition(string $position, int $size=0): ?Collection | ||||
|     { | ||||
|         $where[] = ['position', '=', $position]; | ||||
|         $orders = ['sort'=>'asc']; | ||||
|         return Slide::findList($where, [], 1, $size, null, $orders)['list']; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     /** | ||||
|      * 轮播显示位置列表 | ||||
|      * | ||||
|      * @param array $where | ||||
|      * @param array $fields | ||||
|      * @param int $page | ||||
|      * @param int $size | ||||
|      * @param callable|null $call | ||||
|      * @param array $orders | ||||
|      * @return array | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public function slidePositionList(array $where=[],  array $fields=[], int $page=1, int $size=20, callable $call=null, array $orders=[]): array | ||||
|     { | ||||
|         return SlidePosition::findList($where, $fields, $page, $size, $call, $orders); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 更新轮播位置 | ||||
|      * | ||||
|      * @param  array  $data | ||||
|      * @param  int  $id | ||||
|      * @return bool | ||||
|      * @throws DataNotFoundException | ||||
|      * @throws DbException | ||||
|      * @throws ModelNotFoundException | ||||
|      */ | ||||
|     public function updateSlidePosition(array $data, int $id): bool | ||||
|     { | ||||
|         $item = (new SlidePosition())->where('id', $id)->find(); | ||||
|         if ($item) { | ||||
|             $item->save($data); | ||||
|         } | ||||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 创建轮播位置 | ||||
|      * | ||||
|      * @param array $data | ||||
|      * @return SlidePosition | ||||
|      */ | ||||
|     public function createSlidePosition(array $data): SlidePosition | ||||
|     { | ||||
|         $data['created_at'] = date('y-m-d H:i:s'); | ||||
|         return SlidePosition::create($data); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 删除轮播位置 | ||||
|      * | ||||
|      * @param array $ids | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function deleteSlidePositions(array $ids): bool | ||||
|     { | ||||
|         return SlidePosition::deleteByIds($ids); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 获取轮播位置 | ||||
|      * | ||||
|      * @param  int  $id | ||||
|      * @return array|Model|null | ||||
|      * @throws DataNotFoundException | ||||
|      * @throws DbException | ||||
|      * @throws ModelNotFoundException | ||||
|      */ | ||||
|     public function findSlidePositionById(int $id) | ||||
|     { | ||||
|         return SlidePosition::findById($id); | ||||
|     } | ||||
| 
 | ||||
| } | ||||
|  | @ -0,0 +1,38 @@ | |||
| <?php | ||||
| 
 | ||||
| namespace app\repository; | ||||
| 
 | ||||
| use app\exception\RepositoryException; | ||||
| 
 | ||||
| use app\model\Recharge; | ||||
| use app\service\Repository; | ||||
| use think\db\exception\DataNotFoundException; | ||||
| use think\db\exception\DbException; | ||||
| use think\db\exception\ModelNotFoundException; | ||||
| use think\Model; | ||||
| 
 | ||||
| /** | ||||
|  * 充值户域 相关操作 | ||||
|  * Class RechargeRepository | ||||
|  * @package app\repository | ||||
|  * @method self getInstance(Model $model = null) static | ||||
|  */ | ||||
| class RechargeRepository extends Repository | ||||
| { | ||||
|     /** | ||||
|      * 创建一个支付订单 | ||||
|      * */ | ||||
|     public function createOrder($businessCode, $money) | ||||
|     { | ||||
|         $data = [ | ||||
|             "order_num" => createUuid(), | ||||
|             "business_code" => $businessCode, | ||||
|             "money" => $money, | ||||
|             "state" => Recharge::state_off, | ||||
|             "create_time" => date("Y-m-d H:i:s"), | ||||
|             "balance" => 0, | ||||
|         ]; | ||||
|         return Recharge::create($data); | ||||
|     } | ||||
| 
 | ||||
| } | ||||
|  | @ -0,0 +1,9 @@ | |||
| <?php | ||||
| 
 | ||||
| use tauthz\TauthzService; | ||||
| 
 | ||||
| // 系统服务定义文件
 | ||||
| // 服务在完成全局初始化之后执行
 | ||||
| return [ | ||||
|     TauthzService::class, | ||||
| ]; | ||||
|  | @ -0,0 +1,46 @@ | |||
| <?php | ||||
| 
 | ||||
| namespace app\service; | ||||
| 
 | ||||
| use OSS\Core\OssException; | ||||
| use OSS\OssClient; | ||||
| use think\facade\Config; | ||||
| use think\facade\Log; | ||||
| 
 | ||||
| class AliOss | ||||
| { | ||||
|     private static $oss = null; | ||||
| 
 | ||||
|     private function __construct() | ||||
|     { | ||||
|     } | ||||
| 
 | ||||
|     private function __clone() | ||||
|     { | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 阿里云OSS | ||||
|      * | ||||
|      */ | ||||
|     public static function config() | ||||
|     { | ||||
|         Config::load('extra/alioss', 'alioss'); | ||||
|         return config('alioss'); | ||||
|     } | ||||
| 
 | ||||
|     // 阿里云OSS实例  单例模式
 | ||||
|     public static function instance(): ?OssClient | ||||
|     { | ||||
|         if (self::$oss == null) { | ||||
|             try { | ||||
|                 $conf = self::config(); | ||||
|                 self::$oss =  new OssClient($conf['accessKeyId'], $conf['accessKeySecret'], $conf['endpoint']); | ||||
|             } catch (OssException $e) { | ||||
|                 Log::error('实例化阿里云OSS失败: ' . $e->getMessage()); | ||||
|                 return null; | ||||
|             } | ||||
|         } | ||||
|         return self::$oss; | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,64 @@ | |||
| <?php | ||||
| 
 | ||||
| namespace app\service; | ||||
| 
 | ||||
| use Yansongda\Pay\Pay; | ||||
| use Yansongda\Pay\Log; | ||||
| use think\facade\Config; | ||||
| 
 | ||||
| class Alipay | ||||
| { | ||||
|     private static $app = null; | ||||
| 
 | ||||
|     private function __construct() | ||||
|     { | ||||
|     } | ||||
| 
 | ||||
|     private function __clone() | ||||
|     { | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 支付宝配置 | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public static function config(): array | ||||
|     { | ||||
|         Config::load('extra/alipay', 'alipay'); | ||||
|         $conf = config('alipay'); | ||||
|         return [ | ||||
|             'app_id'         => trim($conf['appId']), | ||||
|             'notify_url'     => trim($conf['notify_url']), | ||||
|             'return_url'     => trim($conf['return_url']) ?? trim($conf['notify_url']), | ||||
|             'ali_public_key' => trim($conf['aliPubKey']),//注意 这里的是支付宝的公钥
 | ||||
|             // 加密方式: **RSA2**
 | ||||
|             'private_key'    => trim($conf['priKey']), | ||||
|             // 使用公钥证书模式,请配置下面两个参数,同时修改ali_public_key为以.crt结尾的支付宝公钥证书路径,
 | ||||
|             // 如(./cert/alipayCertPublicKey_RSA2.crt)
 | ||||
|             // 'app_cert_public_key' => './cert/appCertPublicKey.crt', //应用公钥证书路径
 | ||||
|             // 'alipay_root_cert' => './cert/alipayRootCert.crt', //支付宝根证书路径
 | ||||
|             'log'            => [ // optional
 | ||||
|                 'file'     => './logs/alipay.log', | ||||
|                 'level'    => 'debug', // 建议生产环境等级调整为 info,开发环境为 debug
 | ||||
|                 'type'     => 'single', // optional, 可选 daily.
 | ||||
|                 'max_file' => 30, // optional, 当 type 为 daily 时有效,默认 30 天
 | ||||
|             ], | ||||
|             'http'           => [ // optional
 | ||||
|                 'timeout'         => 5.0, | ||||
|                 'connect_timeout' => 5.0, | ||||
|                 // 更多配置项请参考 [Guzzle](https://guzzle-cn.readthedocs.io/zh_CN/latest/request-options.html)
 | ||||
|             ], | ||||
|             //                'mode' => 'dev', // optional,设置此参数,将进入沙箱模式
 | ||||
|         ]; | ||||
|     } | ||||
| 
 | ||||
|     //支付宝支付实例  单例模式
 | ||||
|     public static function getInstance(): ?\Yansongda\Pay\Gateways\Alipay | ||||
|     { | ||||
|         if (self::$app == null) { | ||||
|             self::$app = Pay::alipay(self::config()); | ||||
|         } | ||||
|         return self::$app; | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,201 @@ | |||
| <?php | ||||
| namespace app\service; | ||||
| 
 | ||||
| use PhpOffice\PhpSpreadsheet\Shared\Date as EDate; | ||||
| use PhpOffice\PhpSpreadsheet\Style\Alignment; | ||||
| use PhpOffice\PhpSpreadsheet\Style\Border; | ||||
| use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet; | ||||
| use PhpOffice\PhpSpreadsheet\Writer\Xlsx; | ||||
| use think\file\UploadedFile; | ||||
| 
 | ||||
| class Excel | ||||
| { | ||||
|     // 导出excel默认样式
 | ||||
|     public static array $excelStyle = [ | ||||
|         'font'      => [ | ||||
|             'name' => '宋体', | ||||
|         ], | ||||
|         'alignment' => [ | ||||
|             'horizontal' => Alignment::HORIZONTAL_CENTER,  // 水平居中
 | ||||
|             'vertical'   => Alignment::VERTICAL_CENTER,  // 垂直居中
 | ||||
|             'wrapText'   => true, | ||||
|         ], | ||||
|         'borders'   => [ | ||||
|             'allBorders' => [ | ||||
|                 'borderStyle' => Border::BORDER_THIN, | ||||
|                 'color'       => ['rgb' => 'eeeeee'], | ||||
|             ] | ||||
|         ], | ||||
|     ]; | ||||
| 
 | ||||
|     public static array $defaultSetting = [ | ||||
|         'cell_width'    => 30, // 默认列宽
 | ||||
|         'font_size'     => 12, // 默认excel内容字体大小
 | ||||
|     ]; | ||||
| 
 | ||||
|     //导出
 | ||||
|     static public function export($spreadsheet,$filename) | ||||
|     { | ||||
|         $writer = new Xlsx($spreadsheet); | ||||
|         header("Content-Type: application/force-download"); | ||||
|         header("Content-Type: application/octet-stream"); | ||||
|         header("Content-Type: application/download"); | ||||
|         header('Content-Disposition:inline;filename="'.$filename.'"'); | ||||
|         header("Content-Transfer-Encoding: binary"); | ||||
|         header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); | ||||
|         header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); | ||||
|         header("Cache-Control: must-revalidate, post-check=0, pre-check=0"); | ||||
|         header("Pragma: no-cache"); | ||||
|         $writer->save('php://output'); | ||||
|         $spreadsheet->disconnectWorksheets(); | ||||
|         unset($spreadsheet); | ||||
|         exit; | ||||
|     } | ||||
| 
 | ||||
|     public static function cancelTimeLimit() | ||||
|     { | ||||
|         ini_set('max_execution_time', '0'); | ||||
|         ini_set("memory_limit", '-1'); | ||||
|         set_time_limit(0); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 根据header字段获取可配置列的cellId列表 | ||||
|      * 默认前26列为可配置列A~Z, $headerLength不能超过26 * 27 = 702 | ||||
|      * | ||||
|      * @param int $headerLength | ||||
|      * @return array | ||||
|      */ | ||||
|     public static function getCellIds(int $headerLength): array | ||||
|     { | ||||
|         $defaultCellIds = range('A', 'Z', 1); | ||||
|         $cellIds = $defaultCellIds; | ||||
|         $loop = ceil($headerLength / 26); | ||||
|         if($loop>1) { | ||||
|             $maxPrefixIndex = ($loop - 2) >= 25 ? 25 : ($loop - 2); | ||||
|             for ($prefixIndex = 0; $prefixIndex<= $maxPrefixIndex; $prefixIndex++) { | ||||
|                 $prefix = $defaultCellIds[$prefixIndex]; | ||||
|                 $cellIds = array_merge($cellIds, array_map(function ($val) use($prefix) { | ||||
|                     return $prefix.$val; | ||||
|                 }, $defaultCellIds)); | ||||
|             } | ||||
|         } | ||||
|         return $cellIds; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 设置导出表数据 | ||||
|      * | ||||
|      * @param Worksheet $sheet 工作表对象 | ||||
|      * @param array $cellValues 数据信息,二维数组(ps:若字段值需要指定样式以数组格式传递,如[$val, DataType::TYPE_STRING])。第二行开始填充 | ||||
|      * @param array $header 表头信息, 第一行为表头 | ||||
|      * @param string $sheetTitle 工作表标题 | ||||
|      * @param array $cellWidthList 列宽样式,键值对,键名为列序号(从0开始计算) | ||||
|      * @param array $excelStyle 表数据样式 | ||||
|      * @param array $defaultList 默认设置样式 | ||||
|      * @param array $cellWrapList 列换行样式 | ||||
|      * @return bool | ||||
|      */ | ||||
|     public static function setExcelCells(Worksheet $sheet, array $cellValues, array $header, string $sheetTitle = '数据列表', $cellWidthList = [], $excelStyle = [], $defaultList = [], $cellWrapList = []): bool | ||||
|     { | ||||
|         $defaultStyle = [ | ||||
|             'font' => [ | ||||
|                 'name' => '宋体', | ||||
|             ], | ||||
|             'alignment' => [ | ||||
|                 'horizontal' => Alignment::HORIZONTAL_CENTER,  // 水平居中
 | ||||
|                 'vertical' => Alignment::VERTICAL_CENTER,  // 垂直居中
 | ||||
|                 'wrapText' => false, | ||||
|             ], | ||||
|             'borders' => [ | ||||
|                 'allBorders' => [ | ||||
|                     'borderStyle' => Border::BORDER_THIN, | ||||
|                     'color' => ['rgb'=>'eeeeee'], | ||||
|                 ] | ||||
|             ], | ||||
|         ]; | ||||
|         $headerLength = count($header); | ||||
| 
 | ||||
|         if($headerLength === 0) return false; | ||||
|         $cellIds = self::getCellIds($headerLength); | ||||
|         $lastCellId = $cellIds[$headerLength-1]; | ||||
|         $contentIndex = 2; | ||||
|         foreach ($cellValues as $n => $itemCell) { | ||||
|             foreach ($itemCell as $i => $cellValue) { | ||||
|                 if(is_array($cellValue)) { | ||||
|                     $sheet->setCellValueExplicit($cellIds[$i] . $contentIndex, ...$cellValue); | ||||
|                 } else { | ||||
|                     $sheet->setCellValue($cellIds[$i] . $contentIndex, $cellValue); | ||||
|                 } | ||||
|             } | ||||
|             $contentIndex++; | ||||
|         } | ||||
| 
 | ||||
|         try { | ||||
|             $headerStr = 'A1:' . $lastCellId.'1'; | ||||
|             $bodyStr = 'A2:' . $lastCellId . ($contentIndex - 1); | ||||
| 
 | ||||
|             $defaultWidth   = 24; // 默认列宽24个字符
 | ||||
|             $fontSize       = 12; // 默认字体大小为12号
 | ||||
|             if(!empty($defaultList)) { | ||||
|                 if(isset($defaultList['cell_width']) && is_numeric($defaultList['cell_width']) && $defaultList['cell_width'] > 0) { | ||||
|                     $defaultWidth = $defaultList['cell_width']; | ||||
|                 } | ||||
|                 if(isset($defaultList['font_size']) && is_numeric($defaultList['font_size']) && $defaultList['font_size'] > 0) { | ||||
|                     $fontSize = $defaultList['font_size']; | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
| 
 | ||||
|             $sheet->setTitle(empty($sheetTitle) ? '数据列表': $sheetTitle); | ||||
|             $sheet->getDefaultColumnDimension()->setAutoSize($fontSize); | ||||
|             $sheet->getStyle($headerStr)->getFont()->setBold(false)->setSize($fontSize+2); | ||||
|             $sheet->getDefaultColumnDimension()->setWidth($defaultWidth); | ||||
|             $sheet->fromArray($header, null, 'A1'); | ||||
|             $sheet->getStyle($headerStr)->applyFromArray($defaultStyle); | ||||
|             $sheet->getStyle($bodyStr)->applyFromArray(empty($excelStyle) ? $defaultStyle : $excelStyle); | ||||
| 
 | ||||
|             // 自定义列宽
 | ||||
|             if(!empty($cellWidthList)) { | ||||
|                 foreach ($cellWidthList as $cellId => $widthVal) { | ||||
|                     if(isset($cellIds[$cellId]) && is_numeric($widthVal) && $widthVal > 0) { | ||||
|                         $sheet->getColumnDimension($cellIds[$cellId])->setWidth($widthVal); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             //自定义列是否换行
 | ||||
|             if(!empty($cellWrapList)) { | ||||
|                 foreach ($cellWrapList as $cellId => $boolVal) { | ||||
|                     if(isset($cellIds[$cellId])) { | ||||
|                         $wrap = $boolVal ? true : false; | ||||
|                         $sheet->getStyle($cellIds[$cellId])->getAlignment()->setWrapText($wrap); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             return true; | ||||
|         } catch (\Exception $e) { | ||||
|             return false; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     // excel导入时间转换
 | ||||
|     public static function getExcelTime($timeStr, $format = 'Y-m-d') | ||||
|     { | ||||
|         $timezone = ini_get('date.timezone'); | ||||
|         $timeStr = trim($timeStr); | ||||
|         if (!empty($timeStr)) { | ||||
|             if (is_numeric($timeStr)) { | ||||
|                 $toTimestamp = EDate::excelToTimestamp($timeStr, $timezone); | ||||
|                 $timeStr = date($format, $toTimestamp); | ||||
|             } else { | ||||
|                 $toTimestamp = strtotime($timeStr); | ||||
|                 $timeStr = ($toTimestamp === false) ? '' : date($format, $toTimestamp); | ||||
|             } | ||||
|         } else { | ||||
|             $timeStr = ''; | ||||
|         } | ||||
|         return $timeStr; | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,62 @@ | |||
| <?php | ||||
| namespace app\service; | ||||
| 
 | ||||
| use think\facade\Config as CConfig; | ||||
| 
 | ||||
| /** | ||||
|  * 扩展配置项工具类 | ||||
|  * Class ExtraConfig | ||||
|  * @package app\service | ||||
|  */ | ||||
| class ExtraConfig | ||||
| { | ||||
|     private static string $extraDir = 'extra/'; | ||||
| 
 | ||||
|     /** | ||||
|      * 比率设置 | ||||
|      * @return array|mixed | ||||
|      */ | ||||
|     public static function ratio() | ||||
|     { | ||||
|         CConfig::load(self::$extraDir.'ratio', 'ratio'); | ||||
|         return config('ratio') ?? []; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 微信相关设置 | ||||
|      * @return array|mixed | ||||
|      */ | ||||
|     public static function wechat() | ||||
|     { | ||||
|         CConfig::load(self::$extraDir.'wechat', 'wechat'); | ||||
|         return config('wechat') ?? []; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 小程序个性装修配置 | ||||
|      * @return array|mixed | ||||
|      */ | ||||
|     public static function miniProgram() | ||||
|     { | ||||
|         CConfig::load('extra/mini_program', 'mini_program'); | ||||
|         return config('mini_program') ?? []; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 基础配置 | ||||
|      */ | ||||
|     public static function base() | ||||
|     { | ||||
|         CConfig::load('extra/base', 'base'); | ||||
|         return config('base') ?? []; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 阿里OSS配置 | ||||
|      */ | ||||
|     public static function aliOss() | ||||
|     { | ||||
|         CConfig::load('extra/alioss', 'alioss'); | ||||
|         return config('alioss') ?? []; | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,65 @@ | |||
| <?php | ||||
| namespace app\service; | ||||
| 
 | ||||
| use think\file\UploadedFile; | ||||
| 
 | ||||
| class File | ||||
| { | ||||
|     //上传文件移动到上传文件夹
 | ||||
|     public static function move(UploadedFile $file) | ||||
|     { | ||||
|         $upload_path = 'storage/uploads/' . date('Ymd'); | ||||
|         $path = app()->getRootPath() . $upload_path; | ||||
|         $filename = uniqid() . '.' . $file->extension(); | ||||
|         $upload_filename = '/' . $upload_path . '/' . $filename; | ||||
|         return [$file->move($path, $filename), $file, $upload_filename]; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 文件访问路径转换为完整的url | ||||
|      * @param string|null $fileUrl | ||||
|      * @param bool $ossAnalysis 是否进行OSS解析 | ||||
|      * @return string | ||||
|      * @todo 若启用OOS存储,需根据业务配置调整$fileDomain | ||||
|      * | ||||
|      */ | ||||
|     public static function convertCompleteFileUrl(?string $fileUrl, bool $ossAnalysis=true): string | ||||
|     { | ||||
|         if (empty($fileUrl)) { | ||||
|             return ''; | ||||
|         } | ||||
|         if ($ossAnalysis) { | ||||
|             $fileDomain = self::getFileDomain(); | ||||
|         } else { | ||||
|             $fileDomain = request()->domain(); | ||||
|         } | ||||
|         $prefix = substr($fileUrl, 0, 4); | ||||
|         if (!($prefix == 'http')) { | ||||
|             $fileUrl    = $fileDomain.'/'.ltrim($fileUrl, '/'); | ||||
|         } | ||||
| 
 | ||||
|         return $fileUrl; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 文件访问域名前缀 | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
|     public static function getFileDomain(): string | ||||
|     { | ||||
|         $confBase   = ExtraConfig::base(); | ||||
|         $confOss    = ExtraConfig::aliOss(); | ||||
|         $isOss      = $confBase['oss'] ?? 'false'; | ||||
|         $ossDomain  = $confOss['customDomain'] ?? ''; | ||||
| 
 | ||||
|         // 默认为当前域名
 | ||||
|         $fileDomain = request()->domain(); | ||||
|         if ($isOss == 'true' && !empty($ossDomain)) { | ||||
|             $fileDomain = $ossDomain; | ||||
|         } | ||||
| 
 | ||||
|         $fileDomain = trim($fileDomain); | ||||
|         return rtrim($fileDomain, '/'); | ||||
|     } | ||||
| } | ||||
Some files were not shown because too many files have changed in this diff Show More
		Loading…
	
		Reference in New Issue