setter
commit
4aab76d038
|
@ -0,0 +1,19 @@
|
|||
APP_DEBUG = true
|
||||
APP_TRACE = true
|
||||
|
||||
[APP]
|
||||
DEFAULT_TIMEZONE = Asia/Shanghai
|
||||
|
||||
[DATABASE]
|
||||
TYPE = mysql
|
||||
HOSTNAME = 127.0.0.1
|
||||
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,674 @@
|
|||
<?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;
|
||||
}
|
||||
}
|
||||
|
||||
// 是否http开头
|
||||
if (!function_exists('isHttpUrl')) {
|
||||
function isHttpUrl(string $url): bool
|
||||
{
|
||||
return substr(trim($url), 0, 4) == 'http';
|
||||
}
|
||||
}
|
||||
|
||||
//富文本中提取视频路径
|
||||
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值转为空字符串,并以数组格式返回
|
||||
* 通常用于api json 返回内容null转换
|
||||
*
|
||||
* @param array $data 【array|collection】
|
||||
* @return array
|
||||
*/
|
||||
function arrayNullToString($data)
|
||||
{
|
||||
if ($data instanceof Collection || $data instanceof Model) {
|
||||
$data = $data->toArray();
|
||||
}
|
||||
// 判断是否可以遍历
|
||||
if (is_iterable($data)) {
|
||||
foreach ($data as $key => $val) {
|
||||
if ($val instanceof Collection || $data instanceof Model) {
|
||||
$val = $val->toArray();
|
||||
}
|
||||
if (is_iterable($val)) {
|
||||
$data[$key] = arrayNullToString($val);
|
||||
} elseif ($val === null) {
|
||||
$data[$key] = '';
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$data = [];
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('resourceJoin')) {
|
||||
/**
|
||||
* 资源拼接前缀 如/xxx/xxxx/xxx.jpg 拼接为前缀http://www.xxx.com/xxx/xxxx/xxx.jpg
|
||||
*
|
||||
* @param string $string
|
||||
* @param string $domain
|
||||
* @return string
|
||||
*/
|
||||
function resourceJoin(string $string, string $domain): string
|
||||
{
|
||||
if (empty($string)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (isHttpUrl($string)) {
|
||||
return $string;
|
||||
}
|
||||
|
||||
return $domain.$string;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
<?php
|
||||
|
||||
namespace app\controller;
|
||||
|
||||
/**
|
||||
* 控制器基础类
|
||||
*/
|
||||
class Base extends BaseController
|
||||
{
|
||||
//需要向模板传递的值
|
||||
protected $data = [];
|
||||
//系统配置信息
|
||||
protected $system = [];
|
||||
|
||||
protected $auth = [];
|
||||
|
||||
protected $authId = 0;
|
||||
|
||||
|
||||
// 初始化
|
||||
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,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,284 @@
|
|||
<?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()->findById($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()->findById($this->auth['id'] ?? 0)) {
|
||||
return $this->redirect('/login');
|
||||
}
|
||||
|
||||
if (!empty($account['mobile'])) {
|
||||
return $this->redirect('/');
|
||||
}
|
||||
}
|
||||
return $this->view();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,275 @@
|
|||
<?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);
|
||||
}
|
||||
|
||||
$order = ['sort' => 'desc'];
|
||||
$data = ArchivesRepository::getInstance()->category($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 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)];
|
||||
}
|
||||
|
||||
$order = ['sort' => 'desc'];
|
||||
$data = ArchivesRepository::getInstance()->category($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 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,91 @@
|
|||
<?php
|
||||
|
||||
namespace app\controller\api;
|
||||
|
||||
use app\repository\CommonRepository;
|
||||
use app\repository\OperationRepository;
|
||||
use app\repository\OrderRepository;
|
||||
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,115 @@
|
|||
<?php
|
||||
|
||||
namespace app\controller\api;
|
||||
|
||||
use app\exception\RepositoryException;
|
||||
use app\repository\AccountRepository;
|
||||
use app\service\ExtraConfig;
|
||||
use Exception;
|
||||
use think\facade\Config as CConfig;
|
||||
use think\response\Json;
|
||||
|
||||
class Index extends Base
|
||||
{
|
||||
protected $noNeedLogin = [
|
||||
'miniProgramSetting',
|
||||
'clearFootmarks',
|
||||
'baseConfig',
|
||||
'work',
|
||||
'kf',
|
||||
'hotKeywords',
|
||||
'statement',
|
||||
'about'
|
||||
];
|
||||
|
||||
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()->findById($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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 基础配置
|
||||
*
|
||||
* @return Json
|
||||
*/
|
||||
public function baseConfig(): Json
|
||||
{
|
||||
try {
|
||||
CConfig::load('extra/base', 'base');
|
||||
$res = config('base')['show_video'] ?? 0;
|
||||
return $this->json(0, 'success', ['v' => (int) $res]);
|
||||
} catch (Exception $e) {
|
||||
return $this->json(5000, '获取基础配置失败');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 免责声明
|
||||
*
|
||||
* @return Json
|
||||
*/
|
||||
public function statement(): Json
|
||||
{
|
||||
try {
|
||||
CConfig::load('extra/statement', 'statement');
|
||||
$content = config('statement')['content'] ?? '';
|
||||
return $this->json(0, 'success', ['content' => $content]);
|
||||
} catch (Exception $e) {
|
||||
return $this->json(5000, '获取免责声明失败');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 关于我们
|
||||
*
|
||||
* @return Json
|
||||
*/
|
||||
public function about(): Json
|
||||
{
|
||||
try {
|
||||
CConfig::load('extra/about', 'about');
|
||||
$res = config('about')?? [];
|
||||
return $this->json(0, 'success', $res);
|
||||
} catch (Exception $e) {
|
||||
return $this->json(5000, '获取关于我们失败');
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,430 @@
|
|||
<?php
|
||||
|
||||
namespace app\controller\api;
|
||||
|
||||
use app\exception\RepositoryException;
|
||||
use app\repository\OrderRepository;
|
||||
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;
|
||||
|
||||
$domain = $this->request->domain();
|
||||
|
||||
$data = OrderRepository::getInstance()->shoppingCart($accountId, $type, $page, $size);
|
||||
$data['list'] = $data['list']->each(function ($item) use ($domain) {
|
||||
$item->spu->spu_cover = $item->spu->spu_cover ?? '';
|
||||
$item->spu->spu_cover = resourceJoin($item->spu->spu_cover, $domain);
|
||||
});
|
||||
|
||||
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;
|
||||
$params['domain'] = $this->request->domain();
|
||||
|
||||
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);
|
||||
// 核验后事件
|
||||
event('OrderSpuCheck', $orderCoding);
|
||||
} 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, '订单商品核验结果获取失败');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取拼团ID
|
||||
*
|
||||
* @return Json
|
||||
*/
|
||||
public function getGroupId(): Json
|
||||
{
|
||||
$params = $this->request->param();
|
||||
$orderCoding = $params['order_coding'] ?? '';
|
||||
|
||||
$groupId = OrderRepository::getInstance()->groupId($orderCoding);
|
||||
|
||||
return $this->json(0, 'success', ['group_id' => $groupId]);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,179 @@
|
|||
<?php
|
||||
|
||||
namespace app\controller\api;
|
||||
|
||||
use app\exception\RepositoryException;
|
||||
use app\model\Account;
|
||||
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 (RepositoryException $e) {
|
||||
Db::rollback();
|
||||
$this->json(4003, "签到失败");
|
||||
} catch (Exception $e) {
|
||||
Db::rollback();
|
||||
$this->json(5000, "签到失败");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,385 @@
|
|||
<?php
|
||||
|
||||
namespace app\controller\api;
|
||||
|
||||
use app\controller\manager\mall\Category;
|
||||
use app\exception\RepositoryException;
|
||||
use app\model\AccountRecord;
|
||||
use app\model\Spu as SpuModel;
|
||||
use app\model\SpuActivity;
|
||||
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 $noNeedLogin = ['list', 'category', 'condition', 'detail', 'home'];
|
||||
|
||||
/**
|
||||
* 商品列表筛选条件
|
||||
*
|
||||
*/
|
||||
public function category(): Json
|
||||
{
|
||||
$list = SpuRepository::getInstance()->category()->toArray();
|
||||
|
||||
return $this->json(0, 'success', $list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 商品列表筛选条件
|
||||
*
|
||||
*/
|
||||
public function condition(): Json
|
||||
{
|
||||
$list = [
|
||||
[
|
||||
'title' => '分类',
|
||||
'field' => 'category_id',
|
||||
'children' => array_merge([['name' => '全部', 'value' => '']], SpuRepository::getInstance()->category(0, ['id as value', 'title as name'])->toArray())
|
||||
],
|
||||
[
|
||||
'title' => '活动',
|
||||
'field' => 'activity',
|
||||
'children' => array_merge([['name' => '全部', 'value' => '']], SpuModel::activity())
|
||||
]
|
||||
];
|
||||
|
||||
return $this->json(0, 'success', $list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 首页商品列表
|
||||
*
|
||||
* @return Json
|
||||
* @throws RepositoryException
|
||||
* @throws Exception
|
||||
*/
|
||||
public function home(): Json
|
||||
{
|
||||
$repo = SpuRepository::getInstance();
|
||||
|
||||
$fields = [
|
||||
'id', 'name', 'subtitle', 'price', 'original_price', 'cover', 'home_display', 'stock', 'amount','activity_id','activity_type'
|
||||
];
|
||||
|
||||
$params = input();
|
||||
$params['fields'] = $fields;
|
||||
$params['is_home'] = SpuModel::COMMON_ON;
|
||||
$params['is_score'] = SpuModel::COMMON_OFF;//排除积分商品
|
||||
|
||||
if (!isset($params['category_id']) || empty($params['category_id'])) {
|
||||
$params['category_id'] = \app\model\mall\Category::getFirst();
|
||||
}
|
||||
|
||||
$list = $repo->listForFront($params, function ($q) {
|
||||
return $q->withAttr('cover', function ($value, $data) {
|
||||
return resourceJoin($value, $this->request->domain());
|
||||
});
|
||||
});
|
||||
|
||||
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->withAttr('cover', function ($value, $data) {
|
||||
return resourceJoin($value, $this->request->domain());
|
||||
});
|
||||
});
|
||||
|
||||
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->withAttr('cover', function ($value, $data) {
|
||||
return resourceJoin($value, $this->request->domain());
|
||||
});
|
||||
}, $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->withAttr('cover', function ($value, $data) {
|
||||
return resourceJoin($value, $this->request->domain());
|
||||
});
|
||||
}, [], $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);
|
||||
$accountId = $this->request->user['user_id'] ?? 0;
|
||||
$domain = $this->request->domain();
|
||||
|
||||
try {
|
||||
$data = $repo->detail($id, $accountId);
|
||||
$data['detail']['cover'] = $data['detail']['cover'] ?? '';
|
||||
$data['detail']['cover'] = resourceJoin($data['detail']['cover'], $domain);
|
||||
|
||||
$data['detail']['share_img'] = $data['detail']['share_img'] ?? '';
|
||||
$data['detail']['share_img'] = resourceJoin($data['detail']['share_img'], $domain);
|
||||
|
||||
if(isset($data['detail']['images']) && !empty($data['detail']['images'])){
|
||||
$images = explode(',', $data['detail']['images']);
|
||||
$imageArr = [];
|
||||
foreach ($images as $image) {
|
||||
if(!empty($image)){
|
||||
$imageArr[] = resourceJoin($image, $domain);
|
||||
}
|
||||
}
|
||||
$data['detail']['images'] = implode(',', $imageArr);
|
||||
}
|
||||
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 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();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取商品规格信息
|
||||
*
|
||||
* @return Json
|
||||
* @throws RepositoryException
|
||||
* @throws DataNotFoundException
|
||||
* @throws DbException
|
||||
* @throws ModelNotFoundException
|
||||
*/
|
||||
public function spec(): Json
|
||||
{
|
||||
$spuId = input('id');
|
||||
return $this->json(0, 'success', SpuRepository::getInstance()->getSpec($spuId));
|
||||
}
|
||||
}
|
|
@ -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('files/'.date('Ym'), $file, 'uniqid');
|
||||
$src = $this->uploadPath . '/' . $src;
|
||||
$return['src'] = $src;
|
||||
$return['name'] = $file->getOriginalName();
|
||||
|
||||
//加入上传文件表
|
||||
File::add($file, $src, $file->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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 通用图片上传
|
||||
* @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('images/'.date('Ym'), $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,353 @@
|
|||
<?php
|
||||
|
||||
namespace app\controller\manager;
|
||||
|
||||
use app\model\Log;
|
||||
use app\model\Archives as ArchivesModel;
|
||||
use app\model\ArchivesCategory as ArticleCategoryModel;
|
||||
use app\model\ArchivesModelField;
|
||||
use app\model\Config;
|
||||
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 Archives
|
||||
* @package app\controller\manager
|
||||
*/
|
||||
class Archives extends Base
|
||||
{
|
||||
protected $noNeedLogin = [];
|
||||
|
||||
/**
|
||||
* 删除
|
||||
*
|
||||
* @return Json
|
||||
*/
|
||||
public function del(): Json
|
||||
{
|
||||
if ($this->request->isPost()) {
|
||||
$ids = input('post.ids/a', []);
|
||||
if (empty($ids)) {
|
||||
$ids[] = input('post.id/d');
|
||||
}
|
||||
ArchivesModel::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 = ArchivesModel::findById($id)) {
|
||||
return $this->json(4001, '记录不存在');
|
||||
}
|
||||
|
||||
if ($this->request->isPost()) {
|
||||
$item = input('post.');
|
||||
if (isset($item['video_src'])) {
|
||||
$item['video'] = $item['video_src'];
|
||||
unset($item['video_src']);
|
||||
}
|
||||
|
||||
$validate = $this->validateByApi($item, [
|
||||
'category_id|栏目' => 'require|gt:0',
|
||||
'title|标题' => 'require|max:255',
|
||||
'summary|摘要' => 'max:255',
|
||||
'content|内容' => 'require',
|
||||
], ['category_id.gt' => '请选择栏目']);
|
||||
|
||||
if ($validate !== true) {
|
||||
return $validate;
|
||||
}
|
||||
|
||||
try {
|
||||
$now = date('Y-m-d H:i:s');
|
||||
$item['updated_at'] = $now;
|
||||
$item['updated_by'] = $this->auth['user_id'];
|
||||
$info->save($item);
|
||||
return $this->json();
|
||||
} catch (ValidateException $e) {
|
||||
return $this->json(4001, $e->getError());
|
||||
}
|
||||
}
|
||||
|
||||
$showFieldList = ArchivesModelField::showFieldList();//所有栏目 可展示字段列表
|
||||
$currentShowFields = $showFieldList[$info['category_id']] ?? [];//当前选中栏目 可展示字段列表
|
||||
|
||||
$this->data['item'] = $info;
|
||||
$this->data['jsonList'] = $this->xmSelectJson([$info['category_id']]);
|
||||
$this->data['showList'] = json_encode($showFieldList, JSON_UNESCAPED_UNICODE);
|
||||
$this->data['currentList'] = $currentShowFields;
|
||||
|
||||
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 = ArchivesModel::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()
|
||||
{
|
||||
$categoryId = input('category_id/d', 0);
|
||||
|
||||
if ($this->request->isPost()) {
|
||||
$item = input('post.');
|
||||
if (isset($item['video_src'])) {
|
||||
$item['video'] = $item['video_src'];
|
||||
unset($item['video_src']);
|
||||
}
|
||||
|
||||
$validate = $this->validateByApi($item, [
|
||||
'category_id|栏目' => 'require|gt:0',
|
||||
'title|标题' => 'require|max:255',
|
||||
'summary|摘要' => 'max:255',
|
||||
'content|内容' => 'require',
|
||||
], ['category_id.gt' => '请选择栏目']);
|
||||
|
||||
if ($validate !== true) {
|
||||
return $validate;
|
||||
}
|
||||
|
||||
try {
|
||||
$now = date('Y-m-d H:i:s');
|
||||
$item['created_at'] = $now;
|
||||
$item['published_at'] = $now;
|
||||
$item['created_by'] = $this->auth['user_id'];
|
||||
ArchivesModel::create($item);
|
||||
|
||||
return $this->json();
|
||||
} catch (ValidateException $e) {
|
||||
return $this->json(4001, $e->getError());
|
||||
}
|
||||
}
|
||||
|
||||
$showFieldList = ArchivesModelField::showFieldList();//所有栏目 可展示字段列表
|
||||
//有指定栏目获取指定栏目 否则获取第一个 可展示字段列表
|
||||
$currentShowFields = $categoryId > 0 ? ($showFieldList[$categoryId] ?? []) : array_values($showFieldList)[0];
|
||||
|
||||
$this->data['categoryId'] = $categoryId ?? 0;
|
||||
$this->data['jsonList'] = $this->xmSelectJson([$categoryId]);
|
||||
$this->data['showList'] = json_encode($showFieldList, JSON_UNESCAPED_UNICODE);
|
||||
$this->data['currentList'] = $currentShowFields;
|
||||
|
||||
return $this->view();
|
||||
}
|
||||
|
||||
/**
|
||||
* 列表
|
||||
*
|
||||
* @return View|Json
|
||||
* @throws Exception
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$categoryId = input('category_id/d', 0);
|
||||
if ($this->request->isPost()) {
|
||||
$page = input('page/d', 1);
|
||||
$limit = input('size/d', 20);
|
||||
$searchParams = input('searchParams');
|
||||
$where = [];
|
||||
|
||||
if ($categoryId > 0) {
|
||||
$where[] = ['category_id', '=', $categoryId];
|
||||
}
|
||||
|
||||
if ($searchParams) {
|
||||
foreach ($searchParams as $key => $param) {
|
||||
if (!empty($param)) {
|
||||
if (is_string($param)) {
|
||||
$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];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$items = ArchivesModel::findList($where, [], $page, $limit, function ($q) {
|
||||
return $q->with(['member', 'category'])
|
||||
->order('top', 'desc')
|
||||
->order('recommend', 'desc')
|
||||
->order('hot', 'desc')
|
||||
->order('sort', 'desc')
|
||||
->order('id', 'desc');
|
||||
});
|
||||
|
||||
$diseaseCategoryIds = ArticleCategoryModel::diseaseCategoryIds();
|
||||
$items['list'] = $items['list']->each(function ($item) use ($diseaseCategoryIds) {
|
||||
$item->mpPath = in_array($item['category_id'], $diseaseCategoryIds) ? Config::MINI_PATH_PROBLEM : Config::MINI_PATH_ARCHIVES;
|
||||
});
|
||||
|
||||
return $this->json(0, '操作成功', $items);
|
||||
}
|
||||
|
||||
$selected = $categoryId > 0 ? [$categoryId] : [];
|
||||
|
||||
$this->data['categoryId'] = $categoryId;
|
||||
$this->data['categoryJson'] = $this->categoryJson($selected);
|
||||
$this->data['archivesPath'] = '/'.Config::MINI_PATH_ARCHIVES;
|
||||
|
||||
return $this->view();
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造分类 json数据[zTree用]
|
||||
*
|
||||
* @param array $selected
|
||||
* @return false|string
|
||||
* @throws DataNotFoundException
|
||||
* @throws DbException
|
||||
* @throws ModelNotFoundException
|
||||
*/
|
||||
private function categoryJson(array $selected = [])
|
||||
{
|
||||
$category = ArticleCategoryModel::order('sort', 'desc')
|
||||
->field('id,pid,title')
|
||||
->select()
|
||||
->toArray();
|
||||
foreach ($category as $k => $m) {
|
||||
$category[$k]['checked'] = in_array($m['id'], $selected);
|
||||
$category[$k]['spread'] = true;
|
||||
}
|
||||
|
||||
$category = CmsRepository::getInstance()->buildMenuChild(0, $category);
|
||||
return json_encode($category, JSON_UNESCAPED_UNICODE);
|
||||
}
|
||||
|
||||
/**
|
||||
* 内容分类 构造xmSelect json数据[xmSelect用]
|
||||
*
|
||||
* @param array $selected
|
||||
* @param array $disabled
|
||||
* @return false|string
|
||||
* @throws DataNotFoundException
|
||||
* @throws DbException
|
||||
* @throws ModelNotFoundException
|
||||
*/
|
||||
private function xmSelectJson(array $selected = [], array $disabled = [])
|
||||
{
|
||||
$category = ArticleCategoryModel::order('sort', 'desc')
|
||||
->field('id,pid,title,model_id')
|
||||
->select();
|
||||
$modelList = \app\model\ArchivesModel::column('title', 'id');
|
||||
|
||||
$category->each(function ($item) use ($modelList) {
|
||||
$item->title = sprintf("%s-[所属模型:%s]", $item->title, $modelList[$item->model_id]);
|
||||
});
|
||||
$category = $category->toArray();
|
||||
foreach ($category as $k => $m) {
|
||||
$category[$k]['selected'] = in_array($m['id'], $selected);
|
||||
$category[$k]['disabled'] = in_array($m['id'], $disabled);
|
||||
}
|
||||
|
||||
$category = CmsRepository::getInstance()->buildMenuChild(0, $category);
|
||||
$category = CmsRepository::getInstance()->handleSelectedList($category);
|
||||
return json_encode($category, JSON_UNESCAPED_UNICODE);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量审核
|
||||
*
|
||||
* @return View|Json
|
||||
* @throws Exception
|
||||
*/
|
||||
public function check()
|
||||
{
|
||||
$id = input('id/s', '');
|
||||
if ($this->request->isPost()) {
|
||||
$ids = input('ids/s');
|
||||
$check = input('is_check/d');
|
||||
|
||||
if (!in_array($check, [ArchivesModel::COMMON_ON, ArchivesModel::COMMON_OFF])) {
|
||||
|
||||
return $this->json(4001, '请选择是否展示');
|
||||
}
|
||||
|
||||
$ids = explode(',', $ids);
|
||||
|
||||
Db::startTrans();
|
||||
try {
|
||||
(new ArchivesModel())->whereIn('id', $ids)->save(['is_check' => $check]);
|
||||
Db::commit();
|
||||
return $this->json(0, '操作成功');
|
||||
} catch (Exception $e) {
|
||||
Db::rollback();
|
||||
Log::error('批量审核操作失败'.$e->getMessage());
|
||||
return $this->json(5001, '批量审核操作失败');
|
||||
}
|
||||
}
|
||||
|
||||
$this->data['id'] = $id;
|
||||
|
||||
return $this->view();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,251 @@
|
|||
<?php
|
||||
|
||||
namespace app\controller\manager;
|
||||
|
||||
use app\repository\CmsRepository;
|
||||
use app\model\Log;
|
||||
use app\model\ArchivesCategory as ArchivesCategoryModel;
|
||||
|
||||
use app\validate\MenuValidate;
|
||||
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 Menu
|
||||
* @package app\controller\manager
|
||||
*/
|
||||
class ArchivesCategory 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');
|
||||
}
|
||||
if (ArchivesCategoryModel::hasChildrenByIds($ids)) {
|
||||
return $this->json(4002, '待删除数据存在子数据');
|
||||
}
|
||||
|
||||
if (ArchivesCategoryModel::hasContentByIds($ids)) {
|
||||
return $this->json(4002, '待删除数据存在内容文章');
|
||||
}
|
||||
ArchivesCategoryModel::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 = ArchivesCategoryModel::findById($id)) {
|
||||
return $this->json(4001, '记录不存在');
|
||||
}
|
||||
|
||||
if ($this->request->isPost()) {
|
||||
$item = input('post.');
|
||||
$validate = $this->validateByApi($item, [
|
||||
'pid|父级分类' => 'require|number',
|
||||
'model_id|所属模型' => 'require|number|gt:0',
|
||||
'title|标题' => 'require|max:100',
|
||||
'name|标识' => 'unique:archives_category,name,'.$info['id'] ?? 0,
|
||||
'description|描述' => 'max:255',
|
||||
], ['model_id' => '所属模型必需选择']);
|
||||
|
||||
if ($validate !== true) {
|
||||
return $validate;
|
||||
}
|
||||
|
||||
Db::startTrans();
|
||||
try {
|
||||
$oldPath = $info['path'] ?? '';
|
||||
$item['path'] = ArchivesCategoryModel::getPath($item['pid']);
|
||||
$info->save($item);
|
||||
|
||||
//刷新所有路径
|
||||
$oldPath = $oldPath.','.$id;
|
||||
$newPath = $item['path'].','.$id;
|
||||
if ($oldPath != $newPath) {
|
||||
ArchivesCategoryModel::refreshPath();
|
||||
}
|
||||
Db::commit();
|
||||
return $this->json();
|
||||
} catch (ValidateException $e) {
|
||||
Db::rollback();
|
||||
return $this->json(4001, $e->getError());
|
||||
}
|
||||
}
|
||||
|
||||
$disabled = ArchivesCategoryModel::getAllChildrenIds($id);
|
||||
$disabled[] = $id;
|
||||
$this->data['jsonList'] = $this->categoryJson([$info['pid']], $disabled);
|
||||
$this->data['modelList'] = $this->modelJson([$info['model_id']], []);
|
||||
$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 = ArchivesCategoryModel::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',
|
||||
'model_id|所属模型' => 'require|number|gt:0',
|
||||
'title|标题' => 'require|max:100',
|
||||
'name|标识' => 'require|unique:archives_category',
|
||||
'description|描述' => 'max:255',
|
||||
], ['model_id' => '所属模型必需选择']);
|
||||
|
||||
if ($validate !== true) {
|
||||
return $validate;
|
||||
}
|
||||
try {
|
||||
$item['path'] = ArchivesCategoryModel::getPath($item['pid']);
|
||||
ArchivesCategoryModel::create($item);
|
||||
return $this->json();
|
||||
} catch (ValidateException $e) {
|
||||
return $this->json(4001, $e->getError());
|
||||
}
|
||||
}
|
||||
|
||||
$this->data['jsonList'] = $this->categoryJson();
|
||||
$this->data['modelList'] = $this->modelJson();
|
||||
|
||||
return $this->view();
|
||||
}
|
||||
|
||||
/**
|
||||
* 列表
|
||||
*
|
||||
* @return Json|View
|
||||
* @throws DataNotFoundException
|
||||
* @throws DbException
|
||||
* @throws ModelNotFoundException
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
if ($this->request->isPost()) {
|
||||
$menus = ArchivesCategoryModel::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[] = ['title' => '顶级分类', 'id' => 0, 'disabled' => false, 'selected' => in_array(0, $selected)];
|
||||
$menus = ArchivesCategoryModel::getList();
|
||||
$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);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $selected
|
||||
* @param array $disabled
|
||||
* @return false|string
|
||||
* @throws DataNotFoundException
|
||||
* @throws DbException
|
||||
* @throws ModelNotFoundException
|
||||
*/
|
||||
private function modelJson(array $selected = [], array $disabled = [])
|
||||
{
|
||||
$categoryList[] = ['title' => '全部', 'id' => 0, 'disabled' => false, 'selected' => in_array(0, $selected)];
|
||||
$menus = \app\model\ArchivesModel::field('id,0 as pid,title,name,sort,true as open')
|
||||
->order('sort', 'desc')
|
||||
->order('id', 'asc')
|
||||
->select();;
|
||||
$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,173 @@
|
|||
<?php
|
||||
|
||||
|
||||
namespace app\controller\manager;
|
||||
|
||||
use app\model\Log;
|
||||
use Exception;
|
||||
use app\model\ArchivesModel as MArchivesModel;
|
||||
use app\model\Archives;
|
||||
use app\model\ArchivesModelField;
|
||||
use think\exception\ValidateException;
|
||||
use think\facade\Db;
|
||||
use think\response\Json;
|
||||
use think\response\View;
|
||||
|
||||
/**
|
||||
* 文档模型管理
|
||||
* Class ArchivesModel
|
||||
* @package app\controller\manager
|
||||
*/
|
||||
class ArchivesModel 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');
|
||||
}
|
||||
$groupNames = MArchivesModel::whereIn('id', $ids)->column('name');
|
||||
if (ArchivesModelField::whereIn('name', $groupNames)->count() > 0) {
|
||||
return $this->json(4002, '模型下已存在字段,无法删除!');
|
||||
}
|
||||
|
||||
MArchivesModel::deleteByIds($ids);
|
||||
|
||||
// Log::write(get_class().'Del', 'del', '涉及到的ID为:'.implode(',', $ids));
|
||||
return $this->json();
|
||||
}
|
||||
return $this->json(4001, '非法请求!');
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑
|
||||
*
|
||||
* @return Json|View
|
||||
* @throws Exception
|
||||
*/
|
||||
public function edit()
|
||||
{
|
||||
$id = input('id/d', 0);
|
||||
|
||||
if (!$info = MArchivesModel::findById($id)) {
|
||||
return $this->json(4001, '记录不存在');
|
||||
}
|
||||
|
||||
if ($this->request->isPost()) {
|
||||
$item = input('post.');
|
||||
$validate = $this->validateByApi($item, [
|
||||
'title|模型标题' => 'require',
|
||||
'name|模型标识' => 'alphaDash|unique:archives_model,name,'.$id,
|
||||
]);
|
||||
|
||||
if ($validate !== true) {
|
||||
return $validate;
|
||||
}
|
||||
|
||||
try {
|
||||
ArchivesModelField::setFieldList($id, $info['name']);
|
||||
$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 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 = MArchivesModel::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',
|
||||
'name|模型标识' => 'require|alphaDash|unique:archives_model',
|
||||
]);
|
||||
|
||||
if ($validate !== true) {
|
||||
return $validate;
|
||||
}
|
||||
|
||||
try {
|
||||
$model = MArchivesModel::create($item);
|
||||
ArchivesModelField::setFieldList($model['id'], $model['name']);
|
||||
return $this->json();
|
||||
} catch (ValidateException $e) {
|
||||
return $this->json(4001, $e->getError());
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
$items = MArchivesModel::findList([], [], $page, $limit, function ($q) {
|
||||
return $q->order('sort', 'desc')->order('id', 'asc');
|
||||
});
|
||||
|
||||
return $this->json(0, '操作成功', $items);
|
||||
}
|
||||
return $this->view();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,210 @@
|
|||
<?php
|
||||
|
||||
|
||||
namespace app\controller\manager;
|
||||
|
||||
use app\model\Log;
|
||||
use Exception;
|
||||
use app\model\ArchivesModelField as MArchivesModelField;
|
||||
use app\model\ArchivesModel;
|
||||
use think\exception\ValidateException;
|
||||
use think\response\Json;
|
||||
use think\response\View;
|
||||
|
||||
/**
|
||||
* 文档模型字段管理
|
||||
* Class ArchivesModelField
|
||||
* @package app\controller\manager
|
||||
*/
|
||||
class ArchivesModelField 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');
|
||||
}
|
||||
|
||||
MArchivesModelField::deleteByIds($ids);
|
||||
|
||||
// Log::write(get_class().'Del', 'del', '涉及到的ID为:'.implode(',', $ids));
|
||||
return $this->json();
|
||||
}
|
||||
return $this->json(4001, '非法请求!');
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑
|
||||
*
|
||||
* @return Json|View
|
||||
* @throws Exception
|
||||
*/
|
||||
public function edit()
|
||||
{
|
||||
$id = input('id/d', 0);
|
||||
|
||||
if (!$info = MArchivesModelField::findById($id)) {
|
||||
return $this->json(4001, '记录不存在');
|
||||
}
|
||||
|
||||
if ($this->request->isPost()) {
|
||||
$item = input('post.');
|
||||
$validate = $this->validateByApi($item, [
|
||||
'title|模型标题' => 'require',
|
||||
'name|模型标识' => 'alphaDash',
|
||||
]);
|
||||
|
||||
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 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 = MArchivesModelField::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()
|
||||
{
|
||||
$modelId = input('model_id/d', 0);
|
||||
|
||||
if ($this->request->isPost()) {
|
||||
$item = input('post.');
|
||||
$item['model_id'] = $modelId;
|
||||
|
||||
$validate = $this->validateByApi($item, [
|
||||
'title|字段标题' => 'require',
|
||||
'model_id|模型' => 'require|number|gt:0',
|
||||
'name|字段标识' => 'require|alphaDash|unique:archives_model_field',
|
||||
], ['model_id.gt' => '模型不存在']);
|
||||
|
||||
if ($validate !== true) {
|
||||
return $validate;
|
||||
}
|
||||
|
||||
try {
|
||||
MArchivesModelField::create($item);
|
||||
return $this->json();
|
||||
} catch (ValidateException $e) {
|
||||
return $this->json(4001, $e->getError());
|
||||
}
|
||||
}
|
||||
|
||||
$this->data['modelId'] = $modelId;
|
||||
|
||||
return $this->view();
|
||||
}
|
||||
|
||||
/**
|
||||
* 列表
|
||||
*
|
||||
* @return View|Json
|
||||
* @throws Exception
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$modelId = input('model_id/d', 0);
|
||||
if (!$modelId) {
|
||||
return $this->json(4001, '请选择正确的模型');
|
||||
}
|
||||
|
||||
if ($this->request->isPost()) {
|
||||
$page = input('page/d', 1);
|
||||
$limit = input('size/d', 20);
|
||||
$where[] = ['model_id', '=', $modelId];
|
||||
$items = MArchivesModelField::findList($where, [], $page, $limit, function ($q) {
|
||||
return $q->order('status', 'desc')->order('id', 'asc');
|
||||
});
|
||||
|
||||
return $this->json(0, '操作成功', $items);
|
||||
}
|
||||
|
||||
$this->data['modelId'] = $modelId;
|
||||
|
||||
return $this->view();
|
||||
}
|
||||
|
||||
/**
|
||||
* 同步字段
|
||||
*
|
||||
* @return Json
|
||||
* @throws Exception
|
||||
*/
|
||||
public function sync(): Json
|
||||
{
|
||||
if ($this->request->isPost()) {
|
||||
$modelId = input('model_id/d', 0);
|
||||
|
||||
if (!$modelId) {
|
||||
return $this->json(4001, '模型错误');
|
||||
}
|
||||
|
||||
|
||||
if (!$info = ArchivesModel::findOne(['id' => $modelId])) {
|
||||
return $this->json(4001, '模型不存在');
|
||||
}
|
||||
|
||||
try {
|
||||
MArchivesModelField::syncFieldList($modelId, $info['name']);
|
||||
return $this->json();
|
||||
} catch (ValidateException $e) {
|
||||
return $this->json(4001, $e->getError());
|
||||
}
|
||||
}
|
||||
return $this->json(4000, '非法请求');
|
||||
}
|
||||
}
|
|
@ -0,0 +1,501 @@
|
|||
<?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::load('extra/base', 'base');
|
||||
$config = config('alioss');
|
||||
$baseConfig = config('base');
|
||||
|
||||
$oss = $baseConfig['oss'] == 'true' ? $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::load('extra/base', 'base');
|
||||
$config = config('alioss');
|
||||
$baseConfig = config('base');
|
||||
$oss = $baseConfig['oss'] == 'true' ? $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');
|
||||
$baseConfig = config('base');
|
||||
$oss = $baseConfig['oss'] == 'true' ? $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::load('extra/base', 'base');
|
||||
$config = config('alioss');
|
||||
$baseConfig = config('base');
|
||||
if ($baseConfig['oss'] != 'true') {
|
||||
return $this->json('4000', '配置未开启OSS上传');
|
||||
}
|
||||
|
||||
$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,105 @@
|
|||
<?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)],
|
||||
'log'
|
||||
// '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,307 @@
|
|||
<?php
|
||||
|
||||
namespace app\controller\manager;
|
||||
|
||||
use app\exception\RepositoryException;
|
||||
use app\model\Account;
|
||||
use app\model\AccountDataLog;
|
||||
use app\model\AccountWithdrawalCommission;
|
||||
use app\repository\AccountRepository;
|
||||
use app\service\Math;
|
||||
use Exception;
|
||||
use think\facade\Db;
|
||||
use think\response\Json;
|
||||
use think\response\View;
|
||||
|
||||
/**
|
||||
* 佣金
|
||||
*
|
||||
* Class Commission
|
||||
* @package app\controller\manager
|
||||
*/
|
||||
class Commission extends Base
|
||||
{
|
||||
/**
|
||||
* 操作用户佣金
|
||||
* */
|
||||
public function operation()
|
||||
{
|
||||
$accountId = input('account_id/d');
|
||||
$type = input('type/s', 'commission');
|
||||
if ($this->request->isPost()) {
|
||||
|
||||
$num = input("num/f", 1);
|
||||
$remark = input("remark/s", "");
|
||||
|
||||
$account = AccountRepository::getInstance()->getModel()->findOne(["id" => $accountId], [], function ($q) {
|
||||
return $q->lock(true);
|
||||
});
|
||||
if (empty($account)) {
|
||||
return $this->json(4001, "用户不存在");
|
||||
}
|
||||
Db::startTrans();
|
||||
try {
|
||||
|
||||
$saveData = [$type => ($account[$type] + $num)];
|
||||
|
||||
//写入用户记录
|
||||
AccountDataLog::log($accountId,
|
||||
"后台操作",
|
||||
$num,
|
||||
$type,
|
||||
AccountDataLog::ACTION_ADMIN_OPERATION,
|
||||
($account[$type] + $num),
|
||||
$this->auth['nickname'] ?? "",
|
||||
$this->auth['user_id'] ?? 0,
|
||||
$remark
|
||||
);
|
||||
|
||||
//保存用户
|
||||
$account->save($saveData);
|
||||
|
||||
Db::commit();
|
||||
return $this->json();
|
||||
} catch (RepositoryException $e) {
|
||||
Db::rollback();
|
||||
return $this->json("4000", "佣金操作失败:".$e->getMessage());
|
||||
} catch (Exception $e) {
|
||||
Db::rollback();
|
||||
\think\facade\Log::error('佣金操作失败'.$e->getMessage().' file:'.$e->getFile().' line:'.$e->getLine());
|
||||
return $this->json("5003", "佣金操作失败");
|
||||
}
|
||||
|
||||
}
|
||||
$this->data["accountId"] = $accountId;
|
||||
$this->data["type"] = $type;
|
||||
return $this->view();
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理搜索条件
|
||||
*
|
||||
* @param array $searchParams
|
||||
* @return array[]
|
||||
*/
|
||||
protected function handleSearch(array $searchParams): array
|
||||
{
|
||||
$search = [];
|
||||
$accountWhere = [];
|
||||
if (!empty($searchParams)) {
|
||||
foreach ($searchParams as $key => $param) {
|
||||
if (!empty($param)) {
|
||||
if (in_array($key, ['created_at', 'change_type', 'action'])) {
|
||||
switch ($key) {
|
||||
case 'created_at':
|
||||
case 'action':
|
||||
$search[] = ['self.'.$key, 'like', '%'.$param.'%'];
|
||||
break;
|
||||
case 'change_type':
|
||||
$search[] = $param == 'in' ? ['num', '>', 0] : ['num', '<', 0];
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
$accountWhere[] = [$key, 'like', '%'.$param.'%'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ['search' => $search, 'accountWhere' => $accountWhere];
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户佣金排行 按降序排列
|
||||
*
|
||||
* @return Json|View
|
||||
* @throws Exception
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
if ($this->request->isPost()) {
|
||||
$page = input('page/d', 1);
|
||||
$limit = input('size/d', 10);
|
||||
$params = input('searchParams');
|
||||
$keyword = $params['keyword'] ?? '';
|
||||
|
||||
$where[] = ['phone_active', '=', Account::COMMON_ON];
|
||||
$items = AccountRepository::getInstance()->findList($where, [], $page, $limit, function ($q) use ($keyword) {
|
||||
return $q->when(!empty($keyword), function ($qa) use ($keyword) {
|
||||
$qa->where('real_name|mobile|nickname', 'like', '%'.$keyword.'%');
|
||||
});
|
||||
}, ["commission" => "desc", "id" => "desc"]);
|
||||
|
||||
return $this->json(0, '操作成功', $items);
|
||||
}
|
||||
|
||||
return $this->view();
|
||||
}
|
||||
|
||||
/**
|
||||
* 查看单个用户的佣金记录
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function personal()
|
||||
{
|
||||
$accountId = input("account_id/d", 0);
|
||||
if ($this->request->isPost()) {
|
||||
$page = input('page/d', 1);
|
||||
$limit = input('size/d', 10);
|
||||
$search = [];
|
||||
$search[] = ["account_id", '=', $accountId];
|
||||
$search[] = ["type", '=', AccountDataLog::TYPE_COMMISSION];
|
||||
$items = AccountDataLog::findList($search, [], $page, $limit,
|
||||
function ($q) {
|
||||
return $q->with(["account"]);
|
||||
}, ["id" => "desc"]);
|
||||
$items['list'] = $items['list']->each(function ($item) {
|
||||
$item->nickname = $item->account->nickname ?? '';
|
||||
$item->real_name = $item->account->real_name ?? '';
|
||||
$item->mobile = $item->account->mobile ?? '';
|
||||
});
|
||||
return $this->json(0, '操作成功', $items);
|
||||
}
|
||||
|
||||
$this->data["accountId"] = $accountId;
|
||||
return $this->view();
|
||||
}
|
||||
|
||||
/**
|
||||
* 查看所有用户的佣金记录
|
||||
**/
|
||||
public function log()
|
||||
{
|
||||
$accountId = input('account_id', 0);
|
||||
if ($this->request->isPost()) {
|
||||
$page = input('page/d', 1);
|
||||
$limit = input('size/d', 10);
|
||||
|
||||
$searchParams = input('searchParams', []);
|
||||
|
||||
$accountWhere = [];
|
||||
$search = [];
|
||||
$search[] = ["type", '=', AccountDataLog::TYPE_COMMISSION];
|
||||
if ($accountId > 0) {
|
||||
$search[] = ["self.account_id", '=', $accountId];
|
||||
}
|
||||
|
||||
$searchArr = $this->handleSearch($searchParams);
|
||||
$search = !empty($searchArr['search']) ? array_merge($search, $searchArr['search']) : $search;
|
||||
$accountWhere = !empty($searchArr['accountWhere']) ? array_merge($accountWhere, $searchArr['accountWhere']) : $accountWhere;
|
||||
|
||||
$field = ['self.*', 'a.nickname', 'a.real_name', 'a.mobile'];
|
||||
$items = AccountDataLog::findList($search, $field, $page, $limit,
|
||||
function ($q) use ($accountWhere) {
|
||||
return $q->alias('self')
|
||||
->join('account a', 'a.id = self.account_id')
|
||||
->where($accountWhere);
|
||||
}, ["id" => "desc"]);
|
||||
return $this->json(0, '操作成功', $items);
|
||||
}
|
||||
|
||||
$this->data['accountId'] = $accountId;
|
||||
$this->data["changeAction"] = AccountDataLog::commissionAction();
|
||||
|
||||
return $this->view();
|
||||
}
|
||||
|
||||
/**
|
||||
* 提现列表
|
||||
* */
|
||||
public function withdrawalList()
|
||||
{
|
||||
if ($this->request->isPost()) {
|
||||
$page = input('page/d', 1);
|
||||
$limit = input('size/d', 10);
|
||||
$items = AccountWithdrawalCommission::findList([], [], $page, $limit,
|
||||
function ($q) {
|
||||
return $q->with(["account"]);
|
||||
}, ["id" => "desc"]);
|
||||
return $this->json(0, '操作成功', $items);
|
||||
}
|
||||
|
||||
return $this->view();
|
||||
}
|
||||
|
||||
/**
|
||||
* 审核提现
|
||||
* */
|
||||
public function check(): Json
|
||||
{
|
||||
$id = input("id/d");
|
||||
$status = input("status/d", null);
|
||||
if (empty($status)) {
|
||||
return $this->json(4001, "错误的状态");
|
||||
}
|
||||
|
||||
if (!$accountCoinWithdrawal = AccountWithdrawalCommission::findById($id, [])) {
|
||||
return $this->json(4001, "该提现信息不存在");
|
||||
}
|
||||
if ($accountCoinWithdrawal['status'] != AccountWithdrawalCommission::$status_default) {
|
||||
return $this->json(4001, "该提现不需要审核");
|
||||
}
|
||||
|
||||
$account = AccountRepository::getInstance()->getModel()->findOne(["id" => $accountCoinWithdrawal['account_id']], [], function ($q) {
|
||||
return $q->lock(true);
|
||||
});
|
||||
if (empty($account)) {
|
||||
return $this->json(4001, "提现用户信息不存在");
|
||||
}
|
||||
Db::startTrans();
|
||||
try {
|
||||
//如果状态是审核失败 退回佣金 写入记录
|
||||
if ($status == AccountWithdrawalCommission::$status_fail) {
|
||||
//写入--积分佣金日志
|
||||
AccountDataLog::log($accountCoinWithdrawal['account']['id'],
|
||||
'提现佣金审核失败,退回',
|
||||
$accountCoinWithdrawal['number'],
|
||||
AccountDataLog::TYPE_COMMISSION,
|
||||
AccountDataLog::ACTION_WITHDRAWAL_RETURN,
|
||||
Math::add($accountCoinWithdrawal['account']['commission'], $accountCoinWithdrawal['number'])
|
||||
);
|
||||
//退回到账户
|
||||
$account->save([
|
||||
'commission' => Math::add($accountCoinWithdrawal['account']['commission'], $accountCoinWithdrawal['number'])
|
||||
]);
|
||||
}
|
||||
|
||||
//保存状态
|
||||
$accountCoinWithdrawal->save([
|
||||
"status" => $status,
|
||||
"operator" => $this->auth["nickname"],
|
||||
"audit_at" => date("Y-m-d H:i:s")
|
||||
]);
|
||||
|
||||
Db::commit();
|
||||
return $this->json();
|
||||
} catch (RepositoryException $e) {
|
||||
Db::rollback();
|
||||
return $this->json(4000, $e->getMessage());
|
||||
} catch (Exception $e) {
|
||||
Db::rollback();
|
||||
\think\facade\Log::error('佣金提现审核失败'.$e->getMessage().' file:'.$e->getFile().' line:'.$e->getLine());
|
||||
return $this->json(5003, "审核失败");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 提现配置
|
||||
* */
|
||||
public function withdrawalConfig()
|
||||
{
|
||||
if ($this->request->isPost()) {
|
||||
try {
|
||||
$data = input("post.");
|
||||
$php = var_export($data, true);
|
||||
file_put_contents(config_path().'extra/commission_withdrawal'.'.php', '<?php'.PHP_EOL.'return '.$php.';');
|
||||
return $this->json();
|
||||
} catch (Exception $e) {
|
||||
return $this->json(4001, $e->getMessage());
|
||||
}
|
||||
}
|
||||
\think\facade\Config::load('extra/commission_withdrawal', 'commission_withdrawal');
|
||||
$coinWithdrawal = config('commission_withdrawal');
|
||||
$this->data["item"] = $coinWithdrawal;
|
||||
return $this->view("/manager/config/commission_withdrawal");
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,153 @@
|
|||
<?php
|
||||
|
||||
|
||||
namespace app\controller\manager;
|
||||
|
||||
use Exception;
|
||||
use think\facade\Config as CConfig;
|
||||
|
||||
/**
|
||||
* 额外配置
|
||||
* 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 miniProgram()
|
||||
{
|
||||
if ($this->request->isPost()) {
|
||||
$data = input("post.");
|
||||
unset($data['_token']);
|
||||
unset($data['image']);
|
||||
|
||||
// 字符串与数组转换
|
||||
$data['poster'] = empty($data['poster'] ?? '') ? [] : explode(',', $data['poster']);
|
||||
$footBarList = array_values($data['footBar'] ?? []);
|
||||
foreach ($footBarList as &$item) {
|
||||
$icons = empty($item['icon']) ? [] : explode(',', $item['icon']);
|
||||
$item['icon'] = array_filter($icons);
|
||||
}
|
||||
unset($item);
|
||||
$data['footBar'] = $footBarList;
|
||||
// 按sort排序
|
||||
$recommendList = $data['recommend'] ?? [];
|
||||
if (count($recommendList)) {
|
||||
$recommendKeys = array_column($recommendList, 'sort');
|
||||
array_multisort($recommendKeys, SORT_ASC, $recommendList);
|
||||
}
|
||||
$data['recommend'] = array_values($recommendList);
|
||||
|
||||
$php = var_export($data, true);
|
||||
file_put_contents($this->extraPath . 'mini_program.php', '<?php' . PHP_EOL . 'return ' . $php . ';');
|
||||
return $this->json();
|
||||
|
||||
} else {
|
||||
CConfig::load('extra/mini_program', 'mini_program');
|
||||
$data = config('mini_program');
|
||||
if ($data) {
|
||||
$data['poster'] = implode(',', $data['poster'] ?? []);
|
||||
$footBarList = $data['footBar'] ?? [];
|
||||
foreach ($footBarList as &$item) {
|
||||
$item['icon'] = implode(',', $item['icon'] ?? []);
|
||||
}
|
||||
unset($item);
|
||||
$data['footBar'] = $footBarList;
|
||||
}
|
||||
// 底部默认导航
|
||||
$data['footBarIcons'] = [
|
||||
['key' => 'home', 'name' => '首页', 'aux' => '图标大小为 40 * 40; 第1图为默认图,第2图为高亮图', 'multi' => 1],
|
||||
['key' => 'category', 'name' => '分类', 'aux' => '图标大小为 40 * 40; 第1图为默认图,第2图为高亮图', 'multi' => 1],
|
||||
['key' => 'my', 'name' => '我的', 'aux' => '图标大小为 40 * 40; 第1图为默认图,第2图为高亮图', 'multi' => 1],
|
||||
['key' => 'cart', 'name' => '购物车', 'aux' => '图标大小为 120 * 120', 'multi' => 0],
|
||||
];
|
||||
$this->data = array_merge($this->data, $data);
|
||||
return $this->view();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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,169 @@
|
|||
<?php
|
||||
|
||||
|
||||
namespace app\controller\manager;
|
||||
|
||||
use app\model\Log;
|
||||
use Exception;
|
||||
use app\model\ConfigGroup as ConfigGroupModel;
|
||||
use app\model\Config as ConfigModel;
|
||||
use think\exception\ValidateException;
|
||||
use think\response\Json;
|
||||
use think\response\View;
|
||||
|
||||
/**
|
||||
* 配置分组
|
||||
* Class ConfigGroup
|
||||
* @package app\controller\manager
|
||||
*/
|
||||
class ConfigGroup 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');
|
||||
}
|
||||
$groupNames = ConfigGroupModel::whereIn('id', $ids)->column('name');
|
||||
if (ConfigModel::whereIn('group', $groupNames)->count() > 0) {
|
||||
return $this->json(4002, '分组下已创建配置,无法删除!');
|
||||
}
|
||||
|
||||
ConfigGroupModel::deleteByIds($ids);
|
||||
|
||||
Log::write(get_class().'Del', 'del', '涉及到的ID为:'.implode(',', $ids));
|
||||
return $this->json();
|
||||
}
|
||||
return $this->json(4001, '非法请求!');
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑
|
||||
*
|
||||
* @return Json|View
|
||||
* @throws Exception
|
||||
*/
|
||||
public function edit()
|
||||
{
|
||||
$id = input('id/d', 0);
|
||||
|
||||
if (!$info = ConfigGroupModel::findById($id)) {
|
||||
return $this->json(4001, '记录不存在');
|
||||
}
|
||||
|
||||
if ($this->request->isPost()) {
|
||||
$item = input('post.');
|
||||
$validate = $this->validateByApi($item, [
|
||||
'title|分组标题' => 'require',
|
||||
'name|分组标识' => 'require|alphaDash|unique:config_group,name,'.$id,
|
||||
]);
|
||||
|
||||
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 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 = ConfigGroupModel::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',
|
||||
'name|分组标识' => 'require|alphaDash|unique:config_group',
|
||||
]);
|
||||
|
||||
if ($validate !== true) {
|
||||
return $validate;
|
||||
}
|
||||
|
||||
try {
|
||||
ConfigGroupModel::create($item);
|
||||
return $this->json();
|
||||
} catch (ValidateException $e) {
|
||||
return $this->json(4001, $e->getError());
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
$items = ConfigGroupModel::findList([], [], $page, $limit, function ($q) {
|
||||
return $q->order('sort', 'desc')->order('id', 'asc');
|
||||
});
|
||||
|
||||
return $this->json(0, '操作成功', $items);
|
||||
}
|
||||
return $this->view();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,226 @@
|
|||
<?php
|
||||
|
||||
|
||||
namespace app\controller\manager;
|
||||
|
||||
use app\model\Log;
|
||||
use app\repository\CmsRepository;
|
||||
use Exception;
|
||||
use app\model\Config as ConfigModel;
|
||||
use app\model\ConfigGroup as ConfigGroupModel;
|
||||
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 ConfigItem
|
||||
* @package app\controller\manager
|
||||
*/
|
||||
class ConfigItem 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');
|
||||
}
|
||||
|
||||
ConfigModel::deleteByIds($ids);
|
||||
|
||||
Log::write(get_class().'Del', 'del', '涉及到的ID为:'.implode(',', $ids));
|
||||
return $this->json();
|
||||
}
|
||||
return $this->json(4001, '非法请求!');
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑
|
||||
*
|
||||
* @return Json|View
|
||||
* @throws Exception
|
||||
*/
|
||||
public function edit()
|
||||
{
|
||||
$id = input('id/d', 0);
|
||||
|
||||
if (!$info = ConfigModel::findById($id)) {
|
||||
return $this->json(4001, '记录不存在');
|
||||
}
|
||||
|
||||
if ($this->request->isPost()) {
|
||||
$item = input('post.');
|
||||
$validate = $this->validateByApi($item, [
|
||||
'title|配置标题' => 'require',
|
||||
'group|配置分组' => 'require|alphaDash',
|
||||
'value|配置值' => '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;
|
||||
$this->data['jsonList'] = $this->categoryJson([$info['group']]);
|
||||
|
||||
return $this->view();
|
||||
}
|
||||
|
||||
/**
|
||||
* 单个字段编辑
|
||||
*
|
||||
* @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 = ConfigModel::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',
|
||||
'group|配置分组' => 'require|alphaDash',
|
||||
'name|配置变量名' => 'require|alphaDash|unique:config',
|
||||
]);
|
||||
|
||||
if ($validate !== true) {
|
||||
return $validate;
|
||||
}
|
||||
|
||||
try {
|
||||
ConfigModel::create($item);
|
||||
return $this->json();
|
||||
} catch (ValidateException $e) {
|
||||
return $this->json(4001, $e->getError());
|
||||
}
|
||||
}
|
||||
|
||||
$this->data['jsonList'] = $this->categoryJson();
|
||||
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)) {
|
||||
if (is_string($param)) {
|
||||
$where[] = [$key, 'like', '%'.$param.'%'];
|
||||
} elseif (is_array($param)) {
|
||||
$where[] = [$key, 'in', $param];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$items = ConfigModel::findList($where, [], $page, $limit, function ($q) {
|
||||
return $q->order('sort', 'desc')->order('id', 'asc');
|
||||
});
|
||||
|
||||
return $this->json(0, '操作成功', $items);
|
||||
}
|
||||
|
||||
$this->data['categoryJson'] = json_encode($this->zTree(), JSON_UNESCAPED_UNICODE);
|
||||
|
||||
return $this->view();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $selected
|
||||
* @return false|string
|
||||
* @throws DataNotFoundException
|
||||
* @throws DbException
|
||||
* @throws ModelNotFoundException
|
||||
*/
|
||||
private function categoryJson(array $selected = [])
|
||||
{
|
||||
$menus = $this->zTree($selected);
|
||||
$categoryList = CmsRepository::getInstance()->handleSelectedList($menus);
|
||||
return json_encode($categoryList, JSON_UNESCAPED_UNICODE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $selected
|
||||
* @return array
|
||||
* @throws DataNotFoundException
|
||||
* @throws DbException
|
||||
* @throws ModelNotFoundException
|
||||
*/
|
||||
private function zTree(array $selected = []): array
|
||||
{
|
||||
$menus = ConfigGroupModel::field('id,0 as pid,title,name,sort,true as open')
|
||||
->order('sort', 'desc')
|
||||
->order('id', 'asc')
|
||||
->select()->toArray();
|
||||
foreach ($menus as $k => $m) {
|
||||
$menus[$k]['selected'] = in_array($m['name'], $selected);
|
||||
$menus[$k]['disabled'] = in_array($m['name'], []);
|
||||
}
|
||||
|
||||
return CmsRepository::getInstance()->buildMenuChild(0, $menus);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
<?php
|
||||
namespace app\controller\manager;
|
||||
|
||||
class Error
|
||||
{
|
||||
public function jump()
|
||||
{
|
||||
$param = request()->param();
|
||||
return view()->assign($param);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,113 @@
|
|||
<?php
|
||||
|
||||
namespace app\controller\manager;
|
||||
|
||||
use app\model\Log;
|
||||
use app\repository\OrderRepository;
|
||||
|
||||
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 Express
|
||||
* @package app\controller\manager
|
||||
*/
|
||||
class Express extends Base
|
||||
{
|
||||
/**
|
||||
* 删除
|
||||
*
|
||||
* @return Json
|
||||
*/
|
||||
public function del()
|
||||
{
|
||||
if ($this->request->isPost()) {
|
||||
$ids = input('post.ids/a', []);
|
||||
if (empty($ids)) {
|
||||
$ids[] = input('post.id/d');
|
||||
}
|
||||
$where[] = ['id', 'in', $ids];
|
||||
OrderRepository::getInstance()->delExpress($where);
|
||||
Log::write('express del', 'del', '删除了快递,涉及到的ID为:'.implode(',', $ids));
|
||||
return $this->json();
|
||||
}
|
||||
return $this->json(4001, '非法请求!');
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加
|
||||
*
|
||||
* @return Json|View
|
||||
* @throws DataNotFoundException
|
||||
* @throws DbException
|
||||
* @throws ModelNotFoundException
|
||||
*/
|
||||
public function edit()
|
||||
{
|
||||
$id = input('id/d', 0);
|
||||
|
||||
if (!$info = OrderRepository::getInstance()->expressInfo($id)) {
|
||||
return $this->json(4001, '数据不存在');
|
||||
}
|
||||
|
||||
if ($this->request->isPost()) {
|
||||
$item = input('post.item/a');
|
||||
try {
|
||||
unset($item['id']);
|
||||
OrderRepository::getInstance()->editExpress($item, ['id' => $id]);
|
||||
return $this->json();
|
||||
} catch (ValidateException $e) {
|
||||
return $this->json(4001, $e->getError());
|
||||
}
|
||||
}
|
||||
|
||||
$this->data['item'] = $info;
|
||||
$this->data['id'] = $id;
|
||||
|
||||
return $this->view();
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加
|
||||
*
|
||||
* @return Json|View
|
||||
*/
|
||||
public function add()
|
||||
{
|
||||
if ($this->request->isPost()) {
|
||||
$item = input('post.item/a');
|
||||
try {
|
||||
OrderRepository::getInstance()->addExpress($item);
|
||||
return $this->json();
|
||||
} catch (ValidateException $e) {
|
||||
return $this->json(4001, $e->getError());
|
||||
}
|
||||
}
|
||||
|
||||
return $this->view();
|
||||
}
|
||||
|
||||
/**
|
||||
* 快递列表
|
||||
*
|
||||
* @return View
|
||||
* @throws DbException
|
||||
*/
|
||||
public function index(): View
|
||||
{
|
||||
$size = input('size/d', 20);
|
||||
$urlQuery = input('get.');
|
||||
$where = [];
|
||||
|
||||
$where['size'] = $size;
|
||||
|
||||
$this->data['items'] = OrderRepository::getInstance()->express($where, $urlQuery);
|
||||
return $this->view();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
<?php
|
||||
|
||||
namespace app\controller\manager;
|
||||
|
||||
use app\model\Feedback as FeedbackModel;
|
||||
use app\model\FeedbackType;
|
||||
use app\model\Log;
|
||||
use Exception;
|
||||
use think\response\Json;
|
||||
use think\response\View;
|
||||
|
||||
/**
|
||||
* 意见反馈
|
||||
*
|
||||
* Class Feedback
|
||||
* @package app\controller\manager
|
||||
*/
|
||||
class Feedback 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');
|
||||
}
|
||||
FeedbackModel::deleteByIds($ids);
|
||||
Log::write(get_class().'Del', 'del', '涉及到的ID为:'.implode(',', $ids));
|
||||
return $this->json();
|
||||
}
|
||||
return $this->json(4001, '非法请求!');
|
||||
}
|
||||
|
||||
/**
|
||||
* 列表
|
||||
*
|
||||
* @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');
|
||||
$search = [];
|
||||
if ($searchParams) {
|
||||
foreach ($searchParams as $key => $param) {
|
||||
if ($param) {
|
||||
$search[] = [$key, 'like', '%'.$param.'%'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$items = FeedbackModel::findList($search, [], $page, $limit, function ($q) {
|
||||
return $q->with(['type', 'account'])->order('created_at', 'desc');
|
||||
});
|
||||
|
||||
$items['list'] = $items['list']->each(function ($item) {
|
||||
$item->feedback_type = $item->type->title ?? '';
|
||||
$item->nickname = $item->account->nickname ?? '';
|
||||
$item->mobile = $item->account->mobile ?? '';
|
||||
});
|
||||
|
||||
return $this->json(0, '操作成功', $items);
|
||||
}
|
||||
|
||||
$this->data['typeList'] = FeedbackType::select();
|
||||
|
||||
return $this->view();
|
||||
}
|
||||
}
|
|
@ -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,101 @@
|
|||
<?php
|
||||
|
||||
namespace app\controller\manager;
|
||||
|
||||
use app\model\Overview;
|
||||
use app\model\Spu;
|
||||
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
|
||||
{
|
||||
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()
|
||||
{
|
||||
if ($this->request->isPost()) {
|
||||
$page = input('page/d', 1);
|
||||
$limit = input('size/d', 10);
|
||||
$items = Overview::findList([], [], $page, $limit, function ($q) {
|
||||
return $q->with(['staff', 'account'])->order('customer', 'desc')
|
||||
->order('shares', 'desc')->order('views', 'desc')->order('asks', 'desc');
|
||||
});
|
||||
|
||||
$items['list'] = $items['list']->each(function ($item) {
|
||||
$item->nickname = $item->account->nickname ?? '';
|
||||
$item->real_name = $item->account->real_name ?? '';
|
||||
$item->staff_name = $item->staff->name ?? '';
|
||||
$item->phone = $item->account->mobile ?? '';
|
||||
});
|
||||
|
||||
return $this->json(0, '操作成功', $items);
|
||||
}
|
||||
|
||||
$count['spu'] = Spu::count();
|
||||
|
||||
$this->data['count'] = $count;
|
||||
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();
|
||||
$userId = $this->auth['user_id'] ?? 0;
|
||||
$menus = CmsRepository::getInstance()->handMenuRule($userId, $menus);
|
||||
$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,56 @@
|
|||
<?php
|
||||
|
||||
namespace app\controller\manager;
|
||||
|
||||
use app\model\Log as LogModel;
|
||||
use Exception;
|
||||
use think\response\Json;
|
||||
use think\response\View;
|
||||
|
||||
/**
|
||||
* 日志
|
||||
*
|
||||
* Class Feedback
|
||||
* @package app\controller\manager
|
||||
*/
|
||||
class Log extends Base
|
||||
{
|
||||
/**
|
||||
* 列表
|
||||
*
|
||||
* @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');
|
||||
$search = [];
|
||||
if ($searchParams) {
|
||||
foreach ($searchParams as $key => $param) {
|
||||
if ($param) {
|
||||
if ($key == 'begin_time') {
|
||||
$begin = strtotime($param.' 00:00:00');
|
||||
$search[] = ['create_time', '>', $begin];
|
||||
} elseif ($key == 'end_time') {
|
||||
$end = strtotime($param.' 23:59:59');
|
||||
$search[] = ['create_time', '<', $end];
|
||||
} else {
|
||||
$search[] = [$key, 'like', '%'.$param.'%'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$items = LogModel::findList($search, [], $page, $limit, function ($q) {
|
||||
return $q->with(['memberName'])->order('create_time', 'desc');
|
||||
});
|
||||
|
||||
return $this->json(0, '操作成功', $items);
|
||||
}
|
||||
|
||||
return $this->view();
|
||||
}
|
||||
}
|
|
@ -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,387 @@
|
|||
<?php
|
||||
|
||||
namespace app\controller\manager;
|
||||
|
||||
use app\model\Log;
|
||||
use app\model\Member as MemberModel;
|
||||
use app\model\Role as RoleModel;
|
||||
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 {
|
||||
$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']));
|
||||
|
||||
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,161 @@
|
|||
<?php
|
||||
|
||||
namespace app\controller\manager;
|
||||
|
||||
|
||||
use app\exception\TraitException;
|
||||
use app\model\Log;
|
||||
use app\model\Message AS MessageModel;
|
||||
use app\model\ScriptManagement AS ScriptManagementModel;
|
||||
use app\repository\AccountRepository;
|
||||
use think\facade\Db;
|
||||
|
||||
class Message extends Base
|
||||
{
|
||||
|
||||
public function index()
|
||||
{
|
||||
$repo = AccountRepository::getInstance();
|
||||
|
||||
if ($this->request->isPost()) {
|
||||
$page = $this->request->param('page/d', 1);
|
||||
$size = $this->request->param('size/d', 30);
|
||||
|
||||
$whereMap = [];
|
||||
$orders = ['send_at' => 'desc', 'id' => 'desc'];
|
||||
$whereMap[] = ['type', '<>', MessageModel::TYPE_REMINDERS];
|
||||
$whereMap[] = ['is_push', '=', MessageModel::COMMON_OFF];
|
||||
$res = $repo->messageList($whereMap, [], $page, $size, null, $orders);
|
||||
$list = $res['list'];
|
||||
|
||||
$msgTypeTextList = $repo->messageTypeTextList();
|
||||
$msgTargetTextList = $repo->messageTargetTextList();
|
||||
foreach ($list as $item) {
|
||||
$item['type_text'] = $msgTypeTextList[$item['type']] ?? '';
|
||||
$item['target_text'] = $msgTargetTextList[$item['target']] ?? '';
|
||||
}
|
||||
$res['list'] = $list;
|
||||
|
||||
return $this->json(0, 'success', $res);
|
||||
}
|
||||
|
||||
return $this->view();
|
||||
}
|
||||
|
||||
public function add()
|
||||
{
|
||||
$repo = AccountRepository::getInstance();
|
||||
if ($this->request->isPost()) {
|
||||
$item = $this->request->param('item/a', []);
|
||||
$targetListStr = $this->request->param('target_list_str/s', '');
|
||||
$fdata = $this->request->param('fdata/a', []);
|
||||
if (empty($fdata)) {
|
||||
return $this->json(4001, "发送时间必填");
|
||||
}
|
||||
foreach ($fdata as $fdatum) {
|
||||
if (!isset($fdatum['send_at'])||empty($fdatum['send_at'])) {
|
||||
return $this->json(4001, "发送时间必填");
|
||||
}
|
||||
}
|
||||
unset($item["send_at"]);
|
||||
|
||||
Db::startTrans();
|
||||
try {
|
||||
$type = $item['type'] ?? '';
|
||||
$target = $item['target'] ?? '';
|
||||
$targetList = empty($targetListStr) ? [] : explode(',', $targetListStr);
|
||||
|
||||
foreach ($fdata as $sitem){
|
||||
$item["send_at"] = $sitem['send_at'];
|
||||
$item["content"] = $sitem['content'];
|
||||
$repo->addMessage($type, $target, $targetList, $item);
|
||||
|
||||
}
|
||||
|
||||
Db::commit();
|
||||
|
||||
return $this->json();
|
||||
} catch (TraitException $e) {
|
||||
Db::rollback();
|
||||
return $this->json(4001, $e->getMessage());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
$this->data['typeList'] = $repo->messageTypeTextList();
|
||||
$this->data['targetList'] = $repo->messageTargetTextList();
|
||||
$scriptManagement = ScriptManagementModel::getAll();
|
||||
$this->data["script_management"] = $scriptManagement;
|
||||
$this->data["script_management_json"] = json_encode($scriptManagement);
|
||||
return $this->view();
|
||||
}
|
||||
|
||||
public function edit()
|
||||
{
|
||||
$repo = AccountRepository::getInstance();
|
||||
$id = $this->request->param('id/d', 0);
|
||||
$msg = $repo->messageInfo($id);
|
||||
if (empty($msg)) {
|
||||
return $this->json(4000, '没有相关的消息记录');
|
||||
}
|
||||
|
||||
if ($this->request->isPost()) {
|
||||
$item = $this->request->param('item/a', []);
|
||||
$targetListStr = $this->request->param('target_list_str/s', '');
|
||||
|
||||
try {
|
||||
$type = $item['type'] ?? '';
|
||||
$target = $item['target'] ?? '';
|
||||
$targetList = empty($targetListStr) ? [] : explode(',', $targetListStr);
|
||||
|
||||
$repo->editMessage($id, $type, $target, $targetList, $item);
|
||||
|
||||
} catch (TraitException $e) {
|
||||
return $this->json(4001, $e->getMessage());
|
||||
}
|
||||
|
||||
return $this->json();
|
||||
}
|
||||
|
||||
$targetAids = empty($msg['target_list'] ?? '') ? [] : explode(',', $msg['target_list']);
|
||||
$whereMap[] = ['id', 'in', $targetAids];
|
||||
$targetList = $repo->findList($whereMap)['list']->toArray();
|
||||
foreach ($targetList as &$item) {
|
||||
$item['account_desc2'] = $item['nickname'].'【姓名:'.$item['real_name'].'】';
|
||||
$item['selected'] = true;
|
||||
}
|
||||
|
||||
$this->data['id'] = $id;
|
||||
$this->data['item'] = $msg;
|
||||
$this->data['targetListJson'] = json_encode($targetList, JSON_UNESCAPED_UNICODE);
|
||||
$this->data['typeList'] = $repo->messageTypeTextList();
|
||||
$this->data['targetList'] = $repo->messageTargetTextList();
|
||||
$scriptManagement = ScriptManagementModel::getAll();
|
||||
$this->data["script_management"] = $scriptManagement;
|
||||
$this->data["script_management_json"] = json_encode($scriptManagement);
|
||||
return $this->view();
|
||||
}
|
||||
|
||||
|
||||
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)) {
|
||||
AccountRepository::getInstance()->deleteMessages($ids);
|
||||
Log::write(get_class(), 'del', '删除了message,涉及到的ID为:'.implode(',', $ids));
|
||||
}
|
||||
return $this->json();
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
<?php
|
||||
|
||||
namespace app\controller\manager;
|
||||
|
||||
use app\model\AccountRecord;
|
||||
use app\model\Overview as OverviewModel;
|
||||
use app\model\AccountRole;
|
||||
use app\model\Appointment;
|
||||
use app\model\Account;
|
||||
use Exception;
|
||||
use think\response\Json;
|
||||
use think\response\View;
|
||||
|
||||
class Overview extends Base
|
||||
{
|
||||
/**
|
||||
* 客户分析
|
||||
*
|
||||
* @return Json|View
|
||||
* @throws Exception
|
||||
*/
|
||||
public function customer()
|
||||
{
|
||||
if ($this->request->isPost()) {
|
||||
$page = input('page/d', 1);
|
||||
$limit = input('size/d', 10);
|
||||
$params = input('searchParams');
|
||||
$keyword = $params['keyword'] ?? '';
|
||||
|
||||
$items = OverviewModel::findList([], [], $page, $limit, function ($q) use ($keyword) {
|
||||
return $q->alias('o')->leftJoin('account a', 'a.id = o.account_id')
|
||||
->field('o.*,a.nickname,a.real_name,a.mobile')
|
||||
->when(!empty($keyword), function ($q) use ($keyword) {
|
||||
$q->where('a.nickname|a.real_name|a.mobile', 'like', '%'.$keyword.'%');
|
||||
})
|
||||
->where('a.phone_active', Account::COMMON_ON)
|
||||
->order('customer', 'desc')
|
||||
->order('shares', 'desc')
|
||||
->order('views', 'desc')
|
||||
->order('asks', 'desc');
|
||||
});
|
||||
|
||||
$items['list'] = $items['list']->each(function ($item) {
|
||||
$item->position = '客户';
|
||||
});
|
||||
|
||||
return $this->json(0, '操作成功', $items);
|
||||
}
|
||||
|
||||
$today = date('Y-m-d 00:00:00');
|
||||
$count['new'] = Account::where('created_at', '>', $today)->count();
|
||||
$count['total'] = Account::where('phone_active', Account::COMMON_ON)->count();
|
||||
|
||||
$this->data['count'] = $count;
|
||||
return $this->view();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,150 @@
|
|||
<?php
|
||||
|
||||
namespace app\controller\manager;
|
||||
|
||||
|
||||
use app\exception\RepositoryException;
|
||||
use app\exception\TraitException;
|
||||
use app\model\Log;
|
||||
use app\model\Message as MessageModel;
|
||||
use app\model\ScriptManagement as ScriptManagementModel;
|
||||
use app\repository\AccountRepository;
|
||||
use app\service\ali\Sms;
|
||||
use app\service\wx\WechatApplets;
|
||||
use GuzzleHttp\Exception\GuzzleException;
|
||||
use think\facade\Db;
|
||||
|
||||
class Push extends Base
|
||||
{
|
||||
|
||||
public function index()
|
||||
{
|
||||
$repo = AccountRepository::getInstance();
|
||||
|
||||
if ($this->request->isPost()) {
|
||||
$page = $this->request->param('page/d', 1);
|
||||
$size = $this->request->param('size/d', 30);
|
||||
|
||||
$whereMap = [];
|
||||
$orders = ['send_at' => 'desc', 'id' => 'desc'];
|
||||
$whereMap[] = ['type', '<>', MessageModel::TYPE_REMINDERS];
|
||||
$whereMap[] = ['is_push', '=', MessageModel::COMMON_ON];
|
||||
$res = $repo->messageList($whereMap, [], $page, $size, null, $orders);
|
||||
$list = $res['list'];
|
||||
|
||||
$msgTypeTextList = $repo->messageTypeTextList();
|
||||
$msgTargetTextList = $repo->messageTargetTextList();
|
||||
foreach ($list as $item) {
|
||||
$item['type_text'] = $msgTypeTextList[$item['type']] ?? '';
|
||||
$item['target_text'] = $msgTargetTextList[$item['target']] ?? '';
|
||||
}
|
||||
$res['list'] = $list;
|
||||
|
||||
return $this->json(0, 'success', $res);
|
||||
}
|
||||
|
||||
return $this->view();
|
||||
}
|
||||
|
||||
public function add()
|
||||
{
|
||||
$repo = AccountRepository::getInstance();
|
||||
if ($this->request->isPost()) {
|
||||
$item = $this->request->param('item/a', []);
|
||||
$targetListStr = $this->request->param('target_list_str/s', '');
|
||||
|
||||
Db::startTrans();
|
||||
try {
|
||||
$targetList = empty($targetListStr) ? [] : explode(',', $targetListStr);
|
||||
$repo->createMessage($item, $targetList);
|
||||
Db::commit();
|
||||
return $this->json();
|
||||
} catch (RepositoryException | TraitException $e) {
|
||||
Db::rollback();
|
||||
return $this->json(4001, $e->getMessage());
|
||||
} catch (\Exception $e) {
|
||||
Db::rollback();
|
||||
\think\facade\Log::error('[添加推送失败]'.$e->getMessage());
|
||||
return $this->json(5001, '添加推送失败');
|
||||
}
|
||||
}
|
||||
|
||||
$this->data['subscribeTempList'] = WechatApplets::msgTemplateList();
|
||||
$this->data['subscribeTempParams'] = json_encode(WechatApplets::msgTemplateParams(), JSON_UNESCAPED_UNICODE);
|
||||
|
||||
$this->data['smsTempList'] = Sms::templateList();
|
||||
$this->data['smsTempParams'] = json_encode(Sms::templateParams(), JSON_UNESCAPED_UNICODE);
|
||||
|
||||
|
||||
$this->data['targetList'] = $repo->messageTargetTextList();
|
||||
|
||||
return $this->view();
|
||||
}
|
||||
|
||||
public function edit()
|
||||
{
|
||||
$repo = AccountRepository::getInstance();
|
||||
$id = $this->request->param('id/d', 0);
|
||||
$msg = $repo->messageInfo($id);
|
||||
if (empty($msg)) {
|
||||
return $this->json(4000, '没有相关的消息记录');
|
||||
}
|
||||
|
||||
if ($this->request->isPost()) {
|
||||
$item = $this->request->param('item/a', []);
|
||||
$targetListStr = $this->request->param('target_list_str/s', '');
|
||||
|
||||
try {
|
||||
$type = $item['type'] ?? '';
|
||||
$target = $item['target'] ?? '';
|
||||
$targetList = empty($targetListStr) ? [] : explode(',', $targetListStr);
|
||||
|
||||
$repo->editMessage($id, $type, $target, $targetList, $item);
|
||||
|
||||
} catch (TraitException $e) {
|
||||
return $this->json(4001, $e->getMessage());
|
||||
}
|
||||
|
||||
return $this->json();
|
||||
}
|
||||
|
||||
$targetAids = empty($msg['target_list'] ?? '') ? [] : explode(',', $msg['target_list']);
|
||||
$whereMap[] = ['id', 'in', $targetAids];
|
||||
$targetList = $repo->findList($whereMap)['list']->toArray();
|
||||
foreach ($targetList as &$item) {
|
||||
$item['account_desc2'] = $item['nickname'].'【姓名:'.$item['real_name'].'】';
|
||||
$item['selected'] = true;
|
||||
}
|
||||
|
||||
$this->data['id'] = $id;
|
||||
$this->data['item'] = $msg;
|
||||
$this->data['targetListJson'] = json_encode($targetList, JSON_UNESCAPED_UNICODE);
|
||||
$this->data['typeList'] = $repo->messageTypeTextList();
|
||||
$this->data['targetList'] = $repo->messageTargetTextList();
|
||||
$scriptManagement = ScriptManagementModel::getAll();
|
||||
$this->data["script_management"] = $scriptManagement;
|
||||
$this->data["script_management_json"] = json_encode($scriptManagement);
|
||||
return $this->view();
|
||||
}
|
||||
|
||||
|
||||
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)) {
|
||||
AccountRepository::getInstance()->deleteMessages($ids);
|
||||
Log::write(get_class(), 'del', '删除了message,涉及到的ID为:'.implode(',', $ids));
|
||||
}
|
||||
return $this->json();
|
||||
}
|
||||
|
||||
}
|
|
@ -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,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,241 @@
|
|||
<?php
|
||||
|
||||
namespace app\controller\manager;
|
||||
|
||||
use app\exception\RepositoryException;
|
||||
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('Ym');//自定义目录
|
||||
$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('files'.$this->DIRECTORY_SEPARATOR.date('Ym'), $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');
|
||||
try {
|
||||
$res = $this->uploadImage($image);
|
||||
return $this->json(0, '上传成功', $res);
|
||||
} catch (RepositoryException $e) {
|
||||
return $this->json(1, $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
//富文本编辑器商城图片
|
||||
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('images/'.date('Ym'), $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);
|
||||
}
|
||||
|
||||
public function uploadImage($image)
|
||||
{
|
||||
// 字段名 image-image避免冲突 layui组件自动生成的隐藏file input框中name容易重名冲突
|
||||
$md5 = $image->md5();//文件md5
|
||||
$type = request()->param('type/s', '');
|
||||
$path = request()->param('path/s', '');//指定路径 基于public下 若为空则默认
|
||||
$hasPath = !empty($path);
|
||||
|
||||
if ($this->validate->checkImage($image)) {
|
||||
if ($fileItem = File::where('md5', $md5)->find()) {
|
||||
$return['src'] = $fileItem['src'];
|
||||
$return['thumb_src'] = Image::getThumb($fileItem['src'], 100, 100, TImage::THUMB_SCALING);
|
||||
return $return;
|
||||
}
|
||||
|
||||
$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 : 'images'.$this->DIRECTORY_SEPARATOR.date('Ym');//自定义目录
|
||||
$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) {
|
||||
throw new RepositoryException($e->getMessage());
|
||||
}
|
||||
return $return;
|
||||
} else {
|
||||
$errorMsg = Lang::get($this->validate->getError());
|
||||
throw new RepositoryException($errorMsg);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,282 @@
|
|||
<?php
|
||||
|
||||
namespace app\controller\manager\account;
|
||||
|
||||
use app\controller\manager\Base;
|
||||
use app\exception\RepositoryException;
|
||||
use app\model\AccountTag;
|
||||
use app\model\Account as AccountModel;
|
||||
use app\model\Order;
|
||||
use app\repository\AccountRepository;
|
||||
use app\repository\OrderRepository;
|
||||
use app\service\Math;
|
||||
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\facade\Log;
|
||||
use think\response\Json;
|
||||
use think\response\Redirect;
|
||||
use think\response\View;
|
||||
|
||||
/**
|
||||
* 用户管理
|
||||
*
|
||||
* Class Footmarks
|
||||
* @package app\controller\manager
|
||||
*/
|
||||
class Index extends Base
|
||||
{
|
||||
protected $noNeedLogin = ['getAccountList'];
|
||||
|
||||
/**
|
||||
* 详情
|
||||
*
|
||||
* @return View
|
||||
* @throws RepositoryException
|
||||
*/
|
||||
public function detail(): View
|
||||
{
|
||||
$id = input('id/d', 0);
|
||||
$item = AccountRepository::getInstance()->findById($id);
|
||||
|
||||
$statusList = [
|
||||
Order::STATUS_SHIPPED, Order::STATUS_PAID, Order::STATUS_COMPLETED
|
||||
];
|
||||
$consumption = OrderRepository::getInstance()->userOrderList($id, [], 1, 0, $statusList);
|
||||
$orderNum = 0;
|
||||
$orderScoreNum = 0;
|
||||
$totalPrice = 0;
|
||||
$totalScore = 0;
|
||||
$consumption->each(function ($item) use (&$totalPrice, &$totalScore, &$totalCoin, &$orderScoreNum, &$orderNum) {
|
||||
if ($item->is_score == AccountModel::COMMON_ON) {
|
||||
$orderScoreNum += 1;
|
||||
} else {
|
||||
$orderNum += 1;
|
||||
}
|
||||
$totalPrice += $item->price;
|
||||
$totalScore += $item->score;
|
||||
});
|
||||
$item['total_price'] = Math::fen2Yuan($totalPrice);
|
||||
$item['order_num'] = $orderNum;
|
||||
$item['order_score_num'] = $orderScoreNum;
|
||||
$item['order_newest'] = $consumption->toArray()[0] ?? [];
|
||||
|
||||
$this->data['item'] = $item;
|
||||
|
||||
return $this->view();
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑
|
||||
*
|
||||
* @return Redirect|Json|View
|
||||
* @throws Exception
|
||||
*/
|
||||
public function edit()
|
||||
{
|
||||
$id = input('id/d', 0);
|
||||
if (!$info = AccountRepository::getInstance()->findById($id)) {
|
||||
if ($this->request->isPost()) {
|
||||
return $this->json(4000, '用户不存在');
|
||||
} else {
|
||||
return $this->error('用户不存在');
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->request->isPost()) {
|
||||
$item = input('post.');
|
||||
$validate = $this->validateByApi($item, [
|
||||
'nickname' => '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 = AccountModel::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 View|Json
|
||||
* @throws Exception
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
if ($this->request->isPost()) {
|
||||
$page = input('page/d', 1);
|
||||
$size = input('size/d', 20);
|
||||
$searchParams = input('searchParams');
|
||||
$search = [];
|
||||
$other = [];
|
||||
if ($searchParams) {
|
||||
foreach ($searchParams as $key => $param) {
|
||||
if ($key == 'tag' && !empty($param)) {
|
||||
$other['tag_id'] = $param;
|
||||
continue;
|
||||
}
|
||||
if ($param || $param == '0') {
|
||||
$search[] = [$key, 'like', '%'.$param.'%'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$search[] = ['phone_active', '=', AccountModel::COMMON_ON];
|
||||
|
||||
try {
|
||||
$items = AccountRepository::getInstance()->getAndHandleAccountList($search, [], $page, $size, function ($q) use ($other) {
|
||||
return $q->when(isset($other['tag_id']), function ($query) use ($other) {
|
||||
$query->leftJoin('account_tag_pivot atp', 'atp.account_id = id')->where('atp.tag_id', $other['tag_id']);
|
||||
});
|
||||
});
|
||||
return $this->json(0, '操作成功', $items);
|
||||
} catch (RepositoryException $e) {
|
||||
return $this->json(4001, $e->getMessage());
|
||||
} catch (Exception $e) {
|
||||
return $this->json(5001, '获取用户列表失败'.$e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
$this->data['tagList'] = AccountTag::getTags();
|
||||
|
||||
return $this->view();
|
||||
}
|
||||
|
||||
/**
|
||||
* 分配客户标签
|
||||
*
|
||||
* @return View|Json
|
||||
* @throws Exception
|
||||
*/
|
||||
public function tag()
|
||||
{
|
||||
$id = input('id/s', '');
|
||||
if ($this->request->isPost()) {
|
||||
$ids = input('ids/s');
|
||||
$tagId = input('tag_id/s');
|
||||
if (empty($ids)) {
|
||||
return $this->json(4001, '请选择要操作的用户');
|
||||
}
|
||||
|
||||
if (empty($tagId)) {
|
||||
return $this->json(4001, '请选择分配的标签');
|
||||
}
|
||||
|
||||
$ids = explode(',', $ids);
|
||||
$tags = explode(',', $tagId);
|
||||
|
||||
Db::startTrans();
|
||||
try {
|
||||
AccountRepository::getInstance()->setTagByBatch($ids, $tags);
|
||||
Db::commit();
|
||||
return $this->json(0, '操作成功');
|
||||
} catch (RepositoryException $e) {
|
||||
Db::rollback();
|
||||
return $this->json(4001, $e->getMessage());
|
||||
} catch (Exception $e) {
|
||||
Db::rollback();
|
||||
Log::error('分配客户标签失败'.$e->getMessage());
|
||||
return $this->json(5001, '分配客户标签失败');
|
||||
}
|
||||
}
|
||||
|
||||
$tagList = AccountTag::order('sort', 'desc')->order('id', 'asc')->select()->toArray();
|
||||
|
||||
$this->data['tagList'] = json_encode($tagList, JSON_UNESCAPED_UNICODE);
|
||||
$this->data['id'] = $id;
|
||||
|
||||
return $this->view();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取客户列表
|
||||
*
|
||||
* @return Json
|
||||
* @throws DataNotFoundException
|
||||
* @throws DbException
|
||||
* @throws ModelNotFoundException|Exception
|
||||
*/
|
||||
public function getAccountList(): Json
|
||||
{
|
||||
if ($this->request->isPost()) {
|
||||
$keyword = input('keyword/s', '');
|
||||
$page = input('page/d', 1);
|
||||
$size = input('size/d', 10);
|
||||
$id = input('id', '');
|
||||
|
||||
$relationIds = explode(',', $id);//已选记录
|
||||
|
||||
$where = [];
|
||||
if (!empty($keyword)) {
|
||||
$where[] = ['nickname|real_name|mobile', 'like', '%'.$keyword.'%'];
|
||||
}
|
||||
|
||||
$res = AccountModel::findList($where, ['id', 'nickname', 'real_name', 'mobile'], $page, $size);
|
||||
|
||||
if ($res['total'] > 0 && $relationIds) {
|
||||
$res['list'] = $res['list']->toArray();
|
||||
foreach ($res['list'] as &$item) {
|
||||
$item['name_text'] = sprintf("昵称:%s;真实姓名:%s,手机号:%s", $item['nickname'], $item['real_name'], $item['mobile']);
|
||||
if (count($relationIds) > 0 && in_array($item['id'], $relationIds)) {
|
||||
$item['selected'] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $this->json(0, '操作成功', $res);
|
||||
}
|
||||
return $this->json(4001, '非法请求');
|
||||
}
|
||||
}
|
|
@ -0,0 +1,173 @@
|
|||
<?php
|
||||
|
||||
namespace app\controller\manager\account;
|
||||
|
||||
use app\controller\manager\Base;
|
||||
use app\model\AccountTag as AccountTagModel;
|
||||
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 Tag
|
||||
* @package app\controller\manager\account
|
||||
*/
|
||||
class Tag 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');
|
||||
}
|
||||
AccountTagModel::deleteByIds($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 = AccountTagModel::findById($id)) {
|
||||
return $this->json(4001, '记录不存在');
|
||||
}
|
||||
|
||||
if ($this->request->isPost()) {
|
||||
$item = input('post.');
|
||||
$validate = $this->validateByApi($item, [
|
||||
'name' => '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 = AccountTagModel::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, [
|
||||
'name' => 'require',
|
||||
]);
|
||||
|
||||
if ($validate !== true) {
|
||||
return $validate;
|
||||
}
|
||||
$tag = AccountTagModel::findOne(["name" => $item["name"]]);
|
||||
if (!empty($tag)) {
|
||||
return $this->json(0, "success", ["id" => $tag["id"]]);
|
||||
}
|
||||
try {
|
||||
$item['created_at'] = date('Y-m-d H:i:s');
|
||||
$id = AccountTagModel::insertGetId($item);
|
||||
return $this->json(0, "success", ["id" => $id]);
|
||||
} catch (ValidateException $e) {
|
||||
return $this->json(4001, $e->getError());
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
$items = AccountTagModel::findList([], [], $page, $limit, function ($q) {
|
||||
return $q->order('sort', 'desc')->order('id', 'asc');
|
||||
});
|
||||
|
||||
return $this->json(0, '操作成功', $items);
|
||||
}
|
||||
return $this->view();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,494 @@
|
|||
<?php
|
||||
|
||||
namespace app\controller\manager\mall;
|
||||
|
||||
use app\controller\manager\Base;
|
||||
use app\exception\RepositoryException;
|
||||
use app\model\Config;
|
||||
use app\model\Log;
|
||||
use app\model\Sku;
|
||||
use app\model\Spu as SpuModel;
|
||||
use app\model\SpuActivity;
|
||||
use app\repository\SpuRepository;
|
||||
use app\service\Math;
|
||||
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 Activity extends Base
|
||||
{
|
||||
protected $noNeedLogin = ['getOrder', 'getOrderGroupList'];
|
||||
|
||||
/**
|
||||
* 列表
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
if ($this->request->isPost()) {
|
||||
$params = input();
|
||||
$params['type'] = SpuModel::TYPE_GROUP_BUY;
|
||||
$params['type'] = SpuModel::TYPE_GROUP_BUY;
|
||||
|
||||
$res = $this->spuList($params);
|
||||
|
||||
return $this->json(0, 'success', $res);
|
||||
}
|
||||
|
||||
$this->data['statusList'] = SpuModel::statusTextList();
|
||||
$this->data['spuTypeList'] = SpuModel::spuTypeTextList();
|
||||
$this->data['type'] = SpuModel::TYPE_GROUP_BUY;
|
||||
|
||||
$this->data['mpPath'] = Config::MINI_PATH_SPU_INFO;
|
||||
|
||||
return $this->view();
|
||||
}
|
||||
|
||||
/**
|
||||
* 拼团
|
||||
*
|
||||
* @return Json|View
|
||||
*/
|
||||
public function groupMake()
|
||||
{
|
||||
if ($this->request->isPost()) {
|
||||
$params = input();
|
||||
$params['type'] = SpuModel::TYPE_GROUP_MAKE;
|
||||
|
||||
$res = $this->spuList($params);
|
||||
|
||||
return $this->json(0, 'success', $res);
|
||||
}
|
||||
|
||||
$this->data['statusList'] = SpuModel::statusTextList();
|
||||
$this->data['spuTypeList'] = SpuModel::spuTypeTextList();
|
||||
$this->data['type'] = SpuModel::TYPE_GROUP_MAKE;
|
||||
$this->data['url'] = '/manager/mall/activity/group-make';
|
||||
|
||||
$this->data['mpPath'] = Config::MINI_PATH_SPU_INFO;
|
||||
|
||||
return $this->view('/manager/mall/activity/index');
|
||||
}
|
||||
|
||||
/**
|
||||
* 限时促销
|
||||
*
|
||||
* @return Json|View
|
||||
*/
|
||||
public function limitTime()
|
||||
{
|
||||
if ($this->request->isPost()) {
|
||||
$params = input();
|
||||
$params['type'] = SpuModel::TYPE_LIMIT_TIME;
|
||||
|
||||
$res = $this->spuList($params);
|
||||
|
||||
return $this->json(0, 'success', $res);
|
||||
}
|
||||
|
||||
$this->data['statusList'] = SpuModel::statusTextList();
|
||||
$this->data['spuTypeList'] = SpuModel::spuTypeTextList();
|
||||
$this->data['type'] = SpuModel::TYPE_LIMIT_TIME;
|
||||
$this->data['url'] = '/manager/mall/activity/limit-time';
|
||||
|
||||
$this->data['mpPath'] = Config::MINI_PATH_SPU_INFO;
|
||||
|
||||
return $this->view('/manager/mall/activity/index');
|
||||
}
|
||||
|
||||
protected function spuList(array $params): array
|
||||
{
|
||||
$res = SpuRepository::getInstance()->activityList($params);
|
||||
$res['list'] = $res['list']->each(function ($item) {
|
||||
$status = '';
|
||||
$now = date('Y-m-d H:i:s');
|
||||
if ($item['activity_begin_at'] > $now) {
|
||||
$status = '未开始';
|
||||
}
|
||||
|
||||
if ($item['activity_begin_at'] < $now && $now < $item['activity_end_at']) {
|
||||
$status = '进行中';
|
||||
}
|
||||
|
||||
if ($item['is_activity_history'] == SpuModel::COMMON_ON || $item['activity_end_at'] < $now) {
|
||||
$status = '已结束';
|
||||
}
|
||||
|
||||
$item->status_text = $status;
|
||||
});
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ModelNotFoundException
|
||||
* @throws DbException
|
||||
* @throws DataNotFoundException
|
||||
* @throws Exception
|
||||
*/
|
||||
public function add()
|
||||
{
|
||||
$repo = SpuRepository::getInstance();
|
||||
$type = input('type/s', SpuModel::TYPE_GROUP_BUY);
|
||||
if (!in_array($type, SpuModel::activityList())) {
|
||||
if ($this->request->isPost()) {
|
||||
return $this->json(4000, '活动类型错误');
|
||||
} else {
|
||||
return $this->error('活动类型错误');
|
||||
}
|
||||
}
|
||||
if ($this->request->isPost()) {
|
||||
$item = $this->request->param('item/a', []);
|
||||
$sku = $this->request->param('sku/a', []);
|
||||
$spuId = $this->request->param('spu_id/d', 0);
|
||||
|
||||
$rules = [
|
||||
'cover|活动封面' => 'require',
|
||||
'activity_begin_at|开始时间' => 'require|date',
|
||||
'activity_end_at|结束时间' => 'require|date',
|
||||
];
|
||||
|
||||
$validate = $this->validateByApi($item, $rules);
|
||||
if ($validate !== true) {
|
||||
return $validate;
|
||||
}
|
||||
|
||||
$item['is_score'] = SpuModel::COMMON_OFF;
|
||||
$item['is_activity'] = SpuModel::COMMON_ON;
|
||||
$item['activity_type'] = $type;
|
||||
|
||||
try {
|
||||
foreach ($sku as &$val) {
|
||||
if (isset($val['id'])) {
|
||||
unset($val['id']);
|
||||
}
|
||||
}
|
||||
|
||||
$this->checkSku($sku);
|
||||
$repo->addActivity($type, $item, $spuId, $sku);
|
||||
} catch (RepositoryException $e) {
|
||||
return $this->json(4002, $e->getMessage());
|
||||
} catch (Exception $e) {
|
||||
}
|
||||
|
||||
return $this->json();
|
||||
}
|
||||
|
||||
$this->data['type'] = $type;
|
||||
$this->data['limitList'] = SpuModel::limitList();
|
||||
$this->data['limitFields'] = SpuRepository::getInstance()->activityFields($type);
|
||||
|
||||
return $this->view();
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws DataNotFoundException
|
||||
* @throws ModelNotFoundException
|
||||
* @throws DbException
|
||||
*/
|
||||
public function edit()
|
||||
{
|
||||
$id = $this->request->param('id/d', 0);
|
||||
$skuList = Sku::where('spu_activity_id', $id)
|
||||
->where('enable', Sku::COMMON_ON)
|
||||
->order('sort', 'asc')
|
||||
->order('id', 'asc')->select()->toArray();
|
||||
|
||||
if ($this->request->isPost()) {
|
||||
$item = $this->request->param('item/a', []);
|
||||
$sku = $this->request->param('sku/a', []);
|
||||
try {
|
||||
$this->checkSku($sku);
|
||||
|
||||
SpuRepository::getInstance()->editActivity($id, $item, $sku, $skuList);
|
||||
} catch (RepositoryException $e) {
|
||||
return $this->json(4002, $e->getMessage());
|
||||
} catch (Exception $e) {
|
||||
}
|
||||
|
||||
return $this->json();
|
||||
}
|
||||
|
||||
$spuActivity = SpuActivity::findById($id);
|
||||
if (empty($spuActivity)) {
|
||||
return $this->json(4000, '没有相关的商品记录!');
|
||||
}
|
||||
|
||||
foreach ($skuList as &$val) {
|
||||
$val['price'] = Math::fen2Yuan($val['price']);
|
||||
$val['original_price'] = Math::fen2Yuan($val['original_price']);
|
||||
}
|
||||
|
||||
$this->data['item'] = $spuActivity;
|
||||
$this->data['skuList'] = $skuList;
|
||||
$this->data['limitList'] = SpuModel::limitList();
|
||||
$this->data['limitFields'] = SpuRepository::getInstance()->activityFields($spuActivity['activity_type']);
|
||||
$this->data['id'] = $id;
|
||||
return $this->view();
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws RepositoryException
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function checkSku(array $sku)
|
||||
{
|
||||
// sku验证
|
||||
if (empty($sku)) {
|
||||
throw new RepositoryException('规格信息不能为空');
|
||||
}
|
||||
|
||||
foreach ($sku as $k) {
|
||||
$validate = $this->validateByApi($k, [
|
||||
'title' => 'require',
|
||||
'stock' => 'require|number|gt:0',
|
||||
'price' => 'number',
|
||||
'score' => 'number',
|
||||
'is_default' => 'require|in:0,1',
|
||||
]);
|
||||
|
||||
if ($validate !== true) {
|
||||
return $validate;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ModelNotFoundException
|
||||
* @throws DbException
|
||||
* @throws DataNotFoundException
|
||||
* @throws Exception
|
||||
*/
|
||||
public function modify()
|
||||
{
|
||||
if (!$this->request->isPost()) {
|
||||
return $this->json(4000, '非法请求');
|
||||
}
|
||||
|
||||
$item = input('post.');
|
||||
$validate = $this->validateByApi($item, [
|
||||
'field' => 'require',
|
||||
'value' => 'require',
|
||||
]);
|
||||
|
||||
if ($validate !== true) {
|
||||
return $validate;
|
||||
}
|
||||
|
||||
if (!$info = SpuActivity::findById($item['id'])) {
|
||||
return $this->json(4001, '记录不存在');
|
||||
}
|
||||
|
||||
$update = [$item['field'] => $item['value']];
|
||||
|
||||
try {
|
||||
$info->save($update);
|
||||
if ($item['field'] == 'is_check' && $info['is_activity_history'] == SpuModel::COMMON_OFF) {
|
||||
SpuModel::where('id', $info['spu_id'])->save(['is_check' => $item['value']]);
|
||||
}
|
||||
return $this->json();
|
||||
} catch (ValidateException $e) {
|
||||
return $this->json(4001, $e->getError());
|
||||
} catch (Exception $e) {
|
||||
return $this->json(5000, '修改失败');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 立即结束-还原为普通商品
|
||||
*
|
||||
* @return Json
|
||||
*/
|
||||
public function end(): Json
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
try {
|
||||
if (count($ids)) {
|
||||
SpuRepository::getInstance()->restore($ids);
|
||||
Log::write(get_class(), 'end', '还原了活动商品,涉及到的ID为:'.implode(',', $ids));
|
||||
}
|
||||
} catch (RepositoryException $e) {
|
||||
return $this->json(4001, $e->getMessage());
|
||||
}
|
||||
|
||||
return $this->json();
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除-还原为普通商品且隐藏
|
||||
*
|
||||
* @return Json
|
||||
*/
|
||||
public function del(): Json
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
try {
|
||||
if (count($ids)) {
|
||||
SpuRepository::getInstance()->restore($ids, false, true);
|
||||
// (new SpuActivity())->whereIn('id', $ids)->save(['deleted_at' => date('Y-m-d H:i:s')]);
|
||||
Log::write(get_class(), 'del', '还原了活动商品,涉及到的ID为:'.implode(',', $ids));
|
||||
}
|
||||
} catch (RepositoryException $e) {
|
||||
return $this->json(4001, $e->getMessage());
|
||||
}
|
||||
|
||||
return $this->json();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 活动商品详情
|
||||
*
|
||||
* @return View
|
||||
* @throws DataNotFoundException
|
||||
* @throws DbException
|
||||
* @throws ModelNotFoundException
|
||||
* @throws Exception
|
||||
*/
|
||||
public function info(): View
|
||||
{
|
||||
$id = input('id/d', 0);
|
||||
$item = SpuActivity::findById($id);
|
||||
|
||||
$status = '';
|
||||
$now = date('Y-m-d H:i:s');
|
||||
if ($item['activity_begin_at'] > $now) {
|
||||
$status = '未开始';
|
||||
}
|
||||
|
||||
if ($item['activity_begin_at'] < $now && $now < $item['activity_end_at']) {
|
||||
$status = '进行中';
|
||||
}
|
||||
|
||||
if ($item['is_activity_history'] == SpuModel::COMMON_ON || $item['activity_end_at'] < $now) {
|
||||
$status = '已结束';
|
||||
}
|
||||
|
||||
$item->status_text = $status;
|
||||
|
||||
if ($item->activity_type == SpuModel::TYPE_GROUP_MAKE) {
|
||||
//拼团
|
||||
$orderList = SpuRepository::getInstance()->getActivityGroupList($id);
|
||||
} else {
|
||||
// 团购 促销
|
||||
$orderList = SpuRepository::getInstance()->getActivityOrderList($id);
|
||||
}
|
||||
|
||||
$totalPriceList = $orderList['list']->where('is_paid', SpuActivity::COMMON_ON)->column('total_price');
|
||||
$codingList = $orderList['list']->column('coding');
|
||||
$accountList = $orderList['list']->column('account_id');
|
||||
$codingCount = count(array_unique($codingList));
|
||||
$accountCount = count(array_unique($accountList));
|
||||
$totalPrice = array_sum($totalPriceList);
|
||||
$item->total_money = Math::fen2Yuan($totalPrice) ?? 0;
|
||||
$item->order_count = $codingCount;
|
||||
$item->account_count = $accountCount;
|
||||
|
||||
$this->data['item'] = $item;
|
||||
$this->data['statusList'] = \app\model\Order::statusTextList();
|
||||
$this->data['activityList'] = SpuModel::activityTextList();
|
||||
$this->data['limitList'] = SpuModel::limitList();//限购天数展示
|
||||
|
||||
return $this->view();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取活动商品的订单列表
|
||||
*
|
||||
* @return Json
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getOrder(): Json
|
||||
{
|
||||
$id = input('id/d', 0);
|
||||
$page = input('page/d', 1);
|
||||
$size = input('size/d', 20);
|
||||
|
||||
$res = SpuRepository::getInstance()->getActivityOrderList($id, $page, $size);
|
||||
|
||||
return $this->json(0, '操作成功', $res);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取拼团列表
|
||||
*
|
||||
* @return Json
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getOrderGroupList(): Json
|
||||
{
|
||||
$id = input('id/d', 0);
|
||||
$page = input('page/d', 1);
|
||||
$size = input('size/d', 20);
|
||||
|
||||
$res = SpuRepository::getInstance()->getActivityGroupList($id, $page, $size);
|
||||
|
||||
return $this->json(0, '操作成功', $res);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量审核
|
||||
*
|
||||
* @return View|Json
|
||||
* @throws Exception
|
||||
*/
|
||||
public function check()
|
||||
{
|
||||
$id = input('id/s', '');
|
||||
if ($this->request->isPost()) {
|
||||
$ids = input('ids/s');
|
||||
$check = input('is_check/d');
|
||||
|
||||
if (!in_array($check, [SpuActivity::COMMON_ON, SpuActivity::COMMON_OFF])) {
|
||||
return $this->json(4001, '请选择是否展示');
|
||||
}
|
||||
|
||||
$ids = explode(',', $ids);
|
||||
|
||||
Db::startTrans();
|
||||
try {
|
||||
(new SpuActivity())->whereIn('id', $ids)->save(['is_check' => $check]);
|
||||
// 活动商品对应的普通商品审核状态同步
|
||||
$spuIds = SpuActivity::whereid('id', $ids)
|
||||
->where('is_activity_history', SpuActivity::COMMON_OFF)
|
||||
->column('spu_id');
|
||||
SpuModel::whereIn('id', $spuIds)->save(['is_check' => $check]);
|
||||
Db::commit();
|
||||
return $this->json(0, '操作成功');
|
||||
} catch (Exception $e) {
|
||||
Db::rollback();
|
||||
Log::error('活动商品批量审核操作失败'.$e->getMessage());
|
||||
return $this->json(5001, '商品批量审核操作失败');
|
||||
}
|
||||
}
|
||||
|
||||
$this->data['id'] = $id;
|
||||
|
||||
return $this->view();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,225 @@
|
|||
<?php
|
||||
|
||||
namespace app\controller\manager\mall;
|
||||
|
||||
use app\controller\manager\Base;
|
||||
use app\repository\CmsRepository;
|
||||
use app\model\mall\Category as CategoryModel;
|
||||
|
||||
use app\validate\MenuValidate;
|
||||
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 Menu
|
||||
* @package app\controller\manager\mall
|
||||
*/
|
||||
class Category 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');
|
||||
}
|
||||
if (CategoryModel::hasChildrenByIds($ids)) {
|
||||
return $this->json(4002, '待删除数据存在子数据');
|
||||
}
|
||||
|
||||
if (CategoryModel::hasContentByIds($ids)) {
|
||||
return $this->json(4002, '待删除数据存在内容文章');
|
||||
}
|
||||
CategoryModel::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 = CategoryModel::findById($id)) {
|
||||
return $this->json(4001, '记录不存在');
|
||||
}
|
||||
|
||||
if ($this->request->isPost()) {
|
||||
$item = input('post.');
|
||||
$validate = $this->validateByApi($item, [
|
||||
'pid|父级分类' => 'require|number',
|
||||
'title|标题' => 'require|max:100',
|
||||
// 'name|标识' => 'unique:spu_category,name,'.$info['id'] ?? 0,
|
||||
'description|描述' => 'max:255',
|
||||
]);
|
||||
|
||||
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
|
||||
*/
|
||||
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 = 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',
|
||||
'title|标题' => 'require|max:100',
|
||||
//'name|标识' => 'require|unique:spu_category',
|
||||
'description|描述' => 'max:255',
|
||||
]);
|
||||
|
||||
if ($validate !== true) {
|
||||
return $validate;
|
||||
}
|
||||
Db::startTrans();
|
||||
try {
|
||||
$item['path'] = CategoryModel::getPath($item['pid']);
|
||||
(new CategoryModel())->create($item);
|
||||
Db::commit();
|
||||
return $this->json();
|
||||
} catch (ValidateException $e) {
|
||||
Db::rollback();
|
||||
return $this->json(4001, $e->getError());
|
||||
}
|
||||
}
|
||||
|
||||
$this->data['jsonList'] = $this->categoryJson();
|
||||
|
||||
return $this->view();
|
||||
}
|
||||
|
||||
/**
|
||||
* 列表
|
||||
*
|
||||
* @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[] = ['title' => '顶级分类', 'id' => 0, 'disabled' => false, 'selected' => in_array(0, $selected)];
|
||||
$menus = CategoryModel::getList();
|
||||
$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,183 @@
|
|||
<?php
|
||||
|
||||
namespace app\controller\manager\mall;
|
||||
|
||||
use app\controller\manager\Base;
|
||||
use app\model\Account;
|
||||
use app\model\AccountCoupon as AccountCouponModel;
|
||||
use app\model\Coupon as CouponModel;
|
||||
use app\model\Log;
|
||||
use app\service\Math;
|
||||
use Exception;
|
||||
use think\exception\ValidateException;
|
||||
use think\response\Json;
|
||||
|
||||
class Coupon extends Base
|
||||
{
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
if ($this->request->isPost()) {
|
||||
$page = $this->request->param('page/d', 1);
|
||||
$size = $this->request->param('size/d', 20);
|
||||
|
||||
$startAt = $this->request->param('begin_at/s', '');
|
||||
$endAt = $this->request->param('end_at/s', '');
|
||||
|
||||
$whereMap[] = ['deleted_at', '=', null];
|
||||
$order = ['sort' => 'desc', 'id' => 'desc'];
|
||||
|
||||
if (!empty($startAt) && strtotime($startAt)) {
|
||||
$whereMap[] = ['begin_at', '>=', $startAt];
|
||||
}
|
||||
if (!empty($endAt) && strtotime($endAt)) {
|
||||
$whereMap[] = ['end_at', '<=', $endAt];
|
||||
}
|
||||
|
||||
$res = CouponModel::findList($whereMap, [], $page, $size, null, $order);
|
||||
|
||||
$res['list'] = $res['list']->each(function ($item) {
|
||||
$item->type_text = CouponModel::typeTextList()[$item->type] ?? '';
|
||||
});
|
||||
return $this->json(0, 'success', $res);
|
||||
}
|
||||
|
||||
return $this->view();
|
||||
}
|
||||
|
||||
public function add()
|
||||
{
|
||||
if ($this->request->isPost()) {
|
||||
$item = $this->request->param('item/a', []);
|
||||
|
||||
try {
|
||||
$rules = [
|
||||
'name|优惠券名称' => 'require',
|
||||
'condition|消费额度' => 'float',
|
||||
'amount|优惠额度' => 'float',
|
||||
'total|发行总量' => 'require|integer|gt:0',
|
||||
'begin_at|开始时间' => 'require|date',
|
||||
'end_at|截止时间' => 'require|date',
|
||||
];
|
||||
|
||||
$validate = $this->validateByApi($item, $rules);
|
||||
if ($validate !== true) {
|
||||
return $validate;
|
||||
}
|
||||
|
||||
if ($item['end_at'] <= $item['begin_at']) {
|
||||
throw new ValidateException('优惠期限的截止时间必须大于开始时间!');
|
||||
}
|
||||
|
||||
if ($item['is_home'] == CouponModel::COMMON_ON && empty($item['cover'])) {
|
||||
throw new ValidateException('推荐首页时必传封面图');
|
||||
}
|
||||
|
||||
$data = arrayKeysFilter($item, [
|
||||
'name', 'cover', 'type', 'condition', 'amount', 'begin_at', 'end_at', 'is_home', 'total'
|
||||
]);
|
||||
|
||||
$data['created_at'] = date('Y-m-d H:i:s');
|
||||
$data['remain'] = $data['total'];
|
||||
CouponModel::create($data);
|
||||
} catch (ValidateException $e) {
|
||||
return $this->json(4001, $e->getMessage());
|
||||
} catch (Exception $e) {
|
||||
return $this->json(5000, '新增优惠卷失败!');
|
||||
}
|
||||
|
||||
return $this->json();
|
||||
}
|
||||
|
||||
$this->data['typeList'] = CouponModel::typeTextList();
|
||||
|
||||
return $this->view();
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public function modify()
|
||||
{
|
||||
if (!$this->request->isPost()) {
|
||||
return $this->json(4000, '非法请求');
|
||||
}
|
||||
|
||||
$item = input('post.');
|
||||
$validate = $this->validateByApi($item, [
|
||||
'field' => 'require',
|
||||
'value' => 'require',
|
||||
]);
|
||||
|
||||
if ($validate !== true) {
|
||||
return $validate;
|
||||
}
|
||||
|
||||
if (!$info = CouponModel::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());
|
||||
} catch (Exception $e) {
|
||||
return $this->json(5000, '修改失败');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 软删除
|
||||
*
|
||||
* @return Json
|
||||
*/
|
||||
public function del(): Json
|
||||
{
|
||||
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)) {
|
||||
CouponModel::where('id', 'in', $ids)->save(['deleted_at' => date('Y-m-d H:i:s')]);
|
||||
Log::write(get_class(), 'del', '删除了优惠卷信息,涉及到的ID为:'.implode(',', $ids));
|
||||
}
|
||||
|
||||
return $this->json();
|
||||
}
|
||||
|
||||
//用户持有优惠券的列表
|
||||
public function accountHasList()
|
||||
{
|
||||
$id = input("id/d", 0);
|
||||
if ($this->request->isPost()) {
|
||||
$page = $this->request->param('page/d', 1);
|
||||
$size = $this->request->param('size/d', 20);
|
||||
|
||||
$order = ['id' => 'desc'];
|
||||
$res = AccountCouponModel::findList(["coupon_id" => $id], [], $page, $size, function ($q) {
|
||||
return $q->with(["coupon", "account"]);
|
||||
}, $order);
|
||||
$res['list'] = $res['list']->each(function ($item) {
|
||||
$item->type_text = CouponModel::typeTextList()[$item->type] ?? '';
|
||||
$item->check_by_account = Account::findOne(["id" => $item->check_by,], ["nickname"]);
|
||||
});
|
||||
return $this->json(0, 'success', $res);
|
||||
}
|
||||
$this->data["id"] = $id;
|
||||
return $this->view();
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,128 @@
|
|||
<?php
|
||||
|
||||
namespace app\controller\manager\mall;
|
||||
|
||||
use app\controller\manager\Base;
|
||||
use app\model\Log;
|
||||
use app\model\Express as ExpressModel;
|
||||
use app\repository\OrderRepository;
|
||||
use app\service\Math;
|
||||
use think\db\exception\DataNotFoundException;
|
||||
use think\db\exception\DbException;
|
||||
use think\db\exception\ModelNotFoundException;
|
||||
use think\response\Json;
|
||||
|
||||
/**
|
||||
* 快递配送管理
|
||||
* Class Express
|
||||
* @package app\controller\manager\mall
|
||||
*/
|
||||
class Express extends Base
|
||||
{
|
||||
public function index()
|
||||
{
|
||||
if ($this->request->isPost()) {
|
||||
$items = OrderRepository::getInstance()->allExpress();
|
||||
$items->each(function ($item) {
|
||||
$item->default_price = Math::fen2Yuan($item->default_price);
|
||||
});
|
||||
$data = [
|
||||
'total' => $items->count(),
|
||||
'list' => $items,
|
||||
];
|
||||
|
||||
return $this->json(0, 'success', $data);
|
||||
}
|
||||
|
||||
return $this->view();
|
||||
}
|
||||
|
||||
public function add()
|
||||
{
|
||||
if ($this->request->isPost()) {
|
||||
$data = $this->request->param('item/a', []);
|
||||
$validate = $this->validateByApi($data, [
|
||||
'code|快递代号' => 'require|unique:express',
|
||||
]);
|
||||
|
||||
if ($validate !== true) {
|
||||
return $validate;
|
||||
}
|
||||
|
||||
if ($data['is_default'] == ExpressModel::COMMON_ON) {
|
||||
if (ExpressModel::where('is_default', ExpressModel::COMMON_ON)->count() > 0) {
|
||||
return $this->json(4001, '默认快递已存在');
|
||||
}
|
||||
}
|
||||
|
||||
OrderRepository::getInstance()->addExpress($data);
|
||||
|
||||
return $this->json();
|
||||
}
|
||||
|
||||
return $this->view();
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws DataNotFoundException
|
||||
* @throws ModelNotFoundException
|
||||
* @throws DbException
|
||||
*/
|
||||
public function edit()
|
||||
{
|
||||
$id = $this->request->param('id/d', 0);
|
||||
|
||||
if (!$express = ExpressModel::findById($id)) {
|
||||
return $this->json(4004, '没有相关的快递公司记录');
|
||||
}
|
||||
|
||||
if ($this->request->isPost()) {
|
||||
$data = $this->request->param('item/a', []);
|
||||
$validate = $this->validateByApi($data, [
|
||||
'code|快递代号' => 'require|unique:express,code,'.$id,
|
||||
]);
|
||||
|
||||
if ($validate !== true) {
|
||||
return $validate;
|
||||
}
|
||||
|
||||
if ($data['is_default'] == ExpressModel::COMMON_ON) {
|
||||
if (ExpressModel::where('id', '<>', $id)->where('is_default', ExpressModel::COMMON_ON)->count() > 0) {
|
||||
return $this->json(4001, '默认快递已存在');
|
||||
}
|
||||
}
|
||||
|
||||
$express->save($data);
|
||||
|
||||
return $this->json();
|
||||
}
|
||||
|
||||
$express->default_price = Math::fen2Yuan($express->default_price);
|
||||
$this->data['item'] = $express;
|
||||
$this->data['id'] = $id;
|
||||
return $this->view();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Json
|
||||
*/
|
||||
public function del(): Json
|
||||
{
|
||||
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)) {
|
||||
ExpressModel::deleteByIds($ids);
|
||||
Log::write(get_class(), 'del', '删除了快递记录,涉及到的ID为:'.implode(',', $ids));
|
||||
}
|
||||
|
||||
return $this->json();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,609 @@
|
|||
<?php
|
||||
|
||||
namespace app\controller\manager\mall;
|
||||
|
||||
use app\controller\manager\Base;
|
||||
use app\exception\RepositoryException;
|
||||
use app\exception\TraitException;
|
||||
use app\model\OrderSku;
|
||||
use app\model\Express;
|
||||
use app\repository\OrderRepository;
|
||||
use app\service\Math;
|
||||
use Exception;
|
||||
use PhpOffice\PhpSpreadsheet\IOFactory;
|
||||
use \PhpOffice\PhpSpreadsheet\Shared\Date as PDate;
|
||||
use PhpOffice\PhpSpreadsheet\Style\Alignment; //设置对齐方式
|
||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
|
||||
use think\db\exception\DataNotFoundException;
|
||||
use think\db\exception\DbException;
|
||||
use think\db\exception\ModelNotFoundException;
|
||||
use think\exception\ValidateException;
|
||||
use think\facade\Db;
|
||||
use app\model\Order as OrderModel;
|
||||
use think\facade\Filesystem;
|
||||
use think\response\Json;
|
||||
use think\response\View;
|
||||
|
||||
|
||||
|
||||
|
||||
class Order extends Base
|
||||
{
|
||||
protected $noNeedLogin = ['getOrderSpu', 'checkSku', 'exportOrderList', 'importOrder'];
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
if ($this->request->isPost()) {
|
||||
$page = $this->request->param('page/d', 1);
|
||||
$size = $this->request->param('size/d', 20);
|
||||
$searchParams = $this->request->param('searchParams/a', []);
|
||||
|
||||
$res = $this->getOrderList($searchParams, $page, $size);
|
||||
|
||||
return $this->json(0, 'success', $res);
|
||||
}
|
||||
|
||||
$this->data['statusList'] = OrderModel::statusTextList();
|
||||
|
||||
return $this->view();
|
||||
}
|
||||
|
||||
/**
|
||||
* 积分订单
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function score()
|
||||
{
|
||||
if ($this->request->isPost()) {
|
||||
$page = $this->request->param('page/d', 1);
|
||||
$size = $this->request->param('size/d', 20);
|
||||
$searchParams = $this->request->param('searchParams/a', []);
|
||||
|
||||
$searchParams['is_score'] = OrderModel::COMMON_ON;
|
||||
|
||||
$res = $this->getOrderList($searchParams, $page, $size);
|
||||
|
||||
return $this->json(0, 'success', $res);
|
||||
}
|
||||
|
||||
$this->data['statusList'] = OrderModel::statusTextList();
|
||||
$this->data['dataUrl'] = '/manager/mall/order/score';
|
||||
$this->data['isScore'] = OrderModel::COMMON_ON;
|
||||
|
||||
return $this->view('manager/mall/order/index');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $searchParams
|
||||
* @param int $page
|
||||
* @param int $size
|
||||
* @return array
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function getOrderList(array $searchParams, int $page, int $size): array
|
||||
{
|
||||
// 主动触发:自动检测处理过期订单
|
||||
// OrderRepository::getInstance()->autoCheckInvalidOrders();
|
||||
$status = $searchParams['status'] ?? '';
|
||||
$startAt = $searchParams['start_at'] ?? '';
|
||||
$endAt = $searchParams['end_at'] ?? '';
|
||||
$hasVirtual = $searchParams['has_virtual'] ?? '';
|
||||
$isScore = $searchParams['is_score'] ?? 0;
|
||||
|
||||
$whereMap = [];
|
||||
$order = ['id' => 'desc'];
|
||||
|
||||
$whereMap[] = ['is_score', '=', $isScore];
|
||||
|
||||
if (!empty($status) && in_array($status, array_keys(OrderRepository::getInstance()->orderStatusTextList()))) {
|
||||
$whereMap[] = ['status', '=', $status];
|
||||
}
|
||||
|
||||
if ($hasVirtual != '') {
|
||||
$whereMap[] = ['has_virtual', '=', $hasVirtual];
|
||||
}
|
||||
|
||||
if (!empty($startAt) && strtotime($startAt)) {
|
||||
$whereMap[] = ['created_at', '>= TIME', $startAt];
|
||||
}
|
||||
if (!empty($endAt) && strtotime($endAt)) {
|
||||
$whereMap[] = ['created_at', '<= TIME', $endAt];
|
||||
}
|
||||
if (isset($searchParams['coding']) && !empty($searchParams['coding'])) {
|
||||
$whereMap[] = ['coding', '=', $searchParams['coding']];
|
||||
}
|
||||
|
||||
$res = OrderModel::findList($whereMap, [], $page, $size, function ($q) {
|
||||
return $q->with(['account']);
|
||||
}, $order);
|
||||
|
||||
$res['list'] = $res['list']->each(function ($item) {
|
||||
$item->status_text = OrderModel::statusTextList()[$item->status] ?? '';
|
||||
$item->price = Math::fen2Yuan($item->price);
|
||||
$item->nickname = $item->account->nickname ?? '';
|
||||
$item->real_name = $item->account->real_name ?? '';
|
||||
$item->pick_self_text = $item->pick_self == 1 ? '自提' : '邮寄';
|
||||
$item->is_score_text = $item->is_score == 1 ? '是' : '否';
|
||||
});
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取订单商品列表
|
||||
*
|
||||
* @return Json
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getOrderSpu(): Json
|
||||
{
|
||||
$coding = input('coding/s', '');
|
||||
|
||||
$where = [];
|
||||
$where[] = ['order_coding', '=', $coding];
|
||||
|
||||
$res = OrderSku::findList($where);
|
||||
$res['list'] = $res['list']->each(function ($item) {
|
||||
$item->activity_text = \app\model\Spu::activityTextList()[$item->activity_type] ?? '';
|
||||
});
|
||||
|
||||
return $this->json(0, '操作成功', $res);
|
||||
}
|
||||
|
||||
/**
|
||||
* 核销订单
|
||||
*
|
||||
* @return Json
|
||||
* @throws RepositoryException
|
||||
* @throws DataNotFoundException
|
||||
* @throws DbException
|
||||
* @throws ModelNotFoundException
|
||||
*/
|
||||
public function checkSku(): Json
|
||||
{
|
||||
$coding = input('coding/s', '');
|
||||
$id = input('id/d', 0);
|
||||
$num = input('num/d', 1);
|
||||
|
||||
try {
|
||||
$checkUserInfo = sprintf("ID:%d 昵称:%s", $this->auth['user_id'], $this->auth['nickname']);
|
||||
OrderRepository::getInstance()->checkBase($coding, $id, $num, $checkUserInfo, OrderModel::CHECK_TYPE_BACKEND);
|
||||
event('OrderSpuCheck', $coding);
|
||||
return $this->json(0, '核销成功');
|
||||
} catch (ValidateException $e) {
|
||||
return $this->json(4001, $e->getError());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 订单发货、重发(填写快递信息)
|
||||
* 已有快递记录则覆盖
|
||||
*
|
||||
*/
|
||||
public function send()
|
||||
{
|
||||
$repo = OrderRepository::getInstance();
|
||||
$orderId = $this->request->param('id/d', 0);
|
||||
|
||||
try {
|
||||
$order = $repo->findByid($orderId, [], function ($q) {
|
||||
return $q->with([
|
||||
'account', 'skus' => function ($qr) {
|
||||
$qr->with(['sku']);
|
||||
}
|
||||
]);
|
||||
});
|
||||
|
||||
if (empty($order)) {
|
||||
return $this->json(4004, '没有相关的订单信息!');
|
||||
}
|
||||
} catch (RepositoryException $e) {
|
||||
return $this->json(4004, '没有相关的订单信息!');
|
||||
}
|
||||
|
||||
if ($this->request->isPost()) {
|
||||
$data = [
|
||||
'express_number' => trim($this->request->param('express_number/s', '')),
|
||||
'express_id' => $this->request->param('express_id/d', 0),
|
||||
'business_remarks' => trim($this->request->param('business_remarks/s', ''))
|
||||
];
|
||||
|
||||
Db::startTrans();
|
||||
try {
|
||||
$nowDate = date('Y-m-d H:i:s');
|
||||
|
||||
if ($order->pick_self == 1) {
|
||||
$sendData = [
|
||||
'shipped_at' => $nowDate,
|
||||
'business_remarks' => $data['business_remarks'],
|
||||
];
|
||||
if (empty($order['shipped_at'])) {
|
||||
$sendData['shipped_at'] = $nowDate;
|
||||
}
|
||||
$sendData['status'] = OrderModel::STATUS_SHIPPED;
|
||||
} else {
|
||||
$this->validate($data, [
|
||||
'express_number|快递单号' => 'require|max:100',
|
||||
'express_id|快递公司' => 'require|gt:0',
|
||||
'business_remarks|卖家备注' => 'max:2000',
|
||||
]);
|
||||
if (!$express = Express::findById($data['express_id'])) {
|
||||
throw new ValidateException('没有相关的快递配置信息');
|
||||
}
|
||||
|
||||
if (!in_array($order['status'], [OrderModel::STATUS_PAID, OrderModel::STATUS_SHIPPED])) {
|
||||
throw new ValidateException('该订单当前状态不支持配送信息的录入');
|
||||
}
|
||||
|
||||
$sendData = [
|
||||
'express_number' => $data['express_number'],
|
||||
'express_code' => $express['code'],
|
||||
'express_name' => $express['name'],
|
||||
'business_remarks' => $data['business_remarks'],
|
||||
];
|
||||
if (empty($order['shipped_at']) || $order['express_number'] != $data['express_number']) {
|
||||
$sendData['shipped_at'] = $nowDate;
|
||||
}
|
||||
if ($order['status'] == OrderModel::STATUS_PAID) {
|
||||
$sendData['status'] = OrderModel::STATUS_SHIPPED;
|
||||
}
|
||||
}
|
||||
|
||||
$order->save($sendData);
|
||||
|
||||
Db::commit();
|
||||
} catch (ValidateException $e) {
|
||||
Db::rollback();
|
||||
return $this->json(4001, $e->getMessage());
|
||||
|
||||
} catch (TraitException | RepositoryException $e) {
|
||||
Db::rollback();
|
||||
return $this->json(4002, '配送信息保存失败!');
|
||||
}
|
||||
|
||||
return $this->json();
|
||||
}
|
||||
|
||||
$this->data['id'] = $orderId;
|
||||
$this->data['item'] = $order;
|
||||
$this->data['expressJson'] = $this->handleXmExpress([$order->express_code]);
|
||||
$this->data['statusList'] = OrderModel::statusTextList();
|
||||
return $this->view();
|
||||
}
|
||||
|
||||
/**
|
||||
* 订单详情
|
||||
*
|
||||
* @return Json|View
|
||||
* @throws DataNotFoundException
|
||||
* @throws DbException
|
||||
* @throws ModelNotFoundException
|
||||
*/
|
||||
public function info()
|
||||
{
|
||||
$id = input('id/d', 0);
|
||||
$item = OrderModel::findById($id, [], function ($q) {
|
||||
return $q->with(['account', 'skus']);
|
||||
});
|
||||
|
||||
if ($this->request->isPost()) {
|
||||
$businessRemarks = trim(input('business_remarks/s', ''));
|
||||
|
||||
$item->save(['business_remarks' => $businessRemarks]);
|
||||
|
||||
return $this->json();
|
||||
}
|
||||
|
||||
$this->data['id'] = $id;
|
||||
$this->data['item'] = $item;
|
||||
$this->data['statusList'] = OrderModel::statusTextList();
|
||||
|
||||
return $this->view();
|
||||
}
|
||||
|
||||
private function handleXmOrderStatus(array $selected = [], array $disabled = [])
|
||||
{
|
||||
$list = [];
|
||||
$statusList = OrderRepository::getInstance()->orderStatusTextList();
|
||||
|
||||
foreach ($statusList as $key => $val) {
|
||||
$list[] = [
|
||||
'name' => $val,
|
||||
'value' => $key,
|
||||
'selected' => in_array($key, $selected),
|
||||
'disabled' => in_array($key, $disabled),
|
||||
];
|
||||
}
|
||||
|
||||
return json_encode($list, JSON_UNESCAPED_UNICODE);
|
||||
}
|
||||
|
||||
private function handleXmExpress(array $selected = [], array $disabled = [])
|
||||
{
|
||||
$selected = array_filter($selected);
|
||||
$disabled = array_filter($disabled);
|
||||
|
||||
$list = [];
|
||||
$items = OrderRepository::getInstance()->allExpress();
|
||||
|
||||
foreach ($items as $item) {
|
||||
$list[] = [
|
||||
'name' => $item->name,
|
||||
'value' => $item->id,
|
||||
'selected' => in_array($item->code, $selected),
|
||||
'disabled' => in_array($item->code, $disabled),
|
||||
];
|
||||
}
|
||||
|
||||
return json_encode($list, JSON_UNESCAPED_UNICODE);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出订单列表
|
||||
*
|
||||
* @return Json
|
||||
* @throws DataNotFoundException
|
||||
* @throws DbException
|
||||
* @throws ModelNotFoundException
|
||||
*/
|
||||
public function exportOrderList(): Json
|
||||
{
|
||||
if ($this->request->isPost()) {
|
||||
$ids = input('ids/a', []);
|
||||
$type = input('type/s', 'all');
|
||||
$isScore = input('is_score/d', 0);
|
||||
|
||||
$where = [];
|
||||
$where[] = ['status', '=', OrderModel::STATUS_PAID];
|
||||
$where[] = ['pick_self', '=', OrderModel::COMMON_OFF];
|
||||
if ($type !== 'all') {
|
||||
//获取指定订单列表
|
||||
$where[] = ['id', 'in', $ids];
|
||||
}
|
||||
|
||||
$where[] = ['is_score', '=', $isScore];
|
||||
|
||||
$list = OrderModel::where($where)->order('id', 'desc')->select();
|
||||
|
||||
$result['header'] = [
|
||||
'订单编号', '订单状态', '下单时间', '付款时间', '配送方式', '收货信息', '买家选择快递', '快递编码', '快递单号', '注:1.若快递公司变更,请一定更改快递编码 2.上传物流时请直接在快递单号一栏填写,切勿变更列的顺序'
|
||||
];
|
||||
|
||||
if ($list->isEmpty()) {
|
||||
return $this->json(200, '没有相应订单');
|
||||
}
|
||||
|
||||
$result['data'] = [];
|
||||
$statusList = OrderModel::statusTextList();
|
||||
|
||||
$list->each(function ($item) use (&$result, $statusList) {
|
||||
$arr = [
|
||||
"'".$item['coding'],//订单编号
|
||||
$statusList[$item['status']] ?? '其他',//订单状态
|
||||
"'".$item['created_at'],//下单时间
|
||||
"'".$item['paid_at'],//付款时间
|
||||
$item['pick_self'] == 1 ? '自提' : '邮寄',//配送方式
|
||||
$item['pick_self'] == 1 ? '自提' : $item['address'],//收货信息
|
||||
$item['pick_self'] == 1 ? '自提' : $item['express_name'],//买家选择的快递公司
|
||||
"'".$item['pick_self'] == 1 ? '' : $item['express_code'],//买家选择等快递编码
|
||||
'',//快递单号
|
||||
];
|
||||
|
||||
$result['data'][] = $arr;
|
||||
});
|
||||
|
||||
return $this->json(0, 'success', $result);
|
||||
}
|
||||
return $this->json(4000, '请求错误');
|
||||
}
|
||||
|
||||
/**
|
||||
* 导入物流
|
||||
*
|
||||
* @return Json
|
||||
* @throws DataNotFoundException
|
||||
* @throws DbException
|
||||
* @throws ModelNotFoundException
|
||||
*/
|
||||
public function importOrder(): Json
|
||||
{
|
||||
if ($this->request->isPost()) {
|
||||
$fileSrc = input('file/s', '');
|
||||
$path = public_path().$fileSrc;
|
||||
if (!file_exists($path)) {
|
||||
return $this->json(4000, '文件地址错误'.$path);
|
||||
}
|
||||
|
||||
$inputFileType = IOFactory::identify($path);
|
||||
$reader = IOFactory::createReader($inputFileType);
|
||||
$spreadsheet = $reader->load($path);
|
||||
|
||||
$expressList = Express::column('name', 'code');//快递公司列表
|
||||
$expressCodeList = array_keys($expressList);//快递编号列表
|
||||
|
||||
$sheetData = $spreadsheet->getActiveSheet()->removeRow(1)->toArray(null, true, true, true);
|
||||
|
||||
$orderCodingList = [];
|
||||
$update = [];
|
||||
$now = date('Y-m-d H:i:s');
|
||||
foreach ($sheetData as $key => $data) {
|
||||
$currentKey = $key + 1;
|
||||
if (!isset($data['A']) || empty($data['A'])) {
|
||||
return $this->json(4000, '第'.$currentKey.'行记录订单号不存在');
|
||||
}
|
||||
|
||||
if (!isset($data['H']) || !in_array($data['H'], $expressCodeList)) {
|
||||
return $this->json(4000, '第'.$currentKey.'行快递公司编号不存在');
|
||||
}
|
||||
|
||||
if (!isset($data['I']) || empty($data['I'])) {
|
||||
continue;
|
||||
// 快递单号不存在则不更新
|
||||
// return $this->json(4000, '第'.$currentKey.'行快递单号不存在');
|
||||
}
|
||||
|
||||
$orderCoding = $data['A'];
|
||||
$expressCode = $data['H'];
|
||||
$expressNumber = $data['I'];
|
||||
|
||||
$orderCodingList[] = $orderCoding;
|
||||
|
||||
$update[$orderCoding] = [
|
||||
'coding' => $orderCoding,
|
||||
'status' => OrderModel::STATUS_SHIPPED,
|
||||
'express_code' => $expressCode,
|
||||
'express_number' => $expressNumber,
|
||||
'shipped_at' => $now,
|
||||
'express_name' => $expressList[$expressCode] ?? '',
|
||||
];
|
||||
}
|
||||
|
||||
$orderList = OrderModel::whereIn('coding', $orderCodingList)->column('id,coding,status', 'coding');
|
||||
$notUpdateStatus = [];//不更新状态都记录
|
||||
$existCodings = array_keys($orderList);//数据库存在的订单编号
|
||||
$coding2Id = [];
|
||||
// 仅修改快递信息,不修改订单状态的列表 即仅状态=付款的订单修改状态
|
||||
foreach ($orderList as $order) {
|
||||
if ($order['status'] != OrderModel::STATUS_PAID) {
|
||||
$notUpdateStatus[] = $order['coding'];
|
||||
}
|
||||
$coding2Id[$order['coding']] = $order['id'];
|
||||
}
|
||||
|
||||
// 存在差异的订单号(数据库不存在的)
|
||||
$diff = array_diff($orderCodingList, $existCodings);
|
||||
foreach ($update as $coding => $item) {
|
||||
if (in_array($coding, $diff) || !isset($coding2Id[$coding])) {
|
||||
unset($update[$coding]);
|
||||
continue;
|
||||
}
|
||||
|
||||
$update[$coding]['id'] = $coding2Id[$coding];
|
||||
if (in_array($coding, $notUpdateStatus)) {
|
||||
unset($update[$coding]['status']);
|
||||
}
|
||||
}
|
||||
(new OrderModel())->saveAll($update);
|
||||
|
||||
return $this->json(0, '操作成功', ['count' => count($update)]);
|
||||
}
|
||||
return $this->json(4000, '请求错误');
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改订单里面的sku信息
|
||||
*
|
||||
* @return Json
|
||||
* @throws Exception
|
||||
*/
|
||||
public function editOrderSku(): Json
|
||||
{
|
||||
if ($this->request->isPost()) {
|
||||
$item = input('post.');
|
||||
$validate = $this->validateByApi($item, [
|
||||
'id' => 'require',
|
||||
'field' => 'require',
|
||||
'value' => 'require',
|
||||
]);
|
||||
|
||||
if ($validate !== true) {
|
||||
return $validate;
|
||||
}
|
||||
$orderRep = OrderRepository::getInstance();
|
||||
if (!$orderSkuInfo = $orderRep->getOrderSku($item['id'])) {
|
||||
return $this->json(4001, '订单商品记录不存在');
|
||||
}
|
||||
if (!$order = OrderModel::findOne([["coding","=",$orderSkuInfo["order_coding"]]])) {
|
||||
return $this->json(4001, '订单记录不存在');
|
||||
}
|
||||
Db::startTrans();
|
||||
try {
|
||||
$orderSkuInfo[$item['field']] = $item['value'];
|
||||
//如果是 修改的字段时 数量或者单价 就要调整
|
||||
$orderSkuInfo["subtotal"] = $orderSkuInfo["num"] * $orderSkuInfo["price"];
|
||||
$orderSkuInfo->save();
|
||||
|
||||
$orderOriginalPrice = $orderRep->getOrderOriginalPrice($orderSkuInfo["order_coding"],$orderSkuInfo["coding"]);
|
||||
$orderOriginalPrice += $orderSkuInfo["subtotal"];
|
||||
$order->save(["original_price"=>$orderOriginalPrice]);
|
||||
Db::commit();
|
||||
|
||||
return $this->json(0,"修改成功",["original_price"=>$orderOriginalPrice]);
|
||||
|
||||
} catch (ValidateException $e) {
|
||||
return $this->json(4001, $e->getError());
|
||||
}
|
||||
}
|
||||
return $this->json(4000, '非法请求');
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出订单信息
|
||||
* */
|
||||
public function exportOrderInfo()
|
||||
{
|
||||
$id = input("id/d");
|
||||
$order = OrderModel::findById($id, [], function ($q) {
|
||||
return $q->with([ 'skus']);
|
||||
});
|
||||
|
||||
// 水平居中对齐
|
||||
$styleArray = [
|
||||
'alignment' => [
|
||||
'horizontal' => Alignment::HORIZONTAL_CENTER,
|
||||
'vertical' => Alignment::VERTICAL_CENTER,
|
||||
],
|
||||
];
|
||||
|
||||
// Create new Spreadsheet object
|
||||
$spreadsheet = new Spreadsheet();
|
||||
$sheet = $spreadsheet->getActiveSheet();
|
||||
|
||||
$spreadsheet->getActiveSheet()->setTitle('订单信息');
|
||||
|
||||
//设置默认行高。
|
||||
$sheet->getDefaultRowDimension()->setRowHeight(25);
|
||||
//设置A1单元格
|
||||
$sheet->getStyle('A1')->applyFromArray($styleArray);
|
||||
$setColWidth = [
|
||||
"A"=>"30",
|
||||
"B"=>"30",
|
||||
"C"=>"30",
|
||||
"D"=>"30",
|
||||
"E"=>"30",
|
||||
];
|
||||
foreach ($setColWidth as $key=>$citem){
|
||||
$spreadsheet->getActiveSheet()->getColumnDimension($key)->setWidth($citem);
|
||||
}
|
||||
|
||||
|
||||
//合并单元格
|
||||
$spreadsheet->getActiveSheet()->mergeCells('A1:B1');
|
||||
|
||||
$sheet->setCellValue('A1', "日期:".$order->created_at);
|
||||
|
||||
|
||||
|
||||
//第一种保存方式
|
||||
$writer = new Xlsx($spreadsheet);
|
||||
//保存的路径可自行设置
|
||||
$path = public_path()."storage/order_excel/" ;
|
||||
if(!is_writable($path)){
|
||||
return $this->json("上传文件夹需要写入权限");
|
||||
}
|
||||
$path.=date("Ymd")."/";
|
||||
if(!is_dir($path)){
|
||||
mkdir($path);
|
||||
}
|
||||
$fileName = $order->contacts . "_" . $order->phone . "_" . $order->coding . ".xlsx";
|
||||
$filepath = $path. $fileName;
|
||||
$writer->save($filepath);
|
||||
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,280 @@
|
|||
<?php
|
||||
|
||||
namespace app\controller\manager\mall;
|
||||
|
||||
use app\controller\manager\Base;
|
||||
use app\controller\manager\Upload;
|
||||
use app\exception\RepositoryException;
|
||||
use app\model\mall\SpuLimitTime;
|
||||
use app\model\sku\SpecParam;
|
||||
use app\model\sku\SpecValue;
|
||||
use app\model\sku\SpuType;
|
||||
use app\model\Spu;
|
||||
use app\model\Sku as SkuModel;
|
||||
use Exception;
|
||||
use think\facade\Db;
|
||||
use think\response\Json;
|
||||
|
||||
class Sku extends Base
|
||||
{
|
||||
protected $noNeedRight = [
|
||||
'spuTypeData', 'attrSpecData', 'specValueCreate',
|
||||
'specCreate', 'specValueDelete', 'specDelete', 'upload', 'skuData'
|
||||
];
|
||||
|
||||
/**
|
||||
* 获取SKU数据
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function skuData(): Json
|
||||
{
|
||||
$productId = input('product_id', 0);
|
||||
if ($productId == 0) {
|
||||
return $this->json(200, 'success', []);
|
||||
}
|
||||
|
||||
$spu = Spu::findById($productId, ['id', 'activity_id', 'activity_type', 'multi_spec']);
|
||||
$res = [];
|
||||
|
||||
switch ($spu['activity_type']) {
|
||||
case SpuLimitTime::TYPE:
|
||||
$where = ['spu_activity_id' => $spu['activity_id'], 'type' => $spu['activity_type']];
|
||||
break;
|
||||
default:
|
||||
$where = ['spu_id' => $productId];
|
||||
}
|
||||
|
||||
if ($spu['multi_spec'] > 0) {
|
||||
$list = SkuModel::where($where)->whereNull('deleted_at')->whereNotNull('indexes')->select();
|
||||
foreach ($list as $item) {
|
||||
$key = $item['indexes'];
|
||||
|
||||
$res[sprintf("skus[%s][%s]", $key, 'id')] = $item['id'];
|
||||
$res[sprintf("skus[%s][%s]", $key, 'stock')] = $item['stock'];
|
||||
$res[sprintf("skus[%s][%s]", $key, 'original_price')] = $item['original_price'];
|
||||
$res[sprintf("skus[%s][%s]", $key, 'price')] = $item['price'];
|
||||
$res[sprintf("skus[%s][%s]", $key, 'picture')] = $item['picture'];
|
||||
$res[sprintf("skus[%s][%s]", $key, 'is_default')] = $item['is_default'];
|
||||
$res[sprintf("skus[%s][%s]", $key, 'coding')] = $item['coding'];
|
||||
$res[sprintf("skus[%s][%s]", $key, 'status')] = $item['status'];
|
||||
}
|
||||
} else {
|
||||
$item = SkuModel::where($where)->where('is_default', 1)->find();
|
||||
|
||||
$res['skus[id]'] = $item['id'];
|
||||
$res['skus[stock]'] = $item['stock'];
|
||||
$res['skus[original_price]'] = $item['original_price'];
|
||||
$res['skus[price]'] = $item['price'];
|
||||
$res['skus[coding]'] = $item['coding'];
|
||||
$res['skus[status]'] = $item['status'];
|
||||
$res['skus[is_default]'] = $item['is_default'];
|
||||
}
|
||||
|
||||
return $this->json(200, 'success', $res);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取商品类型列表
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function spuTypeData(): Json
|
||||
{
|
||||
$list = SpuType::where('status', SpuType::COMMON_ON)
|
||||
->order('sort', 'desc')
|
||||
->order('id', 'asc')
|
||||
->field('id,title')
|
||||
->select();
|
||||
|
||||
return $this->json(200, 'success', $list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取商品类型下的规格和属性
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function attrSpecData(): Json
|
||||
{
|
||||
$spuTypeId = input('product_type_id/d');
|
||||
$productId = input('product_id/d', 0);//商品ID
|
||||
|
||||
$spuInfo = Spu::findById($productId, ['id', 'activity_id', 'activity_type', 'multi_spec', 'spec']);
|
||||
|
||||
$selectSpec = [];
|
||||
if ($spuInfo) {
|
||||
switch ($spuInfo['activity_type']) {
|
||||
case SpuLimitTime::TYPE:
|
||||
$selectSpec = SpuLimitTime::where('id', $spuInfo['activity_id'])->value('spec');
|
||||
break;
|
||||
default:
|
||||
$selectSpec = $spuInfo['spec'];
|
||||
}
|
||||
$selectSpec = json_decode($selectSpec, true);
|
||||
}
|
||||
|
||||
$specIds = SpuType::where('id', $spuTypeId)->value('spec_ids');
|
||||
$specIdArr = explode(',', $specIds);
|
||||
$list = SpecParam::whereIn('id', $specIdArr)
|
||||
->where('status', SpecParam::COMMON_ON)
|
||||
->with([
|
||||
'specValue' => function ($q) {
|
||||
$q->where('status', SpecValue::COMMON_ON)->order('sort', 'desc')->order('id', 'asc');
|
||||
}
|
||||
])
|
||||
->order('sort', 'desc')
|
||||
->order('id', 'asc')
|
||||
->field('id,title')
|
||||
->select();
|
||||
$spec = [];//规格
|
||||
$attr = [];//属性
|
||||
$list->each(function ($item) use (&$spec, $selectSpec) {
|
||||
$arr = [];
|
||||
$arr['id'] = (string) $item->id;
|
||||
$arr['title'] = $item->title;
|
||||
$arr['options'] = $item->specValue->each(function ($spec) {
|
||||
$spec->id = (string) $spec->id;
|
||||
unset($spec->sort);
|
||||
unset($spec->spec_id);
|
||||
unset($spec->status);
|
||||
unset($spec->created_at);
|
||||
unset($spec->updated_at);
|
||||
});
|
||||
$arr['value'] = $selectSpec[$item->id] ?? [];
|
||||
$spec[] = $arr;
|
||||
});
|
||||
|
||||
return $this->json(200, 'success', ['spec' => $spec, 'attribute' => $attr]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建规格值
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function specValueCreate(): Json
|
||||
{
|
||||
$params = input('post.');
|
||||
$rules = [
|
||||
'spec_id|规格ID' => 'require|number',
|
||||
'title|规格值' => 'require',
|
||||
];
|
||||
|
||||
$validate = $this->validateByApi($params, $rules);
|
||||
|
||||
if ($validate !== true) {
|
||||
return $validate;
|
||||
}
|
||||
|
||||
$count = SpecValue::where('spec_id', $params['spec_id'])
|
||||
->where('title', $params['title'])
|
||||
->where('status', SpecValue::COMMON_ON)
|
||||
->count();
|
||||
if ($count > 0) {
|
||||
return $this->json(4000, '规格值已存在');
|
||||
}
|
||||
|
||||
$value = SpecValue::create([
|
||||
'spec_id' => $params['spec_id'],
|
||||
'title' => $params['title'],
|
||||
]);
|
||||
|
||||
return $this->json(200, 'success', ['id' => $value->id]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建规格
|
||||
*
|
||||
* @return bool|Json
|
||||
* @throws Exception
|
||||
*/
|
||||
public function specCreate()
|
||||
{
|
||||
$params = input('post.');
|
||||
$rules = [
|
||||
'product_type_id|商品类型' => 'require|number',
|
||||
'title|规格名称' => 'require',
|
||||
];
|
||||
|
||||
$validate = $this->validateByApi($params, $rules);
|
||||
|
||||
if ($validate !== true) {
|
||||
return $validate;
|
||||
}
|
||||
|
||||
$count = SpecParam::where('spu_type_id', $params['product_type_id'])
|
||||
->where('title', $params['title'])
|
||||
->where('status', SpecParam::COMMON_ON)
|
||||
->count();
|
||||
if ($count > 0) {
|
||||
return $this->json(4000, '规格名称已存在');
|
||||
}
|
||||
|
||||
$param = SpecParam::create([
|
||||
'spu_type_id' => $params['product_type_id'],
|
||||
'title' => $params['title'],
|
||||
]);
|
||||
|
||||
$specIds = SpecParam::where('spu_type_id', $params['product_type_id'])->column('id');
|
||||
// 更新商品类型
|
||||
SpuType::where('id', $params['product_type_id'])->save(['spec_ids' => implode(',', $specIds)]);
|
||||
|
||||
return $this->json(200, 'success', ['id' => $param->id]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 规格删除
|
||||
*
|
||||
* @return Json
|
||||
* @throws Exception
|
||||
*/
|
||||
public function specDelete(): Json
|
||||
{
|
||||
$id = input('post.id/d', 0);
|
||||
if ($id <= 0) {
|
||||
return $this->json(4000, '参数错误');
|
||||
}
|
||||
|
||||
SpecParam::where('id', $id)->save(['status' => -1]);
|
||||
SpecValue::where('spec_id', $id)->save(['status' => -1]);
|
||||
|
||||
return $this->json(200, 'success');
|
||||
}
|
||||
|
||||
/**
|
||||
* 规格值删除
|
||||
*
|
||||
* @return Json
|
||||
* @throws Exception
|
||||
*/
|
||||
public function specValueDelete(): Json
|
||||
{
|
||||
$id = input('post.id/d', 0);
|
||||
if ($id <= 0) {
|
||||
return $this->json(4000, '参数错误');
|
||||
}
|
||||
|
||||
SpecValue::where('id', $id)->save(['status' => -1]);
|
||||
|
||||
return $this->json(200, 'success');
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传图片
|
||||
*
|
||||
* @return Json
|
||||
*/
|
||||
public function upload(): Json
|
||||
{
|
||||
// 字段名 image-image避免冲突 layui组件自动生成的隐藏file input框中name容易重名冲突
|
||||
$image = request()->file('file');
|
||||
try {
|
||||
$res = (new Upload())->uploadImage($image);
|
||||
$res['url'] = $res['src'];
|
||||
return $this->json(200, '上传成功', $res);
|
||||
} catch (RepositoryException $e) {
|
||||
return $this->json(1, $e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,488 @@
|
|||
<?php
|
||||
|
||||
namespace app\controller\manager\mall;
|
||||
|
||||
use app\controller\manager\Base;
|
||||
use app\exception\RepositoryException;
|
||||
use app\model\Config;
|
||||
use app\model\Log;
|
||||
use app\model\mall\SpuCategoryPivot;
|
||||
use app\model\Sku;
|
||||
use app\model\Spu as SpuModel;
|
||||
use app\repository\SpuRepository;
|
||||
use app\service\Math;
|
||||
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 Spu extends Base
|
||||
{
|
||||
protected $noNeedRight = ['getSpuList', 'getSkuList', 'checkActivity', 'getSpu'];
|
||||
|
||||
/**
|
||||
* @throws ModelNotFoundException
|
||||
* @throws DbException
|
||||
* @throws DataNotFoundException
|
||||
* @throws Exception
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
if ($this->request->isPost()) {
|
||||
$params = input();
|
||||
|
||||
$res = SpuRepository::getInstance()->list($params);
|
||||
|
||||
$res['list'] = $res['list']->each(function ($item) {
|
||||
$text = $item->saleable ? '已上架' : '已下架';
|
||||
if ($item->is_activity > 0) {
|
||||
$activityText = SpuModel::activityTextList()[$item->activity_type];
|
||||
$text = '<span style="color: red;">'.$text.' '.$activityText.'中</span>';
|
||||
}
|
||||
|
||||
$item->saleable_text = $text;
|
||||
});
|
||||
|
||||
return $this->json(0, 'success', $res);
|
||||
}
|
||||
|
||||
$this->data['mpPath'] = Config::MINI_PATH_SPU_INFO;;
|
||||
$this->data['statusList'] = SpuModel::statusTextList();
|
||||
$this->data['spuTypeList'] = SpuModel::spuTypeTextList();
|
||||
|
||||
return $this->view();
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ModelNotFoundException
|
||||
* @throws DbException
|
||||
* @throws DataNotFoundException
|
||||
* @throws Exception
|
||||
*/
|
||||
public function score()
|
||||
{
|
||||
if ($this->request->isPost()) {
|
||||
$params = input();
|
||||
$params['type'] = SpuModel::TYPE_SCORE;
|
||||
|
||||
$res = SpuRepository::getInstance()->list($params);
|
||||
|
||||
$res['list'] = $res['list']->each(function ($item) {
|
||||
$text = $item->saleable ? '已上架' : '已下架';
|
||||
$item->saleable_text = $text;
|
||||
});
|
||||
return $this->json(0, 'success', $res);
|
||||
}
|
||||
|
||||
$this->data['mpPath'] = Config::MINI_PATH_SPU_INFO;;
|
||||
|
||||
$this->data['statusList'] = SpuModel::statusTextList();
|
||||
$this->data['spuTypeList'] = SpuModel::spuTypeTextList();
|
||||
$this->data['url'] = '/manager/mall/spu/score';
|
||||
$this->data['type'] = SpuModel::TYPE_SCORE;
|
||||
|
||||
return $this->view('manager/mall/spu/index');
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加
|
||||
*
|
||||
* @return Json|View
|
||||
* @throws DataNotFoundException
|
||||
* @throws DbException
|
||||
* @throws ModelNotFoundException
|
||||
*/
|
||||
public function add()
|
||||
{
|
||||
$repo = SpuRepository::getInstance();
|
||||
$type = input('type', SpuModel::TYPE_NORMAL);
|
||||
if ($this->request->isPost()) {
|
||||
$item = $this->request->param('item/a', []);
|
||||
|
||||
$item['is_score'] = $type == SpuModel::TYPE_SCORE;
|
||||
$item['is_activity'] = in_array($type, SpuModel::activityList());
|
||||
$item['activity_type'] = $type;
|
||||
|
||||
$multiSpec = input('post.is_attribute');// 是否多规格 0否 1是
|
||||
$skus = input('post.skus');//规格数据
|
||||
$item['spu_type_id'] = input('post.product_type');//商品类型ID
|
||||
$item['multi_spec'] = $multiSpec;
|
||||
|
||||
if ($multiSpec == SpuModel::COMMON_OFF) {
|
||||
$skus = [$skus];
|
||||
}
|
||||
try {
|
||||
$this->checkData($item, $skus);
|
||||
|
||||
$repo->addSpu($item, $skus);
|
||||
} catch (RepositoryException $e) {
|
||||
return $this->json(4002, $e->getMessage());
|
||||
} catch (Exception $e) {
|
||||
}
|
||||
|
||||
return $this->json();
|
||||
}
|
||||
|
||||
$categoryList = $repo->categoryXmSelect([], [], true);
|
||||
|
||||
$this->data['statusList'] = SpuModel::statusTextList();
|
||||
$this->data['spuTypeList'] = SpuModel::spuTypeTextList();
|
||||
$this->data['limitList'] = SpuModel::limitList();
|
||||
$this->data['categoryJson'] = json_encode($categoryList, JSON_UNESCAPED_UNICODE);
|
||||
$this->data['type'] = $type;
|
||||
$this->data['isScore'] = $type === SpuModel::TYPE_SCORE;
|
||||
|
||||
return $this->view();
|
||||
}
|
||||
|
||||
/**
|
||||
* 检测商品是否处于活动
|
||||
*
|
||||
* @return Json
|
||||
* @throws RepositoryException
|
||||
*/
|
||||
public function checkActivity(): Json
|
||||
{
|
||||
$repo = SpuRepository::getInstance();
|
||||
$id = $this->request->param('id/d', 0);
|
||||
$spu = $repo->findById($id);
|
||||
if (empty($spu)) {
|
||||
return $this->json(4000, '没有相关的商品记录!');
|
||||
}
|
||||
|
||||
if ($spu->is_activity > 0) {
|
||||
$activityText = SpuModel::activityTextList()[$spu['activity_type']] ?? '';
|
||||
$msg = '该商品正在参与'.$activityText.'活动 无法进行此操作!';
|
||||
return $this->json(4000, $msg);
|
||||
}
|
||||
|
||||
return $this->json();
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws DataNotFoundException
|
||||
* @throws ModelNotFoundException
|
||||
* @throws DbException|RepositoryException
|
||||
*/
|
||||
public function edit()
|
||||
{
|
||||
$repo = SpuRepository::getInstance();
|
||||
$id = $this->request->param('id/d', 0);
|
||||
$spu = $repo->findById($id);
|
||||
if (empty($spu)) {
|
||||
return $this->json(4000, '没有相关的商品记录!');
|
||||
}
|
||||
|
||||
if ($spu->is_activity > 0) {
|
||||
$activityText = SpuModel::activityTextList()[$spu['activity_type']] ?? '';
|
||||
$msg = '该商品正在参与'.$activityText.'活动 无法进行此操作!';
|
||||
if ($this->request->isPost()) {
|
||||
return $this->json(4000, $msg);
|
||||
} else {
|
||||
return $this->error($msg);
|
||||
}
|
||||
}
|
||||
|
||||
$skuList = Sku::where('spu_id', $id)
|
||||
->where('spu_activity_id', 0)
|
||||
->where('enable', Sku::COMMON_ON)
|
||||
->order('sort', 'asc')
|
||||
->order('id', 'asc')->select()->toArray();
|
||||
|
||||
if ($this->request->isPost()) {
|
||||
$item = $this->request->param('item/a', []);
|
||||
$multiSpec = input('post.is_attribute');// 是否多规格 0否 1是
|
||||
$skus = input('post.skus');//规格数据
|
||||
$item['spu_type_id'] = input('post.product_type');//商品类型ID
|
||||
$item['multi_spec'] = $multiSpec;
|
||||
|
||||
if ($multiSpec == SpuModel::COMMON_OFF) {
|
||||
$skus = [$skus];
|
||||
}
|
||||
|
||||
try {
|
||||
$this->checkData($item, $skus);
|
||||
|
||||
$repo->editSpu($id, $item, $skus, $skuList);
|
||||
} catch (RepositoryException $e) {
|
||||
return $this->json(4002, $e->getMessage());
|
||||
} catch (Exception $e) {
|
||||
}
|
||||
|
||||
return $this->json();
|
||||
}
|
||||
|
||||
$hasCategories = SpuCategoryPivot::where('spu_id', $id)->column('category_id');
|
||||
$categoryList = $repo->categoryXmSelect($hasCategories, [], true);
|
||||
|
||||
$this->data['statusList'] = SpuModel::statusTextList();
|
||||
$this->data['spuTypeList'] = SpuModel::spuTypeTextList();
|
||||
$this->data['limitList'] = SpuModel::limitList();
|
||||
$this->data['categoryJson'] = json_encode($categoryList, JSON_UNESCAPED_UNICODE);
|
||||
$this->data['isScore'] = $spu->is_score;
|
||||
$this->data['item'] = $spu;
|
||||
$this->data['skuList'] = $skuList;
|
||||
$this->data['id'] = $id;
|
||||
return $this->view();
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查数据
|
||||
*
|
||||
* @throws RepositoryException
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function checkData(array $item, array $skus)
|
||||
{
|
||||
// 基础信息验证
|
||||
$validate = $this->validateByApi($item, [
|
||||
'name|商品名称' => 'require|max:250',
|
||||
'cover|商品封面' => 'require|max:250',
|
||||
'saleable|商品状态' => 'in:0,1',
|
||||
'published_at|发布日期' => 'requireIf:saleable,1|date',
|
||||
'subtitle|副标题' => 'max:2000',
|
||||
]);
|
||||
|
||||
if ($validate !== true) {
|
||||
return $validate;
|
||||
}
|
||||
|
||||
if (empty($skus)) {
|
||||
throw new RepositoryException('规格信息不能为空');
|
||||
}
|
||||
|
||||
foreach ($skus as $k) {
|
||||
if ($this->validateSku($k) !== true) {
|
||||
return $validate;
|
||||
}
|
||||
}
|
||||
|
||||
return $validate;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取验证结果
|
||||
*
|
||||
* @param $sku
|
||||
* @return bool|Json
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function validateSku($sku)
|
||||
{
|
||||
return $this->validateByApi($sku, [
|
||||
'stock' => 'require|number|gt:0',
|
||||
'original_price' => 'number',
|
||||
'price' => 'number',
|
||||
'score' => 'number',
|
||||
'is_default' => 'require|in:0,1',
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ModelNotFoundException
|
||||
* @throws DbException
|
||||
* @throws DataNotFoundException
|
||||
* @throws Exception
|
||||
*/
|
||||
public function modify()
|
||||
{
|
||||
if (!$this->request->isPost()) {
|
||||
return $this->json(4000, '非法请求');
|
||||
}
|
||||
|
||||
$item = input('post.');
|
||||
$validate = $this->validateByApi($item, [
|
||||
'field' => 'require',
|
||||
'value' => 'require',
|
||||
]);
|
||||
|
||||
if ($validate !== true) {
|
||||
return $validate;
|
||||
}
|
||||
|
||||
if (!$info = SpuModel::findById($item['id'])) {
|
||||
return $this->json(4001, '记录不存在');
|
||||
}
|
||||
|
||||
if ($item['field'] == 'home_display') {
|
||||
$v = $item['value'] == 1 ? 'big' : 'normal';
|
||||
$item['value'] = $v;
|
||||
}
|
||||
|
||||
$update = [$item['field'] => $item['value']];
|
||||
|
||||
try {
|
||||
$info->save($update);
|
||||
return $this->json();
|
||||
} catch (ValidateException $e) {
|
||||
return $this->json(4001, $e->getError());
|
||||
} catch (Exception $e) {
|
||||
return $this->json(5000, '修改失败');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Json
|
||||
*/
|
||||
public function del(): Json
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
try {
|
||||
if (count($ids)) {
|
||||
$count = SpuModel::whereIn('id', $ids)
|
||||
->where('is_activity|saleable', SpuModel::COMMON_ON)
|
||||
->count();
|
||||
if ($count > 0) {
|
||||
return $this->json(4002, '当前商品状态不可删除!');
|
||||
}
|
||||
|
||||
SpuRepository::getInstance()->deleteSpu($ids);
|
||||
Log::write(get_class(), 'del', '删除了商品信息,涉及到的ID为:'.implode(',', $ids));
|
||||
}
|
||||
} catch (RepositoryException $e) {
|
||||
return $this->json(4001, $e->getMessage());
|
||||
}
|
||||
|
||||
return $this->json();
|
||||
}
|
||||
|
||||
/**
|
||||
* 商品详情
|
||||
*/
|
||||
public function info()
|
||||
{
|
||||
$skuId = $this->request->param('id/d', 0);
|
||||
$repo = SpuRepository::getInstance();
|
||||
try {
|
||||
$sku = $repo->findById($skuId, []);
|
||||
} catch (RepositoryException $e) {
|
||||
$sku = null;
|
||||
}
|
||||
|
||||
$this->data['item'] = $sku;
|
||||
return $this->view();
|
||||
}
|
||||
|
||||
/**
|
||||
* 商品状态下拉选项
|
||||
*
|
||||
* @param array $selected
|
||||
* @param array $disabled
|
||||
* @return false|string
|
||||
*/
|
||||
private function handleXmStatus(array $selected = [], array $disabled = [])
|
||||
{
|
||||
$items = SpuModel::statusTextList();
|
||||
$list = [];
|
||||
foreach ($items as $key => $val) {
|
||||
$list[] = [
|
||||
'name' => $val,
|
||||
'value' => $key,
|
||||
'selected' => in_array($key, $selected),
|
||||
'disabled' => in_array($key, $disabled),
|
||||
];
|
||||
}
|
||||
return json_encode($list, JSON_UNESCAPED_UNICODE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getSpuList(): Json
|
||||
{
|
||||
if ($this->request->isPost()) {
|
||||
$input = [
|
||||
'type' => SpuModel::TYPE_NORMAL,
|
||||
'saleable' => SpuModel::COMMON_ON,
|
||||
'keyword' => input('keyword/s', '')
|
||||
];
|
||||
$data = SpuRepository::getInstance()->list($input);
|
||||
return $this->json(0, 'success', $data);
|
||||
}
|
||||
|
||||
return $this->json(4000, '操作错误');
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getSpu(): Json
|
||||
{
|
||||
if ($this->request->isPost()) {
|
||||
$id = input('id/d');
|
||||
$data = SpuModel::findById($id, ['id', 'spu_type_id', 'multi_spec']);
|
||||
return $this->json(0, 'success', $data);
|
||||
}
|
||||
|
||||
return $this->json(4000, '操作错误');
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getSkuList(): Json
|
||||
{
|
||||
if ($this->request->isPost()) {
|
||||
$spuId = input('id/d', 0);
|
||||
$data = Sku::where('spu_id', $spuId)->select();
|
||||
$data = $data->each(function ($item) {
|
||||
$item->original_price = Math::fen2Yuan($item->original_price);
|
||||
$item->price = Math::fen2Yuan($item->price);
|
||||
});
|
||||
return $this->json(0, 'success', $data);
|
||||
}
|
||||
|
||||
return $this->json(4000, '操作错误');
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量审核
|
||||
*
|
||||
* @return View|Json
|
||||
* @throws Exception
|
||||
*/
|
||||
public function check()
|
||||
{
|
||||
$id = input('id/s', '');
|
||||
if ($this->request->isPost()) {
|
||||
$ids = input('ids/s');
|
||||
$check = input('is_check/d');
|
||||
|
||||
if (!in_array($check, [SpuModel::COMMON_ON, SpuModel::COMMON_OFF])) {
|
||||
|
||||
return $this->json(4001, '请选择是否展示');
|
||||
}
|
||||
|
||||
$ids = explode(',', $ids);
|
||||
|
||||
Db::startTrans();
|
||||
try {
|
||||
(new SpuModel())->whereIn('id', $ids)->save(['is_check' => $check]);
|
||||
Db::commit();
|
||||
return $this->json(0, '操作成功');
|
||||
} catch (Exception $e) {
|
||||
Db::rollback();
|
||||
Log::error('商品批量审核操作失败'.$e->getMessage());
|
||||
return $this->json(5001, '商品批量审核操作失败');
|
||||
}
|
||||
}
|
||||
|
||||
$this->data['id'] = $id;
|
||||
|
||||
return $this->view();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,355 @@
|
|||
<?php
|
||||
|
||||
namespace app\controller\manager\mall\activity;
|
||||
|
||||
use app\controller\manager\Base;
|
||||
use app\exception\RepositoryException;
|
||||
use app\model\Log;
|
||||
use app\model\mall\SpuLimitTime;
|
||||
use app\model\Order;
|
||||
use app\model\Sku;
|
||||
use app\model\Spu as SpuModel;
|
||||
use app\model\SpuActivity;
|
||||
use app\repository\SpuRepository;
|
||||
use app\service\Math;
|
||||
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 LimitTime extends Base
|
||||
{
|
||||
protected $noNeedLogin = ['getOrder'];
|
||||
|
||||
/**
|
||||
* 列表
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
if ($this->request->isPost()) {
|
||||
$keyword = input('keyword/s');
|
||||
$page = input('page/d', 1);
|
||||
$size = input('size/d', 20);
|
||||
|
||||
$where = [];
|
||||
if (!empty($keyword)) {
|
||||
$where[] = ['keyword', 'like', '%'.$keyword.'%'];
|
||||
}
|
||||
$where[] = ['deleted_at', 'exp', Db::raw('is null')];
|
||||
$order = ['sort' => 'desc', 'id' => 'desc'];
|
||||
$res = SpuLimitTime::fetchList($where, [], $page, $size, null, $order);
|
||||
|
||||
return $this->json(0, 'success', $res);
|
||||
}
|
||||
|
||||
return $this->view();
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ModelNotFoundException
|
||||
* @throws DbException
|
||||
* @throws DataNotFoundException
|
||||
* @throws Exception
|
||||
*/
|
||||
public function add()
|
||||
{
|
||||
if ($this->request->isPost()) {
|
||||
$item = $this->request->param('item/a', []);
|
||||
$skus = input('post.skus');//规格数据
|
||||
$spuId = $this->request->param('spu_id/d', 0);
|
||||
|
||||
$rules = [
|
||||
'name|活动名称' => 'require',
|
||||
'cover|封面图' => 'require',
|
||||
'begin_at|开始时间' => 'require|date',
|
||||
'end_at|结束时间' => 'require|date',
|
||||
];
|
||||
|
||||
$validate = $this->validateByApi($item, $rules);
|
||||
if ($validate !== true) {
|
||||
return $validate;
|
||||
}
|
||||
|
||||
try {
|
||||
$item['spu_id'] = $spuId;
|
||||
SpuRepository::getInstance()->addLimitTime($item, $skus);
|
||||
} catch (RepositoryException $e) {
|
||||
return $this->json(4002, $e->getMessage());
|
||||
} catch (Exception $e) {
|
||||
SpuRepository::log('限时折扣创建失败', $e);
|
||||
return $this->json(5000, '限时折扣创建失败');
|
||||
}
|
||||
|
||||
return $this->json();
|
||||
}
|
||||
|
||||
return $this->view();
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws DataNotFoundException
|
||||
* @throws ModelNotFoundException
|
||||
* @throws DbException
|
||||
*/
|
||||
public function edit()
|
||||
{
|
||||
$id = $this->request->param('id/d', 0);
|
||||
|
||||
if ($this->request->isPost()) {
|
||||
$item = $this->request->param('item/a', []);
|
||||
$skus = $this->request->param('skus');
|
||||
|
||||
$rules = [
|
||||
'name|活动名称' => 'require',
|
||||
'cover|封面图' => 'require',
|
||||
'begin_at|开始时间' => 'require|date',
|
||||
'end_at|结束时间' => 'require|date',
|
||||
];
|
||||
|
||||
$validate = $this->validateByApi($item, $rules);
|
||||
if ($validate !== true) {
|
||||
return $validate;
|
||||
}
|
||||
|
||||
try {
|
||||
SpuRepository::getInstance()->editLimitTime($id, $item, $skus);
|
||||
} catch (RepositoryException $e) {
|
||||
return $this->json(4002, $e->getMessage());
|
||||
} catch (Exception $e) {
|
||||
}
|
||||
|
||||
return $this->json();
|
||||
}
|
||||
|
||||
$limitTime = SpuLimitTime::findById($id);
|
||||
if (empty($limitTime)) {
|
||||
return $this->json(4000, '没有相关记录!');
|
||||
}
|
||||
if (!$spuInfo = SpuModel::findById($limitTime['spu_id'], ['id', 'name', 'multi_spec', 'spu_type_id'])) {
|
||||
return $this->json(4000, '基础商品不存在!');
|
||||
}
|
||||
|
||||
$this->data['item'] = $limitTime;
|
||||
$this->data['id'] = $id;
|
||||
$this->data['spu'] = $spuInfo;
|
||||
return $this->view();
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws RepositoryException
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function checkSku(array $sku)
|
||||
{
|
||||
// sku验证
|
||||
if (empty($sku)) {
|
||||
throw new RepositoryException('规格信息不能为空');
|
||||
}
|
||||
|
||||
foreach ($sku as $k) {
|
||||
$validate = $this->validateByApi($k, [
|
||||
'title' => 'require',
|
||||
'stock' => 'require|number|gt:0',
|
||||
'price' => 'number',
|
||||
'score' => 'number',
|
||||
'is_default' => 'require|in:0,1',
|
||||
]);
|
||||
|
||||
if ($validate !== true) {
|
||||
return $validate;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ModelNotFoundException
|
||||
* @throws DbException
|
||||
* @throws DataNotFoundException
|
||||
* @throws Exception
|
||||
*/
|
||||
public function modify()
|
||||
{
|
||||
if (!$this->request->isPost()) {
|
||||
return $this->json(4000, '非法请求');
|
||||
}
|
||||
|
||||
$item = input('post.');
|
||||
$validate = $this->validateByApi($item, [
|
||||
'field' => 'require',
|
||||
'value' => 'require',
|
||||
]);
|
||||
|
||||
if ($validate !== true) {
|
||||
return $validate;
|
||||
}
|
||||
|
||||
if (!$info = SpuActivity::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());
|
||||
} catch (Exception $e) {
|
||||
return $this->json(5000, '修改失败');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除-还原为普通商品且软删除
|
||||
*
|
||||
* @return Json
|
||||
*/
|
||||
public function del(): Json
|
||||
{
|
||||
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);
|
||||
}
|
||||
try {
|
||||
if (count($ids)) {
|
||||
SpuRepository::getInstance()->restoreLimitTime($ids, true);
|
||||
Log::write(get_class(), 'del', '删除了活动商品,涉及到的ID为:'.implode(',', $ids));
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
return $this->json(4001, $e->getMessage());
|
||||
}
|
||||
|
||||
return $this->json();
|
||||
}
|
||||
|
||||
/**
|
||||
* 结束-还原为普通商品 暂停
|
||||
*
|
||||
* @return Json
|
||||
*/
|
||||
public function end(): Json
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
try {
|
||||
if (count($ids)) {
|
||||
SpuRepository::getInstance()->restoreLimitTime($ids);
|
||||
Log::write(get_class(), 'del', '结束了活动商品,涉及到的ID为:'.implode(',', $ids));
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
return $this->json(4001, $e->getMessage());
|
||||
}
|
||||
|
||||
return $this->json();
|
||||
}
|
||||
|
||||
/**
|
||||
* 重新启动
|
||||
*
|
||||
* @return Json
|
||||
*/
|
||||
public function restart(): Json
|
||||
{
|
||||
if (!$this->request->isPost()) {
|
||||
return $this->json(4000, '非法请求');
|
||||
}
|
||||
|
||||
try {
|
||||
$ids = input('ids');
|
||||
SpuRepository::getInstance()->restart($ids[0]);
|
||||
Log::write(get_class(), 'restart', '重启了活动商品,涉及到的ID为:'.$ids[0]);
|
||||
} catch (Exception $e) {
|
||||
return $this->json(4001, $e->getMessage());
|
||||
}
|
||||
|
||||
return $this->json();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 活动商品详情
|
||||
*
|
||||
* @return View
|
||||
* @throws DataNotFoundException
|
||||
* @throws DbException
|
||||
* @throws ModelNotFoundException
|
||||
* @throws Exception
|
||||
*/
|
||||
public function info(): View
|
||||
{
|
||||
$id = input('id/d', 0);
|
||||
$item = SpuActivity::findById($id);
|
||||
|
||||
$status = '';
|
||||
$now = date('Y-m-d H:i:s');
|
||||
if ($item['begin_at'] > $now) {
|
||||
$status = '未开始';
|
||||
}
|
||||
|
||||
if ($item['begin_at'] < $now && $now < $item['end_at']) {
|
||||
$status = '进行中';
|
||||
}
|
||||
|
||||
if ($item['status'] == 0 || $item['end_at'] < $now) {
|
||||
$status = '已结束';
|
||||
}
|
||||
|
||||
$item->status_text = $status;
|
||||
|
||||
|
||||
$orderList = SpuRepository::getInstance()->getActivityOrderList($id);
|
||||
|
||||
$totalPriceList = $orderList['list']->where('is_paid', SpuActivity::COMMON_ON)->column('total_price');
|
||||
$codingList = $orderList['list']->column('coding');
|
||||
$accountList = $orderList['list']->column('account_id');
|
||||
$codingCount = count(array_unique($codingList));
|
||||
$accountCount = count(array_unique($accountList));
|
||||
$totalPrice = array_sum($totalPriceList);
|
||||
$item->total_money = Math::fen2Yuan($totalPrice) ?? 0;
|
||||
$item->order_count = $codingCount;
|
||||
$item->account_count = $accountCount;
|
||||
|
||||
$this->data['item'] = $item;
|
||||
$this->data['statusList'] = Order::statusTextList();
|
||||
$this->data['activityList'] = SpuModel::activityTextList();
|
||||
$this->data['limitList'] = SpuModel::limitList();//限购天数展示
|
||||
|
||||
return $this->view();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取活动商品的订单列表
|
||||
*
|
||||
* @return Json
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getOrder(): Json
|
||||
{
|
||||
$id = input('id/d', 0);
|
||||
$page = input('page/d', 1);
|
||||
$size = input('size/d', 20);
|
||||
|
||||
$res = SpuRepository::getInstance()->getActivityOrderList($id, $page, $size);
|
||||
|
||||
return $this->json(0, '操作成功', $res);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
<?php
|
||||
// 事件定义文件
|
||||
return [
|
||||
'bind' => [
|
||||
],
|
||||
|
||||
'listen' => [
|
||||
'AppInit' => [],
|
||||
'HttpRun' => [],
|
||||
'HttpEnd' => [],
|
||||
'LogLevel' => [],
|
||||
'LogWrite' => [],
|
||||
],
|
||||
|
||||
'subscribe' => [
|
||||
'app\subscribe\Spu',
|
||||
'app\subscribe\Order',
|
||||
],
|
||||
];
|
|
@ -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,26 @@
|
|||
<?php
|
||||
|
||||
namespace app\middleware;
|
||||
|
||||
use Closure;
|
||||
use think\Request;
|
||||
|
||||
/**
|
||||
* 日志记录
|
||||
*
|
||||
* Class Log
|
||||
* @package app\middleware
|
||||
*/
|
||||
class Log
|
||||
{
|
||||
public function handle(Request $request, Closure $next)
|
||||
{
|
||||
$response = $next($request);
|
||||
|
||||
// 添加中间件执行代码
|
||||
\app\model\Log::write($request->controller(), $request->action(), $request->pathinfo(), $request->method());
|
||||
|
||||
return $response;
|
||||
|
||||
}
|
||||
}
|
|
@ -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,53 @@
|
|||
<?php
|
||||
|
||||
namespace app\model;
|
||||
|
||||
use think\model\relation\BelongsToMany;
|
||||
|
||||
class Account extends Base
|
||||
{
|
||||
public const STATUS_NORMAL = 'normal'; //正常
|
||||
public const STATUS_DISABLE = 'disable';//禁用
|
||||
public const GENDER_UNDEFINED = 0; // 未知
|
||||
public const GENDER_MALE = 1; // 男性
|
||||
public const GENDER_FEMALE = 2; // 女性
|
||||
|
||||
// 生成个人补充信息:邀请码、用户编号
|
||||
public static function onAfterInsert($item)
|
||||
{
|
||||
$item->invite_code = md5($item->id, false);
|
||||
$item->coding = date('y').str_pad((string) $item->id, 10, '0', STR_PAD_LEFT);
|
||||
$item->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* 时间修改器:生日
|
||||
*
|
||||
* @param $value
|
||||
* @return null|mixed
|
||||
*/
|
||||
public function setBirthdayAttr($value)
|
||||
{
|
||||
return empty($value) ? null : $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* 时间获取器:生日
|
||||
* @param $value
|
||||
* @return string
|
||||
*/
|
||||
public function getBirthdayAttr($value)
|
||||
{
|
||||
return empty($value) ? '' : $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* 客户标签
|
||||
*
|
||||
* @return BelongsToMany
|
||||
*/
|
||||
public function tags(): BelongsToMany
|
||||
{
|
||||
return $this->belongsToMany(AccountTag::class, 'account_tag_pivot', 'tag_id', 'account_id');
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
<?php
|
||||
|
||||
namespace app\model;
|
||||
|
||||
class AccountAddress extends Base
|
||||
{
|
||||
|
||||
}
|
|
@ -0,0 +1,124 @@
|
|||
<?php
|
||||
|
||||
namespace app\model;
|
||||
|
||||
use app\exception\RepositoryException;
|
||||
use think\db\exception\DataNotFoundException;
|
||||
use think\db\exception\DbException;
|
||||
use think\db\exception\ModelNotFoundException;
|
||||
use think\model\relation\HasOne;
|
||||
|
||||
class AccountCoupon extends Base
|
||||
{
|
||||
public const STATUS_NORMAL = 'normal';//正常
|
||||
public const STATUS_USED = 'used';//已使用
|
||||
public const STATUS_INVALID = 'invalid';//已失效
|
||||
|
||||
public const CODE_SALT = 'R5S6Y1';//优惠券加密密码盐
|
||||
|
||||
/**
|
||||
* 状态列表
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public static function statusList(): array
|
||||
{
|
||||
return [self::STATUS_NORMAL, self::STATUS_USED, self::STATUS_INVALID];
|
||||
}
|
||||
|
||||
public function coupon(): HasOne
|
||||
{
|
||||
return $this->hasOne(Coupon::class, 'id', 'coupon_id')->bind(
|
||||
[
|
||||
'amount',
|
||||
'name',
|
||||
'cover',
|
||||
'type',
|
||||
'condition',
|
||||
'begin_at',
|
||||
'end_at',
|
||||
]
|
||||
);
|
||||
}
|
||||
public function account(): HasOne
|
||||
{
|
||||
return $this->hasOne(Account::class, 'id', 'account_id')->bind(
|
||||
[
|
||||
'nickname',
|
||||
'mobile',
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 优惠券使用
|
||||
*
|
||||
* @param int $accountId
|
||||
* @param int $id
|
||||
* @param string $orderCoding
|
||||
* @param string $checkBy
|
||||
* @return bool
|
||||
* @throws DataNotFoundException
|
||||
* @throws DbException
|
||||
* @throws ModelNotFoundException
|
||||
* @throws RepositoryException
|
||||
*/
|
||||
public static function use(int $accountId, int $id, string $orderCoding = '',$checkBy =""): bool
|
||||
{
|
||||
$where = ['coupon_id' => $id, 'account_id' => $accountId, 'status' => AccountCoupon::STATUS_NORMAL];
|
||||
if (!$accountCoupon = self::findOne($where)) {
|
||||
throw new RepositoryException('您的优惠券不存在');
|
||||
}
|
||||
|
||||
if (!empty($accountCoupon['deleted_at'])) {
|
||||
throw new RepositoryException('您的优惠券不存在-2');
|
||||
}
|
||||
|
||||
if (!$coupon = Coupon::findById($id)) {
|
||||
throw new RepositoryException('此优惠券不存在或已下架');
|
||||
}
|
||||
|
||||
if (!empty($coupon['deleted_at'])) {
|
||||
throw new RepositoryException('此优惠券已下架');
|
||||
}
|
||||
|
||||
$now = date('Y-m-d H:i:s');
|
||||
if ($now < $coupon['begin_at'] || $now > $coupon['end_at']) {
|
||||
throw new RepositoryException('此优惠券不在有效期');
|
||||
}
|
||||
|
||||
if($accountCoupon["status"] != AccountCoupon::STATUS_NORMAL){
|
||||
throw new RepositoryException('优惠券已使用或已失效');
|
||||
}
|
||||
|
||||
return $accountCoupon->save([
|
||||
'used_at' => $now,
|
||||
'status' => self::STATUS_USED,
|
||||
'order_coding' => $orderCoding,
|
||||
'check_by' => $checkBy,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取首页优惠券
|
||||
* 没有或已领取则返回null
|
||||
*
|
||||
* @param int $accountId
|
||||
* @return Coupon|array|\think\Model|null
|
||||
* @throws DataNotFoundException
|
||||
* @throws DbException
|
||||
* @throws ModelNotFoundException
|
||||
*/
|
||||
public static function homeCoupon(int $accountId)
|
||||
{
|
||||
if (!$coupon = Coupon::homeCoupon()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (self::where('account_id', $accountId)->where('coupon_id', $coupon['id'])->count() > 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $coupon;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,99 @@
|
|||
<?php
|
||||
|
||||
namespace app\model;
|
||||
|
||||
use think\model\relation\HasOne;
|
||||
|
||||
/**
|
||||
* 积分与佣金日志
|
||||
*
|
||||
* Class AccountDataLog
|
||||
* @package app\model
|
||||
*/
|
||||
class AccountDataLog extends Base
|
||||
{
|
||||
public const TYPE_SCORE = 'score';//积分
|
||||
public const TYPE_COMMISSION = 'commission';//佣金
|
||||
|
||||
public const ACTION_ORDER = 'order';//订单返佣
|
||||
public const ACTION_ADMIN_RECHARGE = 'admin_recharge';//后台充值
|
||||
public const ACTION_ADMIN_OPERATION = 'admin_operation';//后台操作
|
||||
public const ACTION_WITHDRAWAL_RETURN = 'withdrawal_return';//提现-退回
|
||||
public const ACTION_WITHDRAWAL = 'withdrawal';//提现-扣除
|
||||
|
||||
// 积分独有
|
||||
public const ACTION_SHARE_REG = 'share_reg';//分享注册
|
||||
public const ACTION_SHARE_REG_CHILD = 'share_reg_child';//分享注册-下级分享时获得积分
|
||||
public const ACTION_SHARE_REG_SERVICE = 'share_reg_service';//分享注册-客户分享时客服获得积分
|
||||
|
||||
/**
|
||||
* 记录变更
|
||||
*
|
||||
* @param int $accountId
|
||||
* @param string $name 日志名称(说明) 如 签到打卡、任务完成等等
|
||||
* @param string $num 数量
|
||||
* @param string $type 类型 目前仅 TYPE_SCORE TYPE_COMMISSION
|
||||
* @param string $action 操作 如打卡=sign 任务=task 订单=order
|
||||
* @param string $surplus 剩余积分或佣金
|
||||
* @param string $operator 操作人
|
||||
* @param int $operatorId 操作人ID
|
||||
* @param string $remarks 备注
|
||||
*/
|
||||
public static function log(int $accountId, string $name, string $num, string $type, string $action, string $surplus, string $operator = '', int $operatorId = 0, string $remarks = '')
|
||||
{
|
||||
self::create([
|
||||
'account_id' => $accountId,
|
||||
'name' => $name,
|
||||
'num' => $num,
|
||||
'type' => $type,
|
||||
'action' => $action,
|
||||
'created_at' => date('Y-m-d H:i:s'),
|
||||
'surplus' => $surplus,
|
||||
'operator' => $operator,
|
||||
'operator_id' => $operatorId,
|
||||
'remarks' => $remarks,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户
|
||||
*
|
||||
*/
|
||||
public function account(): HasOne
|
||||
{
|
||||
return $this->hasOne(Account::class, 'id', 'account_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* 积分操作类型
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public static function scoreAction(): array
|
||||
{
|
||||
return [
|
||||
self::ACTION_ORDER => '订单',
|
||||
self::ACTION_ADMIN_RECHARGE => '后台充值',
|
||||
self::ACTION_ADMIN_OPERATION => '后台操作',
|
||||
self::ACTION_SHARE_REG => '分享注册',
|
||||
self::ACTION_SHARE_REG_CHILD => '分享注册-下级分享',
|
||||
self::ACTION_SHARE_REG_SERVICE => '分享注册-客服获得积分',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 佣金操作类型
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public static function commissionAction(): array
|
||||
{
|
||||
return [
|
||||
self::ACTION_ORDER => '订单返佣',
|
||||
self::ACTION_ADMIN_RECHARGE => '后台充值',
|
||||
self::ACTION_ADMIN_OPERATION => '后台操作',
|
||||
self::ACTION_WITHDRAWAL_RETURN => '提现退回',
|
||||
self::ACTION_WITHDRAWAL => '提现扣除',
|
||||
];
|
||||
}
|
||||
}
|
|
@ -0,0 +1,380 @@
|
|||
<?php
|
||||
|
||||
namespace app\model;
|
||||
|
||||
use Exception;
|
||||
use think\db\exception\DataNotFoundException;
|
||||
use think\db\exception\DbException;
|
||||
use think\db\exception\ModelNotFoundException;
|
||||
use think\facade\Db;
|
||||
use think\model\relation\HasOne;
|
||||
|
||||
class AccountRecord extends Base
|
||||
{
|
||||
public const TYPE_CONTENT = 'content';//内容
|
||||
public const TYPE_SPU = 'spu';//商品
|
||||
public const TYPE_OTHER = 'other';//其他
|
||||
|
||||
public const ACTION_COLLECT = 'collect';//收藏
|
||||
public const ACTION_LIKE = 'like';//点赞
|
||||
public const ACTION_SHARE = 'share';//分享
|
||||
public const ACTION_SEARCH = 'search';//搜索
|
||||
public const ACTION_VIEW = 'view';//查看
|
||||
public const ACTION_REGISTER = 'register';//注册
|
||||
public const ACTION_SHARE_VIEW = 'share_view';//分享内容被查看 记录的account_id为分享人ID
|
||||
|
||||
public const COLLECTED = 1;
|
||||
public const LIKED = 1;
|
||||
|
||||
/**
|
||||
* 允许的类型
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public static function allowTypes(): array
|
||||
{
|
||||
return [
|
||||
self::TYPE_CONTENT, self::TYPE_OTHER, self::TYPE_SPU
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 允许的操作
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public static function allowActions(): array
|
||||
{
|
||||
return [
|
||||
self::ACTION_COLLECT, self::ACTION_LIKE, self::ACTION_SHARE,
|
||||
self::ACTION_REGISTER, self::ACTION_VIEW, self::ACTION_SHARE_VIEW
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 内容表允许的操作
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public static function archivesActions(): array
|
||||
{
|
||||
return [
|
||||
self::ACTION_COLLECT, self::ACTION_LIKE, self::ACTION_SHARE,
|
||||
self::ACTION_VIEW
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 不可撤销的操作 即每次都新增记录 如 分享、咨询、注册
|
||||
* 注意:可撤销操作需要防止撤销后重新操作导致的无限制增加统计 即刷数据 如收藏、点赞等
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public static function notUndoActions(): array
|
||||
{
|
||||
return [self::ACTION_SHARE, self::ACTION_REGISTER, self::ACTION_VIEW];
|
||||
}
|
||||
|
||||
/**
|
||||
* 操作对应字段
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public static function actionField(): array
|
||||
{
|
||||
return [
|
||||
self::ACTION_REGISTER => 'customer',
|
||||
self::ACTION_COLLECT => 'collects',
|
||||
self::ACTION_LIKE => 'likes',
|
||||
self::ACTION_VIEW => 'views',
|
||||
self::ACTION_SHARE => 'shares',
|
||||
self::ACTION_SHARE_VIEW => 'views',//分享内容被查看 也增加views
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 概览操作对应字段
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public static function overviewField(): array
|
||||
{
|
||||
return [
|
||||
self::ACTION_REGISTER => 'customer',
|
||||
self::ACTION_VIEW => 'views',
|
||||
self::ACTION_SHARE => 'shares',
|
||||
self::ACTION_SHARE_VIEW => 'views',//分享内容被查看 也增加views
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 模型关联:内容文档
|
||||
*/
|
||||
public function archive(): HasOne
|
||||
{
|
||||
return $this->hasOne(Archives::class, 'id', 'relation_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* 模型关联:商品
|
||||
*/
|
||||
public function spu(): HasOne
|
||||
{
|
||||
return $this->hasOne(Spu::class, 'id', 'relation_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* 记录 收藏、点赞、分享、搜索、咨询、查询
|
||||
*
|
||||
* @param int $accountId
|
||||
* @param int $relationId
|
||||
* @param string $type
|
||||
* @param string $action
|
||||
* @return bool
|
||||
* @throws ModelNotFoundException
|
||||
*/
|
||||
public static function record(int $accountId, string $type = self::TYPE_CONTENT, string $action = self::ACTION_COLLECT, int $relationId = 0): bool
|
||||
{
|
||||
Db::startTrans();
|
||||
try {
|
||||
$now = date('Y-m-d H:i:s');
|
||||
$hadRecord = false;//是否已经记录 防重复点赞和收藏 无限计数 已记录数据不添加相应统计
|
||||
$notUndoAction = self::notUndoActions();
|
||||
if (in_array($action, $notUndoAction)) {
|
||||
$item = null;
|
||||
} else {
|
||||
$item = self::where('account_id', $accountId)
|
||||
->where('relation_id', $relationId)
|
||||
->where('type', $type)
|
||||
->where('action', $action)
|
||||
->find();
|
||||
}
|
||||
|
||||
if (!$item) {
|
||||
self::create([
|
||||
'account_id' => $accountId,
|
||||
'relation_id' => $relationId,
|
||||
'type' => $type,
|
||||
'action' => $action,
|
||||
'created_at' => $now,
|
||||
'is_record' => self::BOOL_TRUE,
|
||||
'recorded_at' => $now,
|
||||
]);
|
||||
} else {
|
||||
if ($item['is_record'] == self::BOOL_TRUE) {
|
||||
$hadRecord = true;
|
||||
}
|
||||
|
||||
$item['is_record'] = self::BOOL_TRUE;
|
||||
$item['recorded_at'] = $now;
|
||||
$item['type'] = $type;
|
||||
$item->save();
|
||||
}
|
||||
|
||||
// 更新内容表
|
||||
if ($type == self::TYPE_CONTENT && in_array($action, self::archivesActions())) {
|
||||
if (in_array($action, $notUndoAction) || !$hadRecord) {
|
||||
//不需撤销的 和 新增加的操作才计入统计
|
||||
$archive = Archives::findById($relationId);
|
||||
$field = self::actionField()[$action] ?? null;
|
||||
if (!$field) {
|
||||
throw new Exception('操作错误');
|
||||
}
|
||||
if ($archive) {
|
||||
$archive->inc($field)->update();
|
||||
}
|
||||
}
|
||||
}
|
||||
// 更新概览数据表
|
||||
Overview::renew($accountId, $action);
|
||||
|
||||
Db::commit();
|
||||
} catch (ModelNotFoundException | Exception $e) {
|
||||
Db::rollback();
|
||||
throw $e;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消收藏|点赞
|
||||
*
|
||||
* @param int $accountId
|
||||
* @param int $relationId
|
||||
* @param string $type
|
||||
* @param string $action
|
||||
* @return bool
|
||||
*/
|
||||
public static function unRecord(int $accountId, int $relationId, string $type, string $action): bool
|
||||
{
|
||||
Db::startTrans();
|
||||
try {
|
||||
$item = self::where('account_id', $accountId)
|
||||
->where('relation_id', $relationId)
|
||||
->where('type', $type)
|
||||
->where('action', $action)
|
||||
->find();
|
||||
|
||||
if ($item) {
|
||||
$hadUnRecord = $item['is_record'] == self::BOOL_FALSE;
|
||||
|
||||
$item->is_record = self::BOOL_FALSE;
|
||||
$item->recorded_at = null;
|
||||
$item->save();
|
||||
|
||||
if ($type == self::TYPE_CONTENT && !$hadUnRecord) {
|
||||
$archive = Archives::findById($relationId);
|
||||
$archiveUpdate = [];
|
||||
if ($archive) {
|
||||
switch ($action) {
|
||||
case AccountRecord::ACTION_COLLECT:
|
||||
$newCollects = $archive['collects'] - 1;
|
||||
$newCollects = $newCollects < 0 ? 0 : $newCollects;
|
||||
$archiveUpdate['collects'] = $newCollects;
|
||||
break;
|
||||
case AccountRecord::ACTION_LIKE:
|
||||
$newLikes = $archive['likes'] - 1;
|
||||
$newLikes = $newLikes < 0 ? 0 : $newLikes;
|
||||
$archiveUpdate['likes'] = $newLikes;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ($archive && count($archiveUpdate)) {
|
||||
Archives::updateById($relationId, $archiveUpdate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Db::commit();
|
||||
} catch (Exception $e) {
|
||||
Db::rollback();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取已完成的操作
|
||||
*
|
||||
* @param int $accountId
|
||||
* @param int $relationId
|
||||
* @param string $type
|
||||
* @return array
|
||||
*/
|
||||
public static function getDoneAction(int $accountId, int $relationId, string $type = self::TYPE_CONTENT): array
|
||||
{
|
||||
if ($accountId <= 0) {
|
||||
return [];
|
||||
}
|
||||
return self::where('is_record', self::COMMON_ON)
|
||||
->where('account_id', $accountId)
|
||||
->where('relation_id', $relationId)
|
||||
->where('type', $type)
|
||||
->column('action');
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取搜索记录
|
||||
*
|
||||
* @param int $accountId
|
||||
* @param int $page
|
||||
* @param int $size
|
||||
* @return array|null
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function findSearch(int $accountId, int $page = 1, int $size = 20): ?array
|
||||
{
|
||||
if ($accountId <= 0) {
|
||||
return [
|
||||
'total' => 0,
|
||||
'current' => $page,
|
||||
'size' => $size,
|
||||
'list' => [],
|
||||
];
|
||||
}
|
||||
$where[] = ['account_id', '=', $accountId];
|
||||
$where[] = ['is_record', '=', self::COMMON_ON];
|
||||
return self::findList($where, ['id', 'relation_content keyword'], $page, $size, null, ['recorded_at' => 'desc']);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取搜索记录
|
||||
*
|
||||
* @param int $accountId
|
||||
* @param string $keyword
|
||||
* @return bool
|
||||
* @throws DataNotFoundException
|
||||
* @throws DbException
|
||||
* @throws ModelNotFoundException
|
||||
*/
|
||||
public static function saveSearch(int $accountId, string $keyword): bool
|
||||
{
|
||||
$item = AccountRecord::where('account_id', $accountId)->where('type', self::TYPE_CONTENT)
|
||||
->where('action', self::ACTION_SEARCH)
|
||||
->where('relation_content', trim($keyword))
|
||||
->find();
|
||||
$now = date('Y-m-d H:i:s');
|
||||
if (!$item) {
|
||||
AccountRecord::create([
|
||||
'type' => self::TYPE_CONTENT,
|
||||
'action' => self::ACTION_SEARCH,
|
||||
'relation_content' => trim($keyword),
|
||||
'account_id' => $accountId,
|
||||
'is_record' => self::COMMON_ON,
|
||||
'recorded_at' => $now,
|
||||
'created_at' => $now,
|
||||
]);
|
||||
} else {
|
||||
$item->save([
|
||||
'is_record' => self::COMMON_ON,
|
||||
'recorded_at' => $now
|
||||
]);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 清空搜索记录
|
||||
*
|
||||
* @param int $accountId
|
||||
* @return bool
|
||||
*/
|
||||
public static function clearSearch(int $accountId): bool
|
||||
{
|
||||
if ($accountId <= 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$where = ['account_id' => $accountId, 'type' => self::TYPE_CONTENT, 'action' => self::ACTION_SEARCH];
|
||||
AccountRecord::update(['is_record' => self::COMMON_OFF], $where);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 记录统计
|
||||
*
|
||||
* @param string $type
|
||||
* @param string $action
|
||||
* @param int $accountId
|
||||
* @return int
|
||||
*/
|
||||
public static function countByAction(string $type, string $action, int $accountId = 0): int
|
||||
{
|
||||
$whereMap = ['ar.type' => $type, 'ar.action' => $action, 'ar.is_record' => self::BOOL_TRUE];
|
||||
if ($accountId > 0) {
|
||||
$whereMap['ar.account_id'] = $accountId;
|
||||
}
|
||||
try {
|
||||
return self::alias('ar')->where($whereMap)->when($type == self::TYPE_CONTENT, function ($q) {
|
||||
$q->leftJoin('archives arc', 'arc.id=ar.relation_id')->where('arc.id', '>', 0);
|
||||
})->count();
|
||||
} catch (Exception $e) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
<?php
|
||||
namespace app\model;
|
||||
|
||||
class AccountTag extends Base
|
||||
{
|
||||
public static function getTags()
|
||||
{
|
||||
return AccountTag::order('sort', 'desc')->order('id', 'asc')->select();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
<?php
|
||||
namespace app\model;
|
||||
|
||||
class AccountTagPivot extends Base
|
||||
{
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
<?php
|
||||
|
||||
namespace app\model;
|
||||
|
||||
use app\exception\RepositoryException;
|
||||
use app\service\Math;
|
||||
|
||||
/**
|
||||
* 用户佣金提现记录
|
||||
*
|
||||
* Class AccountWithdrawalCommission
|
||||
* @package app\controller\manager
|
||||
*/
|
||||
class AccountWithdrawalCommission extends Base
|
||||
{
|
||||
|
||||
static $status_default = 0;//待审核
|
||||
static $status_success = 1;//审核通过
|
||||
static $status_fail = 2;//审核失败
|
||||
|
||||
|
||||
/**
|
||||
* 客户
|
||||
*/
|
||||
public function account()
|
||||
{
|
||||
return $this->hasOne(Account::class, 'id', 'account_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换佣金和金额
|
||||
* @param $num int 金额或者佣金 单位为分
|
||||
* @param $type string commission/money 需要获得的金额或者佣金 单位分
|
||||
*
|
||||
* @throws RepositoryException
|
||||
*/
|
||||
public static function convertCommissionOrMoney(int $num, string $type)
|
||||
{
|
||||
\think\facade\Config::load('extra/commission_withdrawal', 'commission_withdrawal');
|
||||
$config = config('commission_withdrawal')['withdrawal_proportion'] ?? [];
|
||||
|
||||
if (!$config) {
|
||||
throw new RepositoryException("提现比例未配置,请先联系平台");
|
||||
}
|
||||
|
||||
if ($config["commission"] <= 0 || $config["money"] <= 0) {
|
||||
throw new RepositoryException("提现失败,系统错误");
|
||||
}
|
||||
|
||||
//如果想得到佣金 或者 金额 单位分
|
||||
if ($type == AccountDataLog::TYPE_COMMISSION) {
|
||||
$total = Math::fen2Yuan($num) * ($config["commission"]) / ($config["money"]);
|
||||
} else {
|
||||
$total = $num * ($config["money"]) / ($config["commission"]);
|
||||
}
|
||||
|
||||
return ceil($total);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
<?php
|
||||
|
||||
namespace app\model;
|
||||
|
||||
use think\db\exception\DataNotFoundException;
|
||||
use think\db\exception\DbException;
|
||||
use think\db\exception\ModelNotFoundException;
|
||||
use think\model\relation\HasMany;
|
||||
use think\model\relation\HasOne;
|
||||
|
||||
class Archives extends Base
|
||||
{
|
||||
public const ORIGINAL_TABLE = 'bee_archives';
|
||||
|
||||
public const STATUS_NORMAL = 1;//正常
|
||||
public const STATUS_DISABLE = 0;//禁用
|
||||
|
||||
/**
|
||||
* 相关记录 点赞|收藏
|
||||
*
|
||||
* @return HasMany
|
||||
*/
|
||||
public function record(): HasMany
|
||||
{
|
||||
return $this->hasMany(AccountRecord::class, 'relation_id', 'id');
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否收藏
|
||||
*
|
||||
* @return HasOne
|
||||
*/
|
||||
public function collect(): HasOne
|
||||
{
|
||||
return $this->hasOne(AccountRecord::class, 'relation_id', 'id')->bind(['is_collected' => 'is_record']);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建人信息
|
||||
*
|
||||
* @return HasOne
|
||||
*/
|
||||
public function member(): HasOne
|
||||
{
|
||||
return $this->hasOne(Member::class, 'id', 'created_by')->bind(['nickname']);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 分类
|
||||
*
|
||||
* @return HasOne
|
||||
*/
|
||||
public function category(): HasOne
|
||||
{
|
||||
return $this->hasOne(ArchivesCategory::class, 'id', 'category_id')->bind(['category_title' => 'title']);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
<?php
|
||||
|
||||
namespace app\model;
|
||||
|
||||
use think\Collection;
|
||||
use think\db\exception\DbException;
|
||||
use think\db\exception\DataNotFoundException;
|
||||
use think\db\exception\ModelNotFoundException;
|
||||
use think\model\relation\HasOne;
|
||||
|
||||
class ArchivesCategory extends Base
|
||||
{
|
||||
public const TOP_PID = 0;
|
||||
|
||||
public const NAME_DIARY = 'diary'; //日记分享
|
||||
|
||||
/**
|
||||
* 获取恒美 关于我们栏目列表
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public static function aboutCategoryId(): array
|
||||
{
|
||||
$aboutId = self::where('name', 'about')->value('id');
|
||||
return self::where('pid', $aboutId)->column('id');
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取病种相关模型的栏目 模型名称为:'question', 'diary', 'effect', 'science'
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public static function diseaseCategoryIds(): array
|
||||
{
|
||||
$modelIds = ArchivesModel::whereIn('name', ArchivesModel::models())->column('id');
|
||||
return self::whereIn('model_id', $modelIds)->column('id');
|
||||
}
|
||||
|
||||
/**
|
||||
* 检测数据下 是否有子栏目
|
||||
*
|
||||
* @param array $ids
|
||||
* @return bool
|
||||
*/
|
||||
public static function hasChildrenByIds(array $ids): bool
|
||||
{
|
||||
return self::whereIn('pid', $ids)->count() > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检测数据下 是否有子内容
|
||||
*
|
||||
* @param array $ids
|
||||
* @return bool
|
||||
*/
|
||||
public static function hasContentByIds(array $ids): bool
|
||||
{
|
||||
return Archives::whereIn('category_id', $ids)->count() > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取列表
|
||||
*
|
||||
* @return ArchivesCategory[]|array|Collection
|
||||
* @throws DataNotFoundException
|
||||
* @throws DbException
|
||||
* @throws ModelNotFoundException
|
||||
*/
|
||||
public static function getList()
|
||||
{
|
||||
return self::field('id,pid,title,name,sort,path,true as open')
|
||||
->order('sort', 'desc')
|
||||
->order('id', 'asc')
|
||||
->select();
|
||||
}
|
||||
|
||||
/**
|
||||
* 模型
|
||||
*
|
||||
* @return HasOne
|
||||
*/
|
||||
public function model(): HasOne
|
||||
{
|
||||
return $this->hasOne(ArchivesModel::class, 'id', 'model_id')->bind(['model' => 'name']);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
<?php
|
||||
|
||||
namespace app\model;
|
||||
|
||||
/**
|
||||
* 文档模型
|
||||
* Class ArchivesModel
|
||||
* @package app\model
|
||||
*/
|
||||
class ArchivesModel extends Base
|
||||
{
|
||||
/**
|
||||
* 获取恒美内容模型 问题文章|日记分享|效果模拟|科普视频
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public static function models(): array
|
||||
{
|
||||
return ['question', 'diary', 'effect', 'science'];
|
||||
}
|
||||
|
||||
/**
|
||||
* 内容模型关联栏目
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public static function categories()
|
||||
{
|
||||
return self::alias('am')
|
||||
->leftJoin('archives_category ac', 'ac.model_id = am.id')
|
||||
->field('ac.id,ac.title,ac.model_id, ac.sort,am.name as model_name')
|
||||
->order('ac.sort', 'desc')
|
||||
->order('ac.id', 'asc')
|
||||
->whereIn('am.name', self::models())
|
||||
->select();
|
||||
}
|
||||
|
||||
/**
|
||||
* 关于我们栏目
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public static function about()
|
||||
{
|
||||
return self::alias('am')
|
||||
->leftJoin('archives_category ac', 'ac.model_id = am.id')
|
||||
->field('ac.id,ac.title,ac.model_id, ac.sort,am.name as model_name')
|
||||
->order('ac.sort', 'desc')
|
||||
->order('ac.id', 'asc')
|
||||
->whereIn('ac.id', ArchivesCategory::aboutCategoryId())
|
||||
->select();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,118 @@
|
|||
<?php
|
||||
|
||||
namespace app\model;
|
||||
|
||||
use Exception;
|
||||
use think\db\exception\DataNotFoundException;
|
||||
use think\db\exception\DbException;
|
||||
use think\db\exception\ModelNotFoundException;
|
||||
use think\facade\Db;
|
||||
|
||||
/**
|
||||
* 文档模型字段
|
||||
* Class ArchivesModelField
|
||||
* @package app\model
|
||||
*/
|
||||
class ArchivesModelField extends Base
|
||||
{
|
||||
public const VIRTUAL_YES = 1;//虚拟字段 是
|
||||
public const VIRTUAL_NO = 0;//虚拟字段 否
|
||||
|
||||
/**
|
||||
* 模型添加字段列表
|
||||
*
|
||||
* @param int $modelId
|
||||
* @param string $modelName
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function setFieldList(int $modelId, string $modelName)
|
||||
{
|
||||
if (self::where('model_id', $modelId)->count() <= 0) {
|
||||
$rs = Db::query("SHOW FULL COLUMNS FROM ".Archives::ORIGINAL_TABLE);
|
||||
$insert = [];
|
||||
foreach ($rs as $val) {
|
||||
$arr = [];
|
||||
$arr['model_id'] = $modelId;
|
||||
$arr['model'] = $modelName;
|
||||
$arr['name'] = $val['Field'];
|
||||
$arr['title'] = $val['Comment'];
|
||||
$arr['remark'] = $val['Comment'];
|
||||
$insert[] = $arr;
|
||||
}
|
||||
|
||||
(new self())->saveAll($insert);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 同步字段
|
||||
*
|
||||
* @param int $modelId
|
||||
* @param string $modelName
|
||||
* @throws DataNotFoundException
|
||||
* @throws DbException
|
||||
* @throws ModelNotFoundException
|
||||
*/
|
||||
public static function syncFieldList(int $modelId, string $modelName)
|
||||
{
|
||||
$rs = Db::query("SHOW FULL COLUMNS FROM ".Archives::ORIGINAL_TABLE);
|
||||
$oldFieldList = self::where('model_id', $modelId)->where('is_virtual', self::VIRTUAL_NO)->select();
|
||||
$oldFields = $oldFieldList->column('name');
|
||||
|
||||
|
||||
$newestFields = [];
|
||||
foreach ($rs as $val) {
|
||||
$newestFields[] = $val['Field'];
|
||||
}
|
||||
|
||||
//待删除字段
|
||||
$delete = array_diff($oldFields, $newestFields);
|
||||
|
||||
//待新增字段
|
||||
$needInsertFields = array_diff($newestFields, $oldFields);
|
||||
|
||||
$insert = [];//新增字段
|
||||
foreach ($rs as $val) {
|
||||
if (in_array($val['Field'], $needInsertFields)) {
|
||||
$arr = [];
|
||||
$arr['model_id'] = $modelId;
|
||||
$arr['model'] = $modelName;
|
||||
$arr['name'] = $val['Field'];
|
||||
$arr['title'] = $val['Comment'];
|
||||
$arr['remark'] = $val['Comment'];
|
||||
$insert[] = $arr;
|
||||
}
|
||||
}
|
||||
|
||||
(new self())->saveAll($insert);
|
||||
(new self())->whereIn('name', $delete)->delete();
|
||||
}
|
||||
|
||||
/**
|
||||
* 各栏目[模型] 可展示字段列表
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function showFieldList(): array
|
||||
{
|
||||
$list = self::alias('amf')
|
||||
->leftJoin('archives_category ac', 'ac.model_id = amf.model_id')
|
||||
->field('amf.*, ac.id as category_id, ac.title as category_title')
|
||||
->where('amf.status', self::COMMON_ON)
|
||||
->where('ac.id', '>', 0)
|
||||
->select();
|
||||
|
||||
$res = [];
|
||||
|
||||
$list = $list->toArray();
|
||||
foreach ($list as $item) {
|
||||
if (!isset($res[$item['category_id']])) {
|
||||
$res[$item['category_id']] = [];
|
||||
}
|
||||
|
||||
$res[$item['category_id']][] = $item['name'];
|
||||
}
|
||||
|
||||
return $res;
|
||||
}
|
||||
}
|
|
@ -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,390 @@
|
|||
<?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 ($page) {
|
||||
$q = $q->page($page);
|
||||
}
|
||||
if ($limit == 0) {
|
||||
$q = $q->limit(1000);
|
||||
} else {
|
||||
$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,23 @@
|
|||
<?php
|
||||
|
||||
namespace app\model;
|
||||
|
||||
/**
|
||||
* 配置表
|
||||
* Class Config
|
||||
* @package app\model
|
||||
*/
|
||||
class Config extends Base
|
||||
{
|
||||
// 路径都没有加前缀/ 需要的地方自行添加
|
||||
// 小程序内容详情路径----新闻内容详情 包含: 关于我们模型、普通文章模型
|
||||
public const MINI_PATH_ARCHIVES = 'pagesB/articleDetail/articleDetail';
|
||||
// 小程序病种详情路径----病种内容详情(前端叫法) 包含: 非我们模型、普通文章模型的其他模型 如问题文章、科普视频等
|
||||
public const MINI_PATH_PROBLEM = 'pagesB/problemDetail/problemDetail';
|
||||
// 小程序预约列表界面
|
||||
public const MINI_PATH_APPOINTMENT = 'pagesA/makeAnPppointment/makeAnPppointment';
|
||||
// 小程序消息中心
|
||||
public const MINI_PATH_MESSAGE_CENTER = 'pagesB/messagecenter/messagecenter';
|
||||
// 商品详情
|
||||
public const MINI_PATH_SPU_INFO = 'pagesB/shopDetail/shopDetail';
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
|
||||
namespace app\model;
|
||||
|
||||
/**
|
||||
* 配置分组表
|
||||
* Class ConfigGroup
|
||||
* @package app\model
|
||||
*/
|
||||
class ConfigGroup extends Base
|
||||
{
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
<?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
|
||||
{
|
||||
public const TYPE_DISCOUNT = 'discount';//满减
|
||||
public const TYPE_TASTE = 'taste';//体验
|
||||
|
||||
/**
|
||||
* 类型文案
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public static function typeTextList(): array
|
||||
{
|
||||
return [
|
||||
self::TYPE_DISCOUNT => '满减券',
|
||||
self::TYPE_TASTE => '体验券',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 可领取列表
|
||||
*
|
||||
* @param array $without 需要排除的ID列表
|
||||
* @return Coupon[]|array|Collection
|
||||
* @throws DataNotFoundException
|
||||
* @throws DbException
|
||||
* @throws ModelNotFoundException
|
||||
*/
|
||||
public static function normalList(array $without = [])
|
||||
{
|
||||
$now = date('Y-m-d H:i:s');
|
||||
return self::whereNotIn('id', $without)
|
||||
->whereNull('deleted_at')
|
||||
->where('begin_at', '<', $now)
|
||||
->where('end_at', '>', $now)
|
||||
->where('remain', '>', 0)
|
||||
->order('sort', 'desc')
|
||||
->order('created_at', 'desc')
|
||||
->select();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取首页推荐优惠券
|
||||
*
|
||||
* @return Coupon|array|\think\Model|null
|
||||
* @throws DataNotFoundException
|
||||
* @throws DbException
|
||||
* @throws ModelNotFoundException
|
||||
*/
|
||||
public static function homeCoupon()
|
||||
{
|
||||
$now = date('Y-m-d H:i:s');
|
||||
return self::where('is_home', self::COMMON_ON)
|
||||
->whereNull('deleted_at')
|
||||
->where('begin_at', '<', $now)
|
||||
->where('end_at', '>', $now)
|
||||
->where('remain', '>', 0)
|
||||
->order('sort', 'desc')
|
||||
->order('created_at', 'desc')
|
||||
->find();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
<?php
|
||||
namespace app\model;
|
||||
|
||||
class Express extends Base
|
||||
{
|
||||
public static function getDefaultFreight(string $code)
|
||||
{
|
||||
return self::where('code', $code)->value('default_price', 0);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
<?php
|
||||
namespace app\model;
|
||||
|
||||
use think\model\relation\HasOne;
|
||||
|
||||
/**
|
||||
* 投诉与意见记录
|
||||
* Class Feedback
|
||||
* @package app\model
|
||||
*/
|
||||
class Feedback extends Base
|
||||
{
|
||||
public const STATUS_WAITING = 0; // 待处理
|
||||
public const STATUS_DONE = 1; // 已处理
|
||||
|
||||
|
||||
/**
|
||||
* 模型关联:意见分类
|
||||
*
|
||||
* @return HasOne
|
||||
*/
|
||||
public function type(): HasOne
|
||||
{
|
||||
return $this->hasOne(FeedbackType::class, 'id', 'type_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* 模型关联:用户
|
||||
*
|
||||
* @return HasOne
|
||||
*/
|
||||
public function account(): HasOne
|
||||
{
|
||||
return $this->hasOne(Account::class, 'id', 'account_id');
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
namespace app\model;
|
||||
|
||||
/**
|
||||
* 投诉与意见分类
|
||||
* Class FeedbackType
|
||||
* @package app\model
|
||||
*/
|
||||
class FeedbackType 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'] == 'true') {
|
||||
$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,41 @@
|
|||
<?php
|
||||
|
||||
namespace app\model;
|
||||
|
||||
use think\model\relation\HasOne;
|
||||
|
||||
class Log extends Base
|
||||
{
|
||||
//记录操作日志
|
||||
public static function write($controller, $action, $content, $requestType = '')
|
||||
{
|
||||
$auth = session('auth');
|
||||
return self::create([
|
||||
'member_id' => $auth['user_id'] ?? 0,
|
||||
'name' => $auth['username'] ?? 0,
|
||||
'ip' => request()->ip(),
|
||||
'create_time' => time(),
|
||||
'controller' => $controller,
|
||||
'request_type' => $requestType,
|
||||
'action' => $action,
|
||||
'content' => $content
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HasOne
|
||||
*/
|
||||
public function memberName(): HasOne
|
||||
{
|
||||
return $this->hasOne(Member::class, 'id', 'member_id')->bind(['operator' => 'nickname']);
|
||||
}
|
||||
|
||||
public function getCreateTimeAttr($value)
|
||||
{
|
||||
if (empty($value)) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
return date('Y-m-d H:i:s', $value);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
<?php
|
||||
namespace app\model;
|
||||
|
||||
class LoginLog extends Base
|
||||
{
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
<?php
|
||||
|
||||
namespace app\model;
|
||||
|
||||
class Member extends Base
|
||||
{
|
||||
public const STATUS_NORMAL = 1;//正常
|
||||
public const STATUS_DISABLE = 0;//禁用
|
||||
|
||||
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 getByUserName($username)
|
||||
{
|
||||
return self::where('username', trim($username))
|
||||
->findOrEmpty()
|
||||
->toArray();
|
||||
}
|
||||
}
|
|
@ -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,51 @@
|
|||
<?php
|
||||
|
||||
namespace app\model;
|
||||
|
||||
class Message extends Base
|
||||
{
|
||||
// 消息类型
|
||||
public const TYPE_SYSTEM = 'system'; // 系统消息
|
||||
public const TYPE_NOTICE = 'notice'; // 通知消息
|
||||
public const TYPE_REMINDERS = 'reminders'; // 日程提醒
|
||||
|
||||
// 发送范围
|
||||
public const TARGET_ALL = 'all'; // 所有用户
|
||||
public const TARGET_PART = 'part'; // 部分用户,与target_list组合查询
|
||||
|
||||
|
||||
/**
|
||||
* 消息类型文本描述
|
||||
* @return string[]
|
||||
*/
|
||||
public static function typeTextList(): array
|
||||
{
|
||||
return [
|
||||
self::TYPE_SYSTEM => '系统消息',
|
||||
self::TYPE_NOTICE => '通知消息',
|
||||
self::TYPE_REMINDERS => '日程提醒',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 消息类型文本描述
|
||||
* @return string[]
|
||||
*/
|
||||
public static function targetTextList(): array
|
||||
{
|
||||
return [
|
||||
self::TARGET_ALL => '所有用户',
|
||||
self::TARGET_PART => '部分用户',
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取列表
|
||||
*/
|
||||
public static function getList($per = 20)
|
||||
{
|
||||
return self::order("create_time desc")
|
||||
->paginate($per);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
namespace app\model;
|
||||
|
||||
/**
|
||||
* 消息阅读记录
|
||||
* Class MessageLog
|
||||
* @package app\model
|
||||
*/
|
||||
class MessageLog extends Base
|
||||
{
|
||||
|
||||
}
|
|
@ -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,69 @@
|
|||
<?php
|
||||
|
||||
namespace app\model;
|
||||
|
||||
use think\model\relation\HasMany;
|
||||
use think\model\relation\HasOne;
|
||||
|
||||
class Order extends Base
|
||||
{
|
||||
public const STATUS_ORDER_PLACED = 'order_placed';//已下单 (已付款待发货)
|
||||
public const STATUS_MAKEING = 'makeing';//制作中
|
||||
public const STATUS_SHIPPED = 'shipped';//已发货
|
||||
public const STATUS_ARRIVED = 'arrived';//已送达
|
||||
public const STATUS_COMPLETED = 'completed';//已完成 确认收获 或者 到期自动确认
|
||||
public const STATUS_CANCEL = 'cancel';//已取消
|
||||
|
||||
public const CHECK_TYPE_FRONTEND = 'frontend';//核验类型 前端核验|线下核验
|
||||
public const CHECK_TYPE_BACKEND = 'backend';//核验类型 后台核验|线上核验
|
||||
|
||||
public const PAY_TYPE_WECHAT = 'wechat';//微信
|
||||
public const PAY_TYPE_SCORE = 'score';//积分
|
||||
|
||||
/**
|
||||
* 核验方式列表
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public static function checkTypeList(): array
|
||||
{
|
||||
return [self::CHECK_TYPE_FRONTEND, self::CHECK_TYPE_BACKEND];
|
||||
}
|
||||
|
||||
/**
|
||||
* 模型关联:订单下的sku
|
||||
* 一对多关系
|
||||
*
|
||||
* @return HasMany
|
||||
*/
|
||||
public function skus(): HasMany
|
||||
{
|
||||
return $this->hasMany(OrderSku::class, 'order_coding', 'coding')->whereNull('deleted_at');
|
||||
}
|
||||
|
||||
/**
|
||||
* 模型关联:下单会员
|
||||
* @return HasOne
|
||||
*/
|
||||
public function account(): HasOne
|
||||
{
|
||||
return $this->hasOne(Account::class, 'id', 'account_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* 订单状态描述
|
||||
*/
|
||||
public static function statusTextList(): array
|
||||
{
|
||||
return [
|
||||
self::STATUS_ORDER_PLACED => '已下单',
|
||||
self::STATUS_MAKEING => '制作中',
|
||||
self::STATUS_SHIPPED => '已发货',
|
||||
self::STATUS_ARRIVED => '已送达',
|
||||
self::STATUS_COMPLETED => '已完成',
|
||||
self::STATUS_CANCEL => '已取消',
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue