chore: 添加静态资源文件和版本配置文件
添加大量图片、字体、音频等静态资源文件,包括用户界面图片、模板文件和安装界面素材 添加系统版本配置文件(.version)和常量定义文件(.constant) 更新供应商依赖文件,包括Symfony VarDumper组件和相关许可证文件 添加验证码配置文件(captcha.php)和.gitignore规则
This commit is contained in:
508
app/services/system/AiServices.php
Normal file
508
app/services/system/AiServices.php
Normal file
@@ -0,0 +1,508 @@
|
||||
<?php
|
||||
|
||||
namespace app\services\system;
|
||||
|
||||
use app\services\BaseServices;
|
||||
use app\services\product\product\StoreProductServices;
|
||||
use app\services\product\sku\StoreProductAttrValueServices;
|
||||
use app\services\serve\ServeServices;
|
||||
|
||||
class AiServices extends BaseServices
|
||||
{
|
||||
/**
|
||||
* @var ServeServices
|
||||
*/
|
||||
protected ServeServices $services;
|
||||
|
||||
/**
|
||||
* 构造方法
|
||||
* @param ServeServices $serveServices 服务实例
|
||||
*/
|
||||
public function __construct(ServeServices $serveServices)
|
||||
{
|
||||
$this->services = $serveServices;
|
||||
}
|
||||
|
||||
/**
|
||||
* AI类型分发处理
|
||||
* @param array $data 请求数据
|
||||
* @return array|string
|
||||
*/
|
||||
public function AiType($data)
|
||||
{
|
||||
switch ($data['type']) {
|
||||
case 'product_name':
|
||||
$result = $this->productName($data);
|
||||
break;
|
||||
case 'product_info':
|
||||
$result = $this->productInfo($data);
|
||||
break;
|
||||
case 'share_content':
|
||||
$result = $this->shareContent($data);
|
||||
break;
|
||||
case 'product_attr':
|
||||
$result = $this->productAttr($data);
|
||||
break;
|
||||
case 'product_specs':
|
||||
$result = $this->productSpecs($data);
|
||||
break;
|
||||
case 'product_reply':
|
||||
$result = $this->productReply($data);
|
||||
break;
|
||||
case 'community':
|
||||
$result = $this->community($data);
|
||||
break;
|
||||
case 'community_title':
|
||||
$result = $this->communityTitle($data);
|
||||
break;
|
||||
case 'community_content':
|
||||
$result = $this->communityContent($data);
|
||||
break;
|
||||
case 'article_title':
|
||||
$result = $this->articleTitle($data);
|
||||
break;
|
||||
case 'article_content':
|
||||
$result = $this->articleContent($data);
|
||||
break;
|
||||
default:
|
||||
return '暂不支持该类型';
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* AI生成商品名称
|
||||
* @param array $data 请求数据
|
||||
* @return array
|
||||
*/
|
||||
public function productName($data)
|
||||
{
|
||||
$systemContent = '
|
||||
请严格按此规范执行:
|
||||
1. 核心指令:
|
||||
• 生成3条差异化标题,每条30-50字,符合电商平台SEO规则
|
||||
• 必须包含:核心关键词(前10字)+核心卖点(材质/功能)+附加价值(促销/场景/人群)
|
||||
• 禁止:重复词、违禁词、模糊描述(如“优质”“多功能”)
|
||||
2. 优化维度:
|
||||
▶ 标题1(流量型):关键词堆砌+高频搜索词,例:
|
||||
“2024新款男士运动鞋透气防滑跑步鞋轻便百搭男鞋网面休闲鞋耐磨减震”
|
||||
▶ 标题2(转化型):强促销+紧迫感,例:
|
||||
“【限时5折】男士运动鞋春秋季飞织透气跑步鞋学生潮流男鞋次日达退货运费险”
|
||||
▶ 标题3(场景型):痛点解决方案,例:
|
||||
“健身房必备!男士爆款运动鞋防滑减震跑步鞋宽脚掌透气训练鞋久穿不累”
|
||||
3. 输出格式:仅返回JSON,键名固定为t1/t2/t3(节省字符):
|
||||
{
|
||||
"t1": "标题1(关键词+功能)",
|
||||
"t2": "标题2(促销+服务)",
|
||||
"t3": "标题3(场景+痛点)"
|
||||
}
|
||||
4. 特殊要求:
|
||||
• 若标题含促销,需标注具体力度(如“7折”而非“促销中”)
|
||||
• 人群定向需明确(如“中老年”“宝妈”而非“通用”)
|
||||
• 材质/规格必须具体(如“新疆棉”“20000mAh”)
|
||||
';
|
||||
$userContent = $data['message'];
|
||||
$result = $this->services->ai()->chat($systemContent, $userContent);
|
||||
return array_values(json_decode($result, true));
|
||||
}
|
||||
|
||||
/**
|
||||
* AI生成商品简介
|
||||
* @param array $data 请求数据
|
||||
* @return array
|
||||
*/
|
||||
public function productInfo($data)
|
||||
{
|
||||
$systemContent = '
|
||||
请严格按此规范执行:
|
||||
1. 核心指令:
|
||||
• 生成3条差异化商品简介,每条不少于80字,符合电商平台SEO规则
|
||||
• 必须包含:核心关键词(前10字)+核心卖点(材质/功能)+附加价值(促销/场景/人群)
|
||||
• 禁止:重复词、违禁词、模糊描述(如“优质”“多功能”)
|
||||
2. 优化维度:
|
||||
▶ 标题1(流量型):关键词堆砌+高频搜索词,例:
|
||||
“2024新款男士运动鞋透气防滑跑步鞋轻便百搭男鞋网面休闲鞋耐磨减震”
|
||||
▶ 标题2(转化型):强促销+紧迫感,例:
|
||||
“【限时5折】男士运动鞋春秋季飞织透气跑步鞋学生潮流男鞋次日达退货运费险”
|
||||
▶ 标题3(场景型):痛点解决方案,例:
|
||||
“健身房必备!男士爆款运动鞋防滑减震跑步鞋宽脚掌透气训练鞋久穿不累”
|
||||
3. 输出格式:仅返回JSON,键名固定为t1/t2/t3(节省字符):
|
||||
{
|
||||
"t1": "标题1(关键词+功能)",
|
||||
"t2": "标题2(促销+服务)",
|
||||
"t3": "标题3(场景+痛点)"
|
||||
}
|
||||
4. 特殊要求:
|
||||
• 若标题含促销,需标注具体力度(如“7折”而非“促销中”)
|
||||
• 人群定向需明确(如“中老年”“宝妈”而非“通用”)
|
||||
• 材质/规格必须具体(如“新疆棉”“20000mAh”)
|
||||
';
|
||||
$userContent = $data['store_name'] . $data['message'];
|
||||
$result = $this->services->ai()->chat($systemContent, $userContent);
|
||||
return array_values(json_decode($result, true));
|
||||
}
|
||||
|
||||
/**
|
||||
* AI生成推广文案
|
||||
* @param array $data 请求数据
|
||||
* @return array
|
||||
*/
|
||||
public function shareContent($data)
|
||||
{
|
||||
$systemContent = '
|
||||
请严格按此规范执行:
|
||||
1. 核心指令:
|
||||
• 生成3条差异化推广文案,每条不少于100字,符合各平台投放规范
|
||||
• 必须包含:核心卖点(前15字)+用户痛点+行动号召
|
||||
• 禁止:虚假宣传、绝对化用语(如"最佳""第一")、模糊表述
|
||||
2. 优化维度:
|
||||
▶ 文案1(痛点刺激型):直击用户痛点+解决方案,例:
|
||||
"跑步膝盖疼?新一代缓震科技运动鞋,采用XX减震材料,降低关节冲击力30%,立即体验→"
|
||||
▶ 文案2(场景共鸣型):构建使用场景+情感共鸣,例:
|
||||
"加班到深夜的你值得更好!人体工学办公椅,8小时久坐不腰酸,今日下单享免费安装→"
|
||||
▶ 文案3(数据实证型):量化效果+权威背书,例:
|
||||
"92%用户回购的爆款面膜!中科院认证XX成分,实测28天淡化细纹45%,限时买二送一→"
|
||||
3. 输出格式:仅返回JSON,键名固定为c1/c2/c3:
|
||||
{
|
||||
"c1": "文案1(痛点型)",
|
||||
"c2": "文案2(场景型)",
|
||||
"c3": "文案3(数据型)"
|
||||
}
|
||||
4. 特殊要求:
|
||||
• 痛点描述需具体(如"久坐腰酸"而非"不舒服")
|
||||
• 数据必须真实可查(如"实验室实测""用户调研数据")
|
||||
• 行动号召明确(如"立即咨询""限时特惠"需标注截止时间)
|
||||
';
|
||||
$userContent = $data['store_name'] . $data['message'];
|
||||
$result = $this->services->ai()->chat($systemContent, $userContent);
|
||||
return array_values(json_decode($result, true));
|
||||
}
|
||||
|
||||
/**
|
||||
* AI生成商品规格属性
|
||||
* @param array $data 请求数据
|
||||
* @return array
|
||||
*/
|
||||
public function productAttr($data)
|
||||
{
|
||||
$systemContent = '
|
||||
请严格按此规范执行:
|
||||
1. 核心指令:
|
||||
• 自动识别商品类目并生成完整规格参数
|
||||
• 参数值必须为具体可选项(非范围值)
|
||||
• 包含:基础参数+技术参数+功能参数+扩展参数
|
||||
• 最多三个规格类型,每个规格最多10个值
|
||||
2. 输出格式:仅返回JSON,键名固定为value/detail:
|
||||
{
|
||||
"rule_name": "商品类目"
|
||||
"spec": [
|
||||
{
|
||||
"value": "规格名称1",
|
||||
"detail": [
|
||||
"规格值1-1",
|
||||
"规格值1-2"
|
||||
]
|
||||
},
|
||||
{
|
||||
"value": "规格名称2",
|
||||
"detail": [
|
||||
"规格值2-1",
|
||||
"规格值2-2"
|
||||
]
|
||||
},
|
||||
...
|
||||
]
|
||||
}
|
||||
';
|
||||
$userContent = $data['message'];
|
||||
$result = $this->services->ai()->chat($systemContent, $userContent);
|
||||
return json_decode($result, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* AI生成商品参数模板
|
||||
* @param array $data 请求数据
|
||||
* @return array
|
||||
*/
|
||||
public function productSpecs($data)
|
||||
{
|
||||
$systemContent = '
|
||||
请严格按此规范执行:
|
||||
1. 核心指令:
|
||||
• 自动识别商品类目并生成完整规格参数
|
||||
• 参数值必须为具体可选项(非范围值)
|
||||
• 包含:基础参数+技术参数+功能参数+扩展参数
|
||||
• 生成最少5个specs参数,name和value都是字符串,sort为0
|
||||
2. 输出格式:仅返回JSON:
|
||||
{
|
||||
"name": "参数模板名称",
|
||||
"specs": [
|
||||
{
|
||||
"name": "参数名称1",
|
||||
"value": "参数值1",
|
||||
"sort": 0,
|
||||
},
|
||||
{
|
||||
"name": "参数名称2",
|
||||
"value": "参数值2",
|
||||
"sort": 0,
|
||||
}
|
||||
...
|
||||
]
|
||||
}
|
||||
';
|
||||
$userContent = $data['message'];
|
||||
$result = $this->services->ai()->chat($systemContent, $userContent);
|
||||
return json_decode($result, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* AI生成商品评价
|
||||
* @param array $data 请求数据
|
||||
* @return array
|
||||
*/
|
||||
public function productReply($data)
|
||||
{
|
||||
$productInfo = app()->make(StoreProductServices::class)->get($data['product_id']);
|
||||
$sku = app()->make(StoreProductAttrValueServices::class)->value(['product_id' => $data['product_id'], 'unique' => $data['unique']], 'suk');
|
||||
$date = date('Y-m-d H:i:s');
|
||||
$systemContent = '
|
||||
请严格按此规范执行:
|
||||
1. 输出格式:仅返回JSON,一条数据也按照多条数据的格式返回:
|
||||
{
|
||||
[
|
||||
"product_id": ' . $data['product_id'] . ',
|
||||
"unique": ' . $data['unique'] . ',
|
||||
"store_name": ' . $productInfo['store_name'] . ',
|
||||
"product_image": ' . $productInfo['image'] . ',
|
||||
"delivery_score": 5,
|
||||
"service_score": 5,
|
||||
"product_score": 5,
|
||||
"reply_score": "3",
|
||||
"add_time": ' . $date . ',
|
||||
"nickname": "随机生成的用户名",
|
||||
"avatar": "在https://pro.crmeb.net/uploads/thumb_water/0e41012b7d7df9404ca456df1c7625c6.png,https://pro.crmeb.net/uploads/thumb_water/b0c0dc1d88c00870e16a2e21ca53b71a.png,https://pro.crmeb.net/uploads/thumb_water/037bb2585a07753bf9115d7f16bf5fe3.png,https://pro.crmeb.net/uploads/thumb_water/34dad9517ed6fcc7fdd4c035abad098c.png中随机选择一个",
|
||||
"comment": "评价内容"
|
||||
]
|
||||
...
|
||||
}
|
||||
2. 核心指令:
|
||||
• 根据提示词生成10条差异化好评,每条不少于80字
|
||||
• 必须包含:使用体验+具体优点+场景描述
|
||||
• 禁止:重复内容、虚假评价、模糊表述
|
||||
• 评价内容生成到comment字段,用户随机昵称生成到nickname字段,其余固定
|
||||
• 生成3条评价
|
||||
3. 评价维度(根据提示词自动分配):
|
||||
• 质量评价(占比40%):材质/做工/耐用性
|
||||
• 功能评价(占比30%):实际使用效果
|
||||
• 服务评价(占比20%):物流/包装/售后
|
||||
• 场景评价(占比10%):特定使用场景体验
|
||||
4. 特殊要求:
|
||||
• 优先体现提示词相关内容
|
||||
• 使用真实体验式口吻(如"收到后使用了半个月...")
|
||||
• 包含具体细节(如"缝线很密实""按键反应灵敏")
|
||||
• 每条评价需有明确侧重点
|
||||
|
||||
';
|
||||
$userContent = '商品名称:' . $data['store_name'] . ',商品规格:' . $sku . ',提示词:' . $data['message'] . ', 评价维度:质量、功能、服务、场景';
|
||||
$result = $this->services->ai()->chat($systemContent, $userContent);
|
||||
var_dump($result);
|
||||
return json_decode($result, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* AI生成社区内容
|
||||
* @param array $data 请求数据
|
||||
* @return array
|
||||
*/
|
||||
public function community($data)
|
||||
{
|
||||
$systemContent = '
|
||||
请严格按此规范执行:
|
||||
1. 核心指令:
|
||||
• 生成3条内容
|
||||
• title标题要准确概括核心内容,不超过20个汉字,避免夸张表述
|
||||
• content内容要包含核心内容,内容的类型自适应(描述/心得/观点等),并且符合各平台规范,不少于200字,避免重复内容
|
||||
• topic_name话题名称要和内容相关,话题名称不超过10个汉字
|
||||
• 禁止使用网络流行语和过度口语化表达
|
||||
• 保持语言自然流畅,符合中文表达习惯
|
||||
2. 内容要求:
|
||||
▶ 标题规范:
|
||||
• 准确概括核心内容
|
||||
• 不超过20个汉字
|
||||
• 避免夸张表述
|
||||
▶ 正文规范:
|
||||
• 首段:自然引入主题(50-80字)
|
||||
• 主体:根据内容类型自由展开
|
||||
• 结尾:恰当收束(30-50字)
|
||||
3. 输出格式:仅返回JSON:
|
||||
{
|
||||
[
|
||||
"title": "生成标题",
|
||||
"content": "生成正文内容",
|
||||
"topic_name": "话题名称",
|
||||
]
|
||||
...
|
||||
}
|
||||
4. 特殊要求:
|
||||
• 描述类:需包含五感细节(视觉/听觉/触觉等)
|
||||
• 心得类:需包含真实使用体验
|
||||
• 观点类:需包含合理逻辑推导
|
||||
• 禁止使用网络流行语和过度口语化表达
|
||||
';
|
||||
$userContent = $data['message'];
|
||||
$result = $this->services->ai()->chat($systemContent, $userContent);
|
||||
return json_decode($result, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* AI生成社区标题
|
||||
* @param array $data 请求数据
|
||||
* @return array
|
||||
*/
|
||||
public function communityTitle($data)
|
||||
{
|
||||
$systemContent = '
|
||||
请严格按此规范执行:
|
||||
1. 核心指令:
|
||||
• 生成3条差异化标题,每条不超过20字,需准确概括文章内容
|
||||
• 必须包含:核心主题(前10字)+内容亮点+情感基调
|
||||
• 禁止:标题党、无关词、模糊表述(如"精彩""感人")
|
||||
2. 优化维度:
|
||||
▶ 标题1(流量型):关键词聚焦+热点结合,例:"三月樱花拍摄指南:手机出片的5个构图技巧"
|
||||
▶ 标题2(共鸣型):情感触动+场景代入,例:"老城咖啡馆记事:藏在拿铁里的人生百态"
|
||||
▶ 标题3(悬念型):问题引发+价值提示,例:"为何这间民宿让90%客人续住?丽江庭院设计秘密"
|
||||
3. 输出格式:仅返回JSON:
|
||||
{
|
||||
"t1": "标题1(关键词型)",
|
||||
"t2": "标题2(情感型)",
|
||||
"t3": "标题3(悬念型)"
|
||||
}
|
||||
4. 特殊要求:
|
||||
• 情感基调需明确(如"怀旧""治愈"而非"好看")
|
||||
• 内容亮点需具体(如"手机摄影技巧""庭院设计细节")
|
||||
• 文化类内容需标注地域/时期(如"唐代服饰""江南民居")
|
||||
';
|
||||
$userContent = $data['message'];
|
||||
$result = $this->services->ai()->chat($systemContent, $userContent);
|
||||
return array_values(json_decode($result, true));
|
||||
}
|
||||
|
||||
/**
|
||||
* AI优化社区内容
|
||||
* @param array $data 请求数据
|
||||
* @return array
|
||||
*/
|
||||
public function communityContent($data)
|
||||
{
|
||||
$systemContent = '
|
||||
请严格按此规范执行:
|
||||
1. 核心指令:
|
||||
• 生成3条差异化优化版本,每条保持原篇幅±10%
|
||||
• 每条需体现不同优化方向(结构/语言/情感)
|
||||
• 禁止:改变核心事实、虚构内容
|
||||
2. 优化维度:
|
||||
▶ 版本1(结构优化型):
|
||||
重组段落逻辑
|
||||
增强过渡衔接
|
||||
突出核心论点
|
||||
▶ 版本2(语言润色型):
|
||||
提升表达精准度
|
||||
丰富修辞手法
|
||||
统一语言风格
|
||||
▶ 版本3(情感强化型):
|
||||
深化细节描写
|
||||
增强场景代入感
|
||||
把控情感节奏
|
||||
3. 输出格式:仅返回JSON:
|
||||
{
|
||||
"v1": "结构优化版本",
|
||||
"v2": "语言润色版本",
|
||||
"v3": "情感强化版本"
|
||||
}
|
||||
4. 特殊要求:
|
||||
• 技术类:专业术语需验证
|
||||
• 文学类:保留原修辞特色
|
||||
• 商业类:符合广告法规定
|
||||
';
|
||||
$userContent = $data['message'];
|
||||
$result = $this->services->ai()->chat($systemContent, $userContent);
|
||||
return array_values(json_decode($result, true));
|
||||
}
|
||||
|
||||
/**
|
||||
* AI生成文章标题
|
||||
* @param array $data 请求数据
|
||||
* @return array
|
||||
*/
|
||||
public function articleTitle($data)
|
||||
{
|
||||
$systemContent = '
|
||||
请严格按此规范执行:
|
||||
1. 核心指令:
|
||||
• 生成3条差异化标题,每条不超过20字,需准确概括文章内容
|
||||
• 必须包含:核心主题(前10字)+内容亮点+情感基调
|
||||
• 禁止:标题党、无关词、模糊表述(如"精彩""感人")
|
||||
2. 优化维度:
|
||||
▶ 标题1(流量型):关键词聚焦+热点结合,例:"三月樱花拍摄指南:手机出片的5个构图技巧"
|
||||
▶ 标题2(共鸣型):情感触动+场景代入,例:"老城咖啡馆记事:藏在拿铁里的人生百态"
|
||||
▶ 标题3(悬念型):问题引发+价值提示,例:"为何这间民宿让90%客人续住?丽江庭院设计秘密"
|
||||
3. 输出格式:仅返回JSON:
|
||||
{
|
||||
"t1": "标题1(关键词型)",
|
||||
"t2": "标题2(情感型)",
|
||||
"t3": "标题3(悬念型)"
|
||||
}
|
||||
4. 特殊要求:
|
||||
• 情感基调需明确(如"怀旧""治愈"而非"好看")
|
||||
• 内容亮点需具体(如"手机摄影技巧""庭院设计细节")
|
||||
• 文化类内容需标注地域/时期(如"唐代服饰""江南民居")
|
||||
';
|
||||
$userContent = $data['message'];
|
||||
$result = $this->services->ai()->chat($systemContent, $userContent);
|
||||
return array_values(json_decode($result, true));
|
||||
}
|
||||
|
||||
/**
|
||||
* AI优化文章内容
|
||||
* @param array $data 请求数据
|
||||
* @return array
|
||||
*/
|
||||
public function articleContent($data)
|
||||
{
|
||||
$systemContent = '
|
||||
请严格按此规范执行:
|
||||
1. 核心指令:
|
||||
• 生成3条差异化优化版本,每条保持原篇幅±10%
|
||||
• 每条需体现不同优化方向(结构/语言/情感)
|
||||
• 禁止:改变核心事实、虚构内容
|
||||
2. 优化维度:
|
||||
▶ 版本1(结构优化型):
|
||||
重组段落逻辑
|
||||
增强过渡衔接
|
||||
突出核心论点
|
||||
▶ 版本2(语言润色型):
|
||||
提升表达精准度
|
||||
丰富修辞手法
|
||||
统一语言风格
|
||||
▶ 版本3(情感强化型):
|
||||
深化细节描写
|
||||
增强场景代入感
|
||||
把控情感节奏
|
||||
3. 输出格式:仅返回JSON:
|
||||
{
|
||||
"v1": "结构优化版本",
|
||||
"v2": "语言润色版本",
|
||||
"v3": "情感强化版本"
|
||||
}
|
||||
4. 特殊要求:
|
||||
• 技术类:专业术语需验证
|
||||
• 文学类:保留原修辞特色
|
||||
• 商业类:符合广告法规定
|
||||
';
|
||||
$userContent = $data['message'];
|
||||
$result = $this->services->ai()->chat($systemContent, $userContent);
|
||||
return array_values(json_decode($result, true));
|
||||
}
|
||||
|
||||
}
|
||||
100
app/services/system/AppVersionServices.php
Normal file
100
app/services/system/AppVersionServices.php
Normal file
@@ -0,0 +1,100 @@
|
||||
<?php
|
||||
|
||||
namespace app\services\system;
|
||||
|
||||
use app\dao\system\AppVersionDao;
|
||||
use app\services\BaseServices;
|
||||
use crmeb\services\FormBuilder as Form;
|
||||
use think\annotation\Inject;
|
||||
use think\facade\Route as Url;
|
||||
|
||||
class AppVersionServices extends BaseServices
|
||||
{
|
||||
/**
|
||||
* @var AppVersionDao
|
||||
*/
|
||||
#[Inject]
|
||||
protected AppVersionDao $dao;
|
||||
|
||||
/**
|
||||
* 获取APP版本列表
|
||||
* @param array $where 查询条件
|
||||
* @return array
|
||||
*/
|
||||
public function versionList($where)
|
||||
{
|
||||
[$page, $limit] = $this->getPageValue();
|
||||
$list = $this->dao->versionList($where, $page, $limit);
|
||||
foreach ($list as &$item) {
|
||||
$item['add_time'] = date('Y-m-d H:i:s', $item['add_time']);
|
||||
}
|
||||
$count = $this->dao->versionCount($where);
|
||||
return compact('list', 'count');
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建版本表单
|
||||
* @param int $id 版本ID
|
||||
* @return array
|
||||
*/
|
||||
public function createForm($id = 0)
|
||||
{
|
||||
if ($id) {
|
||||
$info = $this->dao->get($id);
|
||||
}
|
||||
$field[] = Form::hidden('id', $info['id'] ?? 0);
|
||||
$field[] = Form::input('version', '版本号:', $info['version'] ?? '')->col(24);
|
||||
$field[] = Form::radio('platform', '平台类型:', $info['platform'] ?? 1)->options([['label' => 'Android', 'value' => 1], ['label' => 'IOS', 'value' => 2]]);
|
||||
$field[] = Form::input('info', '版本介绍:', $info['info'] ?? '')->type('textarea');
|
||||
$field[] = Form::input('url', '下载链接:', $info['url'] ?? '')->appendRule('suffix', [
|
||||
'type' => 'div',
|
||||
'class' => 'tips-info',
|
||||
'domProps' => ['innerHTML' => '填写下载链接,Android的为压缩包的url地址,点击升级会自动下载压缩包替换安装,例如:域名/xxx.zip;IOS的为应用商店链接地址,直接跳转AppStore,例如:itms-apps://itunes.apple.com/cn/app/id1234567890']
|
||||
]);
|
||||
$field[] = Form::radio('is_force', '强制:', $info['is_force'] ?? 1)->options([['label' => '开启', 'value' => 1], ['label' => '关闭', 'value' => 0]]);
|
||||
$field[] = Form::radio('is_new', '是否最新:', $info['is_new'] ?? 1)->options([['label' => '是', 'value' => 1], ['label' => '否', 'value' => 0]]);
|
||||
return create_form('添加版本信息', $field, Url::buildUrl('/app_version/version_save'), 'POST');
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存版本信息
|
||||
* @param int $id 版本ID
|
||||
* @param array $data 版本数据
|
||||
* @return bool|mixed
|
||||
*/
|
||||
public function versionSave($id, $data)
|
||||
{
|
||||
if ($id) {
|
||||
return $this->transaction(function () use ($data, $id) {
|
||||
if ($data['is_new']) {
|
||||
$this->dao->update(['platform' => $data['platform']], ['is_new' => 0]);
|
||||
}
|
||||
return $this->dao->update($id, $data);
|
||||
});
|
||||
} else {
|
||||
$data['is_del'] = 0;
|
||||
$data['add_time'] = time();
|
||||
return $this->transaction(function () use ($data) {
|
||||
$this->dao->update(['platform' => $data['platform']], ['is_new' => 0]);
|
||||
return $this->dao->save($data);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取最新版本信息
|
||||
* @param int $platform 平台类型(1:Android 2:IOS)
|
||||
* @return array
|
||||
*/
|
||||
public function getNewInfo($platform)
|
||||
{
|
||||
$res = $this->dao->get(['platform' => $platform, 'is_new' => 1]);
|
||||
if ($res) {
|
||||
$res = $res->toArray();
|
||||
$res['time'] = date('Y-m-d H:i:s', $res['add_time']);
|
||||
return $res;
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
}
|
||||
188
app/services/system/CapitalFlowServices.php
Normal file
188
app/services/system/CapitalFlowServices.php
Normal file
@@ -0,0 +1,188 @@
|
||||
<?php
|
||||
|
||||
namespace app\services\system;
|
||||
|
||||
use app\dao\system\CapitalFlowDao;
|
||||
use app\services\BaseServices;
|
||||
use crmeb\exceptions\AdminException;
|
||||
use think\annotation\Inject;
|
||||
|
||||
/**
|
||||
* 资金流水
|
||||
* Class SystemFileServices
|
||||
* @package app\services\system
|
||||
* @mixin CapitalFlowDao
|
||||
*/
|
||||
class CapitalFlowServices extends BaseServices
|
||||
{
|
||||
|
||||
protected array $typeName = [
|
||||
1 => '商城购物',
|
||||
2 => '商城购物退款',
|
||||
3 => '用户充值',
|
||||
4 => '用户充值退款',
|
||||
5 => '抽奖中奖',
|
||||
6 => '佣金提现',
|
||||
7 => '购买会员',
|
||||
8 => '线下支付',
|
||||
];
|
||||
|
||||
/**
|
||||
* @var CapitalFlowDao
|
||||
*/
|
||||
#[Inject]
|
||||
protected CapitalFlowDao $dao;
|
||||
|
||||
/**
|
||||
* 添加资金流水
|
||||
* @param $orderInfo
|
||||
* @param string $type
|
||||
*/
|
||||
public function setFlow($data, $type = '')
|
||||
{
|
||||
$data['flow_id'] = 'ZJ' . date('Ymdhis', time()) . rand('1000', '9999');
|
||||
switch ($type) {
|
||||
case 'order':
|
||||
$data['trading_type'] = 1;
|
||||
break;
|
||||
case 'refund':
|
||||
$data['price'] = bcmul('-1', $data['price'], 2);
|
||||
$data['trading_type'] = 2;
|
||||
break;
|
||||
case 'recharge':
|
||||
$data['trading_type'] = 3;
|
||||
break;
|
||||
case 'refund_recharge':
|
||||
$data['price'] = bcmul('-1', $data['price'], 2);
|
||||
$data['trading_type'] = 4;
|
||||
break;
|
||||
case 'luck':
|
||||
$data['price'] = bcmul('-1', $data['price'], 2);
|
||||
$data['trading_type'] = 5;
|
||||
break;
|
||||
case 'extract':
|
||||
$data['price'] = bcmul('-1', $data['price'], 2);
|
||||
$data['trading_type'] = 6;
|
||||
break;
|
||||
case 'pay_member':
|
||||
$data['trading_type'] = 7;
|
||||
break;
|
||||
case 'offline_scan':
|
||||
$data['trading_type'] = 8;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
$data['add_time'] = time();
|
||||
$this->dao->save($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取资金流水
|
||||
* @param $where
|
||||
* @return array
|
||||
*/
|
||||
public function getFlowList($where)
|
||||
{
|
||||
$export = $where['export'] ?? 0;
|
||||
unset($where['export']);
|
||||
[$page, $limit] = $this->getPageValue();
|
||||
$status = ['支付订单', '订单退款', '充值订单', '充值退款', '抽奖红包', '佣金提现', '购买会员', '线下收银'];
|
||||
$pay_type = ['weixin' => '微信支付', 'routine' => '小程序', 'alipay' => '支付宝', 'offline' => '线下支付', 'bank' => '银行'];
|
||||
$list = $this->dao->getList($where, '*', $page, $limit);
|
||||
foreach ($list as &$item) {
|
||||
$item['add_time'] = date('Y-m-d H:i:s', $item['add_time']);
|
||||
$item['trading_type'] = $status[$item['trading_type']];
|
||||
$item['pay_type'] = $pay_type[$item['pay_type']] ?? '';
|
||||
}
|
||||
$count = $this->dao->count($where);
|
||||
if ($export) {
|
||||
$fileKey = ['flow_id', 'order_id', 'nickname', 'phone', 'price', 'trading_type', 'pay_type', 'add_time', 'mark'];
|
||||
$header = ['交易单号', '关联订单', '用户', '电话', '金额', '订单类型', '支付类型', '交易时间', '备注'];
|
||||
$fileName = '账单导出' . date('YmdHis') . rand(1000, 9999);
|
||||
return compact('list', 'fileKey', 'header', 'fileName');
|
||||
} else {
|
||||
return compact('list', 'count', 'status');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加备注
|
||||
* @param $id
|
||||
* @param $data
|
||||
* @return bool
|
||||
*/
|
||||
public function setMark($id, $data)
|
||||
{
|
||||
$res = $this->dao->update($id, $data);
|
||||
if ($res) {
|
||||
return true;
|
||||
} else {
|
||||
throw new AdminException('备注失败');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取账单记录
|
||||
* @param $where
|
||||
* @return array
|
||||
*/
|
||||
public function getFlowRecord($where)
|
||||
{
|
||||
[$page, $limit] = $this->getPageValue();
|
||||
$data = $this->dao->getRecordList($where, $page, $limit);
|
||||
$i = 1;
|
||||
foreach ($data['list'] as &$item) {
|
||||
$item['id'] = $i;
|
||||
$i++;
|
||||
$item['entry_price'] = bcadd($item['income_price'], $item['exp_price'], 2);
|
||||
switch ($where['type']) {
|
||||
case "day" :
|
||||
$item['title'] = "日账单";
|
||||
$item['add_time'] = date('Y-m-d', $item['add_time']);
|
||||
break;
|
||||
case "week" :
|
||||
$item['title'] = "周账单";
|
||||
$item['add_time'] = '第' . $item['day'] . '周(' . date('m', $item['add_time']) . '月)';
|
||||
break;
|
||||
case "month" :
|
||||
$item['title'] = "月账单";
|
||||
$item['add_time'] = date('Y-m', $item['add_time']);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户资金记录
|
||||
* @param int $uid
|
||||
* @param array $data
|
||||
* @return array
|
||||
*/
|
||||
public function userCapitalList(int $uid, array $data)
|
||||
{
|
||||
$where = [];
|
||||
$where['uid'] = $uid;
|
||||
$where['trading_type'] = [1, 7];
|
||||
if ((isset($data['start']) && $data['start']) || (isset($data['stop']) && $data['stop'])) {
|
||||
$where['time'] = [$data['start'], $data['stop']];
|
||||
}
|
||||
[$page, $limit] = $this->getPageValue();
|
||||
$list = $this->dao->getList($where, '*', $page, $limit);
|
||||
$times = [];
|
||||
if ($list) {
|
||||
$typeName = $this->typeName;
|
||||
foreach ($list as &$item) {
|
||||
$item['time_key'] = $item['add_time'] ? date('Y-m', (int)$item['add_time']) : '';
|
||||
$item['day'] = $item['add_time'] ? date('Y-m-d', (int)$item['add_time']) : '';
|
||||
$item['add_time'] = $item['add_time'] ? date('Y/m/d H:i', (int)$item['add_time']) : '';
|
||||
$item['type'] = $item['trading_type'];
|
||||
$item['type_name'] = $typeName[$item['type'] ?? ''] ?? '未知类型';
|
||||
$item['title'] = $item['type_name'];
|
||||
}
|
||||
$times = array_merge(array_unique(array_column($list, 'time_key')));
|
||||
}
|
||||
return ['list' => $list, 'time' => $times];
|
||||
}
|
||||
}
|
||||
481
app/services/system/PrintDocumentServices.php
Normal file
481
app/services/system/PrintDocumentServices.php
Normal file
@@ -0,0 +1,481 @@
|
||||
<?php
|
||||
|
||||
namespace app\services\system;
|
||||
|
||||
use app\dao\system\PrintDocumentDao;
|
||||
use app\services\BaseServices;
|
||||
use crmeb\exceptions\AdminException;
|
||||
use crmeb\services\FormBuilder as Form;
|
||||
use crmeb\services\printer\Printer;
|
||||
use think\annotation\Inject;
|
||||
|
||||
class PrintDocumentServices extends BaseServices
|
||||
{
|
||||
/**
|
||||
* @var PrintDocumentDao
|
||||
*/
|
||||
#[Inject]
|
||||
protected PrintDocumentDao $dao;
|
||||
|
||||
/**
|
||||
* 小票打印机列表
|
||||
* @param $where
|
||||
* @return array
|
||||
* @author wuhaotian
|
||||
* @email 442384644@qq.com
|
||||
* @date 2024/8/21
|
||||
*/
|
||||
public function printList($where)
|
||||
{
|
||||
[$page, $limit] = $this->getPageValue();
|
||||
$list = $this->dao->printList($where, $page, $limit);
|
||||
foreach ($list as &$item) {
|
||||
$item['add_time'] = date('Y-m-d H:i:s', $item['add_time']);
|
||||
}
|
||||
$count = $this->dao->printCount($where);
|
||||
return compact('list', 'count');
|
||||
}
|
||||
|
||||
/**
|
||||
* 小票打印机表单
|
||||
* @param $id
|
||||
* @return mixed
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
* @author wuhaotian
|
||||
* @email 442384644@qq.com
|
||||
* @date 2024/8/21
|
||||
*/
|
||||
public function printForm($id, $supplier_id = 0)
|
||||
{
|
||||
$info = $this->dao->get($id) ?? [];
|
||||
if ($info) $info = $info->toArray();
|
||||
$field[] = Form::input('print_name', '打印机名称:', $info['print_name'] ?? '')->required('请输入打印机名称')->info('打印机名称');
|
||||
$field[] = Form::radio('type', '平台选择:', $info['type'] ?? 1)
|
||||
->options([['label' => '易联云', 'value' => 1], ['label' => '飞鹅云', 'value' => 2]])
|
||||
->appendControl(1, [
|
||||
Form::input('yly_user_id', '用户ID:', $info['yly_user_id'] ?? '')->required('请输入用户ID')->info('易联云开发者ID'),
|
||||
Form::input('yly_app_id', '应用ID:', $info['yly_app_id'] ?? '')->required('请输入应用ID')->info('易联应用ID'),
|
||||
Form::input('yly_app_secret', '应用密钥:', $info['yly_app_secret'] ?? '')->required('请输入应用密钥')->info('易联应用密钥'),
|
||||
Form::input('yly_sn', '终端号', $info['yly_sn'] ?? '')->required('请输入终端号')->info('易联云打印机终端号,打印机型号:易联云打印机 K4无线版'),
|
||||
]
|
||||
)->appendControl(2, [
|
||||
Form::input('fey_user', '飞鹅云USER:', $info['fey_user'] ?? '')->required('请输入飞鹅云USER')->info('飞鹅云后台注册账号'),
|
||||
Form::input('fey_ukey', '飞鹅云UYEK:', $info['fey_ukey'] ?? '')->required('请输入飞鹅云UYEK')->info('飞鹅云后台注册账号后生成的UKEY 【备注:这不是填打印机的KEY】'),
|
||||
Form::input('fey_sn', '飞鹅云SN:', $info['fey_sn'] ?? '')->required('请输入飞鹅云SN')->info('打印机标签上的编号,必须要在管理后台里添加打印机或调用API接口添加之后,才能调用API'),
|
||||
]
|
||||
);
|
||||
$field[] = Form::number('times', '打印联数:', $info['times'] ?? 1)->min(0)->required('请输入打印联数')->info('打印机单次打印张数');
|
||||
$field[] = Form::radio('print_type', '打印时机:', $info['print_type'] ?? 1)->options([['label' => '支付后打印', 'value' => 1], ['label' => '下单后打印', 'value' => 2]]);
|
||||
$field[] = Form::switches('status', '打印开关:', $info['status'] ?? 1)->falseValue(0)->trueValue(1)->openStr('打开')->closeStr('关闭')->size('large');
|
||||
return create_form('小票打印机', $field, $this->url('/print/save/' . $id), 'POST');
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存小票打印机
|
||||
* @param $id
|
||||
* @param $data
|
||||
* @return bool
|
||||
* @author wuhaotian
|
||||
* @email 442384644@qq.com
|
||||
* @date 2024/8/21
|
||||
*/
|
||||
public function printSave($id, $data)
|
||||
{
|
||||
if ($id) {
|
||||
$this->dao->update($id, $data);
|
||||
} else {
|
||||
$data['add_time'] = time();
|
||||
$this->dao->save($data);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改打印机状态
|
||||
* @param $id
|
||||
* @param $status
|
||||
* @return bool
|
||||
* @author wuhaotian
|
||||
* @email 442384644@qq.com
|
||||
* @date 2024/8/21
|
||||
*/
|
||||
public function printSetStatus($id, $status)
|
||||
{
|
||||
$this->dao->update($id, ['status' => $status]);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除打印机
|
||||
* @param $id
|
||||
* @return bool
|
||||
* @author wuhaotian
|
||||
* @email 442384644@qq.com
|
||||
* @date 2024/8/21
|
||||
*/
|
||||
public function printDel($id)
|
||||
{
|
||||
$this->dao->update($id, ['is_del' => 1]);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取打印内容配置
|
||||
* @param int $id 打印机ID
|
||||
* @return array
|
||||
*/
|
||||
public function getPrintContent($id)
|
||||
{
|
||||
$print_content = $this->dao->value(['id' => $id], 'print_content');
|
||||
return $print_content ? json_decode($print_content, true) : [];
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存打印内容配置
|
||||
* @param int $id 打印机ID
|
||||
* @param array $data 打印内容配置
|
||||
* @return bool
|
||||
*/
|
||||
public function savePrintContent($id, $data)
|
||||
{
|
||||
$print_content = json_encode($data);
|
||||
$this->dao->update($id, ['print_content' => $print_content]);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 开始打印订单小票
|
||||
* @param array $order 订单信息
|
||||
* @param array $product 商品信息
|
||||
* @param int $print_type 打印时机(1:支付后 2:下单后)
|
||||
* @param int $supplier_id 供应商ID
|
||||
* @return void
|
||||
* @throws AdminException
|
||||
*/
|
||||
public function startPrint($order, $product, $print_type = 1, $supplier_id = 0)
|
||||
{
|
||||
$list = $this->dao->printList(['status' => 1, 'print_type' => $print_type, 'supplier_id' => $supplier_id]);
|
||||
foreach ($list as $item) {
|
||||
if ($item['type'] == 1) { //易联云
|
||||
$name = 'yi_lian_yun';
|
||||
$configData = [
|
||||
'partner' => $item['yly_user_id'],
|
||||
'clientId' => $item['yly_app_id'],
|
||||
'apiKey' => $item['yly_app_secret'],
|
||||
'terminal' => $item['yly_sn']
|
||||
];
|
||||
$print_content = json_decode($item['print_content'], true);
|
||||
if (is_null($print_content) || !count($print_content)) throw new AdminException('请先配置打印内容');
|
||||
$content = $this->ylyContent($print_content, $order, $product, $item['times'], $print_type);
|
||||
} else { //飞鹅云
|
||||
$name = 'fei_e_yun';
|
||||
$configData = [
|
||||
'feyUser' => $item['fey_user'],
|
||||
'feyUkey' => $item['fey_ukey'],
|
||||
'feySn' => $item['fey_sn']
|
||||
];
|
||||
$print_content = json_decode($item['print_content'], true);
|
||||
if (is_null($print_content) || !count($print_content)) throw new AdminException('请先配置打印内容');
|
||||
$content = $this->feyContent($print_content, $order, $product, $print_type);
|
||||
}
|
||||
$printer = new Printer($name, $configData);
|
||||
|
||||
$printer->setPrinterContent($content, $item['times'])->startPrinter();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成易联云打印内容
|
||||
* @param array $printContent 打印配置
|
||||
* @param array $orderInfo 订单信息
|
||||
* @param array $product 商品信息
|
||||
* @param int $times 打印联数
|
||||
* @param int $print_type 打印时机
|
||||
* @return string
|
||||
*/
|
||||
public function ylyContent($printContent, $orderInfo, $product, $times, $print_type)
|
||||
{
|
||||
$goodsStr = '<table><tr><td>名称</td><td>单价</td><td>数量</td><td>金额</td></tr>';
|
||||
foreach ($product as $item) {
|
||||
$goodsStr .= '<tr><td><FH2><FW2>----------------</FW2></FH2></td></tr>';
|
||||
$goodsStr .= '<tr>';
|
||||
$price = $item['sum_price'];
|
||||
$num = $item['cart_num'];
|
||||
$prices = bcmul((string)$item['cart_num'], (string)$item['sum_price'], 2);
|
||||
$goodsStr .= "<td>{$item['productInfo']['store_name']} | {$item['productInfo']['attrInfo']['suk']}</td><td>{$price}</td><td>{$num}</td><td>{$prices}</td>";
|
||||
$goodsStr .= '</tr>';
|
||||
if (in_array(1, $printContent['goods'])) {
|
||||
$goodsStr .= '<tr>';
|
||||
$goodsStr .= "<td>规格编码:{$item['productInfo']['attrInfo']['code']}</td>";
|
||||
$goodsStr .= '</tr>';
|
||||
}
|
||||
unset($price, $num, $prices);
|
||||
}
|
||||
$goodsStr .= '</table>';
|
||||
$total_price = bcadd($orderInfo['total_price'], $orderInfo['pay_postage'], 2);
|
||||
$addTime = date('Y-m-d H:i:s', $orderInfo['add_time']);
|
||||
$payTime = isset($orderInfo['pay_time']) ? date('Y-m-d H:i:s', $orderInfo['pay_time']) : '';
|
||||
$printTime = date('Y-m-d H:i:s', time());
|
||||
|
||||
$content = '';
|
||||
$content .= '<MN>' . $times . '</MN>';
|
||||
if ($printContent['header']) {
|
||||
$content .= '<FS2><center>' . sys_config('site_name') . '</center></FS2>';
|
||||
$content .= '<FH2><FW2>----------------</FW2></FH2>';
|
||||
}
|
||||
if ($printContent['delivery']) {
|
||||
if ($orderInfo['shipping_type'] == 1) {
|
||||
$content .= "配送方式:商家配送 \r";
|
||||
} else {
|
||||
$content .= "配送方式:门店自提 \r";
|
||||
}
|
||||
$content .= '客户姓名: ' . $orderInfo['real_name'] . " \r";
|
||||
$content .= '客户电话: ' . $orderInfo['user_phone'] . " \r";
|
||||
if ($orderInfo['shipping_type'] == 1) $content .= '收货地址: ' . $orderInfo['user_address'] . " \r";
|
||||
$content .= '<FH2><FW2>----------------</FW2></FH2>';
|
||||
}
|
||||
if ($printContent['buyer_remarks']) {
|
||||
$content .= '买家备注: ' . $orderInfo['mark'] . " \r";
|
||||
$content .= '<FH2><FW2>----------------</FW2></FH2>';
|
||||
}
|
||||
if (in_array(0, $printContent['goods'])) {
|
||||
$content .= '*************商品***************';
|
||||
$content .= " \r";
|
||||
$content .= $goodsStr;
|
||||
$content .= "********************************\r";
|
||||
$content .= '<FH2><FW2>----------------</FW2></FH2>';
|
||||
}
|
||||
if ($printContent['freight']) {
|
||||
$content .= '<RA>邮费:' . $orderInfo['pay_postage'] . '元</RA>';
|
||||
$content .= '<RA>合计:' . $total_price . '元</RA>';
|
||||
$content .= '<FH2><FW2>----------------</FW2></FH2>';
|
||||
}
|
||||
if ($printContent['preferential']) {
|
||||
$discount_price = bcsub(bcadd($orderInfo['total_price'], $orderInfo['pay_postage'], 2), bcadd($orderInfo['deduction_price'], $orderInfo['pay_price'], 2), 2);
|
||||
$content .= '<RA>优惠:-' . $discount_price . '元</RA>';
|
||||
$content .= '<RA>抵扣:-' . $orderInfo['deduction_price'] . '元</RA>';
|
||||
$content .= '<FH2><FW2>----------------</FW2></FH2>';
|
||||
}
|
||||
if (in_array(0, $printContent['pay'])) {
|
||||
if ($print_type == 1) {
|
||||
$content .= match ($orderInfo['pay_type']) {
|
||||
'weixin' => '<RA>支付方式:微信支付</RA>',
|
||||
'alipay' => '<RA>支付方式:支付宝支付</RA>',
|
||||
'yue' => '<RA>支付方式:余额支付</RA>',
|
||||
'offline' => '<RA>支付方式:线下支付</RA>',
|
||||
default => '<RA>支付方式:暂无</RA>',
|
||||
};
|
||||
} else {
|
||||
$content .= '<RA>支付方式:暂无</RA>';
|
||||
}
|
||||
}
|
||||
if (in_array(1, $printContent['pay'])) {
|
||||
$content .= '<RA>实际支付:' . $orderInfo['pay_price'] . '元</RA>';
|
||||
}
|
||||
if (count($printContent['pay'])) {
|
||||
$content .= '<FH2><FW2>----------------</FW2></FH2>';
|
||||
}
|
||||
if (in_array(0, $printContent['order'])) {
|
||||
$content .= '订单编号:' . $orderInfo['order_id'] . "\r";
|
||||
}
|
||||
if (in_array(1, $printContent['order'])) {
|
||||
$content .= '下单时间:' . $addTime . "\r";
|
||||
}
|
||||
if (in_array(2, $printContent['order'])) {
|
||||
$content .= '支付时间:' . $payTime . "\r";
|
||||
}
|
||||
if (in_array(3, $printContent['order'])) {
|
||||
$content .= '打印时间:' . $printTime . "\r";
|
||||
}
|
||||
$content .= '<FH2><FW2>----------------</FW2></FH2>';
|
||||
if ($printContent['code'] && $printContent['code_url']) {
|
||||
$content .= '<QR>' . sys_config('site_url') . $printContent['code_url'] . '</QR>';
|
||||
$content .= " \r";
|
||||
}
|
||||
if ($printContent['show_notice']) {
|
||||
$content .= '<center>' . $printContent['notice_content'] . '</center>';
|
||||
$content .= " \r";
|
||||
}
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成飞鹅云打印内容
|
||||
* @param array $printContent 打印配置
|
||||
* @param array $orderInfo 订单信息
|
||||
* @param array $product 商品信息
|
||||
* @param int $print_type 打印时机
|
||||
* @return string
|
||||
*/
|
||||
public function feyContent($printContent, $orderInfo, $product, $print_type)
|
||||
{
|
||||
$printTime = date('Y-m-d H:i:s', time());
|
||||
$addTime = date('Y-m-d H:i:s', $orderInfo['add_time']);
|
||||
$payTime = isset($orderInfo['pay_time']) ? date('Y-m-d H:i:s', $orderInfo['pay_time']) : '';
|
||||
$content = '';
|
||||
if ($printContent['header']) {
|
||||
$content .= '<CB>' . sys_config('site_name') . '</CB><BR>';
|
||||
$content .= '--------------------------------<BR>';
|
||||
}
|
||||
if ($printContent['delivery']) {
|
||||
if ($orderInfo['shipping_type'] == 1) {
|
||||
$content .= '配送方式:商家配送<BR>';
|
||||
} else {
|
||||
$content .= '配送方式:门店自提<BR>';
|
||||
}
|
||||
$content .= '客户姓名: ' . $orderInfo['real_name'] . '<BR>';
|
||||
$content .= '客户电话: ' . $orderInfo['user_phone'] . '<BR>';
|
||||
if ($orderInfo['shipping_type'] == 1) $content .= '收货地址:' . $orderInfo['user_address'] . '<BR>';
|
||||
$content .= '--------------------------------<BR>';
|
||||
}
|
||||
if ($printContent['buyer_remarks']) {
|
||||
$content .= '买家备注:' . $orderInfo['mark'] . '<BR>';
|
||||
$content .= '--------------------------------<BR>';
|
||||
}
|
||||
if (in_array(0, $printContent['goods'])) {
|
||||
$content .= '<BR>';
|
||||
$content .= '**************商品**************<BR>';
|
||||
$content .= '<BR>';
|
||||
$content .= '名称 单价 数量 金额<BR>';
|
||||
foreach ($product as $item) {
|
||||
$content .= '--------------------------------<BR>';
|
||||
$name = $item['productInfo']['store_name'] . " | " . $item['productInfo']['attrInfo']['suk'];
|
||||
$price = $item['sum_price'];
|
||||
$num = $item['cart_num'];
|
||||
$prices = bcmul((string)$item['cart_num'], (string)$item['sum_price'], 2);
|
||||
$kw3 = '';
|
||||
$kw1 = '';
|
||||
$kw2 = '';
|
||||
$kw4 = '';
|
||||
$str = $name;
|
||||
$blankNum = 14;//名称控制为14个字节
|
||||
$lan = mb_strlen($str, 'utf-8');
|
||||
$m = 0;
|
||||
$j = 1;
|
||||
$blankNum++;
|
||||
$result = array();
|
||||
if (strlen($price) < 6) {
|
||||
$k1 = 6 - strlen($price);
|
||||
for ($q = 0; $q < $k1; $q++) {
|
||||
$kw1 .= ' ';
|
||||
}
|
||||
$price = $price . $kw1;
|
||||
}
|
||||
if (strlen($num) < 3) {
|
||||
$k2 = 3 - strlen($num);
|
||||
for ($q = 0; $q < $k2; $q++) {
|
||||
$kw2 .= ' ';
|
||||
}
|
||||
$num = $num . $kw2;
|
||||
}
|
||||
if (strlen($prices) < 6) {
|
||||
$k3 = 6 - strlen($prices);
|
||||
for ($q = 0; $q < $k3; $q++) {
|
||||
$kw4 .= ' ';
|
||||
}
|
||||
$prices = $prices . $kw4;
|
||||
}
|
||||
for ($i = 0; $i < $lan; $i++) {
|
||||
$new = mb_substr($str, $m, $j, 'utf-8');
|
||||
$j++;
|
||||
if (mb_strwidth($new, 'utf-8') < $blankNum) {
|
||||
if ($m + $j > $lan) {
|
||||
$m = $m + $j;
|
||||
$tail = $new;
|
||||
$lenght = iconv("UTF-8", "GBK//IGNORE", $new);
|
||||
$k = 14 - strlen($lenght);
|
||||
for ($q = 0; $q < $k; $q++) {
|
||||
$kw3 .= ' ';
|
||||
}
|
||||
if ($m == $j) {
|
||||
$tail .= $kw3 . ' ' . $price . ' ' . $num . ' ' . $prices;
|
||||
} else {
|
||||
$tail .= $kw3 . '<BR>';
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
$next_new = mb_substr($str, $m, $j, 'utf-8');
|
||||
if (mb_strwidth($next_new, 'utf-8') < $blankNum) {
|
||||
continue;
|
||||
} else {
|
||||
$m = $i + 1;
|
||||
$result[] = $new;
|
||||
$j = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$head = '';
|
||||
foreach ($result as $key => $value) {
|
||||
if ($key < 1) {
|
||||
$v_lenght = iconv("UTF-8", "GBK//IGNORE", $value);
|
||||
$v_lenght = strlen($v_lenght);
|
||||
if ($v_lenght == 13) $value = $value . " ";
|
||||
$head .= $value . ' ' . $price . ' ' . $num . ' ' . $prices;
|
||||
} else {
|
||||
$head .= $value . '<BR>';
|
||||
}
|
||||
}
|
||||
$content .= $head . $tail;
|
||||
if (in_array(1, $printContent['goods'])) {
|
||||
$content .= '规格编码:' . $item['productInfo']['attrInfo']['code'] . '<BR>';
|
||||
}
|
||||
unset($price);
|
||||
}
|
||||
$content .= '<BR>';
|
||||
$content .= '********************************<BR>';
|
||||
}
|
||||
if ($printContent['freight']) {
|
||||
$content .= '<BR>';
|
||||
$content .= '--------------------------------<BR>';
|
||||
$content .= '<RIGHT>邮费:' . number_format($orderInfo['pay_postage'], 2) . '元</RIGHT><BR>';
|
||||
$total_price = bcadd($orderInfo['total_price'], $orderInfo['pay_postage'], 2);
|
||||
$content .= '<RIGHT>合计:' . number_format($total_price, 2) . '元</RIGHT>';
|
||||
$content .= '--------------------------------<BR>';
|
||||
}
|
||||
if ($printContent['preferential']) {
|
||||
$discount_price = bcsub(bcadd($orderInfo['total_price'], $orderInfo['pay_postage'], 2), bcadd($orderInfo['deduction_price'], $orderInfo['pay_price'], 2), 2);
|
||||
$content .= '<RIGHT>优惠:-' . number_format($discount_price, 2) . '元</RIGHT><BR>';
|
||||
$content .= '<RIGHT>抵扣:-' . number_format($orderInfo['deduction_price'], 2) . '元</RIGHT>';
|
||||
$content .= '--------------------------------<BR>';
|
||||
}
|
||||
if (in_array(0, $printContent['pay'])) {
|
||||
if ($print_type == 1) {
|
||||
$content .= match ($orderInfo['pay_type']) {
|
||||
'weixin' => '<RIGHT>支付方式:微信支付</RIGHT><BR>',
|
||||
'alipay' => '<RIGHT>支付方式:支付宝支付</RIGHT><BR>',
|
||||
'yue' => '<RIGHT>支付方式:余额支付</RIGHT><BR>',
|
||||
'offline' => '<RIGHT>支付方式:线下支付</RIGHT><BR>',
|
||||
default => '<RIGHT>支付方式:暂无</RIGHT><BR>',
|
||||
};
|
||||
} else {
|
||||
$content .= '<RIGHT>支付方式:暂无</RIGHT><BR>';
|
||||
}
|
||||
$content .= '<RIGHT>实际支付:' . number_format($orderInfo['pay_price'], 2) . '元</RIGHT>';
|
||||
$content .= '--------------------------------<BR>';
|
||||
}
|
||||
if (in_array(0, $printContent['order'])) {
|
||||
$content .= '订单编号:' . $orderInfo['order_id'] . '<BR>';
|
||||
}
|
||||
if (in_array(1, $printContent['order'])) {
|
||||
$content .= '下单时间: ' . $addTime . '<BR>';
|
||||
}
|
||||
if (in_array(2, $printContent['order'])) {
|
||||
$content .= '付款时间: ' . $payTime . '<BR>';
|
||||
}
|
||||
if (in_array(3, $printContent['order'])) {
|
||||
$content .= '打印时间: ' . $printTime . '<BR>';
|
||||
}
|
||||
$content .= '--------------------------------<BR>';
|
||||
$content .= '<BR>';
|
||||
if ($printContent['code'] && $printContent['code_url']) {
|
||||
$content .= '<QR>' . sys_config('site_url') . $printContent['code_url'] . '</QR>';
|
||||
}
|
||||
if ($printContent['show_notice']) {
|
||||
$content .= '<C>' . $printContent['notice_content'] . '</C>';
|
||||
}
|
||||
return $content;
|
||||
}
|
||||
}
|
||||
48
app/services/system/SystemAuthServices.php
Normal file
48
app/services/system/SystemAuthServices.php
Normal file
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\services\system;
|
||||
|
||||
|
||||
use app\services\BaseServices;
|
||||
use crmeb\exceptions\AdminException;
|
||||
use crmeb\services\HttpService;
|
||||
|
||||
/**
|
||||
* 商业授权
|
||||
* Class SystemAuthServices
|
||||
* @package app\services\system
|
||||
*/
|
||||
class SystemAuthServices extends BaseServices
|
||||
{
|
||||
|
||||
/**
|
||||
* 申请授权
|
||||
* @param array $data
|
||||
* @param $headerData
|
||||
* @return bool
|
||||
*/
|
||||
public function authApply(array $data, $headerData)
|
||||
{
|
||||
$res = HttpService::postRequest('http://authorize.crmeb.net/api/auth_apply', $data, $headerData);
|
||||
if ($res === false) {
|
||||
throw new AdminException('申请失败,服务器没有响应!');
|
||||
}
|
||||
$res = json_decode($res, true);
|
||||
if (isset($res['status'])) {
|
||||
if ($res['status'] == 400) {
|
||||
throw new AdminException($res['msg'] ?? "申请失败");
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
173
app/services/system/SystemClearServices.php
Normal file
173
app/services/system/SystemClearServices.php
Normal file
@@ -0,0 +1,173 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\services\system;
|
||||
|
||||
|
||||
use app\services\BaseServices;
|
||||
use app\services\community\CommunityRelevanceServices;
|
||||
use app\services\product\product\StoreDescriptionServices;
|
||||
use app\services\product\product\StoreProductCouponServices;
|
||||
use app\services\product\product\StoreProductRelationServices;
|
||||
use app\services\product\product\StoreProductReplyServices;
|
||||
use app\services\product\product\StoreProductServices;
|
||||
use app\services\product\sku\StoreProductAttrResultServices;
|
||||
use app\services\product\sku\StoreProductAttrServices;
|
||||
use app\services\product\sku\StoreProductAttrValueServices;
|
||||
use app\services\user\UserRelationServices;
|
||||
use crmeb\exceptions\AdminException;
|
||||
use think\facade\Config;
|
||||
use think\facade\Db;
|
||||
|
||||
/**
|
||||
* 清除数据
|
||||
* Class SystemClearServices
|
||||
* @package app\services\system
|
||||
*/
|
||||
class SystemClearServices extends BaseServices
|
||||
{
|
||||
/**
|
||||
* 清除表数据
|
||||
* @param string|array $table_name
|
||||
* @param $status
|
||||
*/
|
||||
public function clearData($table_name, bool $status)
|
||||
{
|
||||
$prefix = config('database.connections.' . config('database.default'))['prefix'];
|
||||
if (is_string($table_name)) {
|
||||
$clearData = [$table_name];
|
||||
} else {
|
||||
$clearData = $table_name;
|
||||
}
|
||||
foreach ($clearData as $name) {
|
||||
if ($status) {
|
||||
Db::execute('TRUNCATE TABLE ' . $prefix . $name);
|
||||
} else {
|
||||
Db::execute('DELETE FROM' . $prefix . $name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 递归删除文件,只能删除 public/uploads下的文件
|
||||
* @param $dirName
|
||||
* @param bool $subdir
|
||||
*/
|
||||
public function delDirAndFile(string $dirName, $subdir = true)
|
||||
{
|
||||
if (strstr($dirName, 'public/uploads') === false) {
|
||||
return true;
|
||||
}
|
||||
if ($handle = @opendir("$dirName")) {
|
||||
while (false !== ($item = readdir($handle))) {
|
||||
if ($item != "." && $item != "..") {
|
||||
if (is_dir("$dirName/$item"))
|
||||
$this->delDirAndFile("$dirName/$item", false);
|
||||
else
|
||||
@unlink("$dirName/$item");
|
||||
}
|
||||
}
|
||||
closedir($handle);
|
||||
if (!$subdir) @rmdir($dirName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 替换域名
|
||||
* @param string $url
|
||||
* @return mixed
|
||||
*/
|
||||
public function replaceSiteUrl(string $url)
|
||||
{
|
||||
$siteUrl = sys_config('site_url');
|
||||
$siteUrlJosn = str_replace('://', ':\\\/\\\/', $siteUrl);
|
||||
$valueJosn = str_replace('://', ':\\\/\\\/', $url);
|
||||
$prefix = Config::get('database.connections.' . Config::get('database.default') . '.prefix');
|
||||
$sql = [
|
||||
"UPDATE `{$prefix}system_attachment` SET `att_dir` = replace(att_dir ,'{$siteUrl}','{$url}'),`satt_dir` = replace(satt_dir ,'{$siteUrl}','{$url}')",
|
||||
"UPDATE `{$prefix}store_product` SET `image` = replace(image ,'{$siteUrl}','{$url}'),`slider_image` = replace(slider_image ,'{$siteUrlJosn}','{$valueJosn}')",
|
||||
"UPDATE `{$prefix}store_product_attr_value` SET `image` = replace(image ,'{$siteUrl}','{$url}')",
|
||||
"UPDATE `{$prefix}store_seckill` SET `image` = replace(image ,'{$siteUrl}','{$url}'),`images` = replace(images,'{$siteUrlJosn}','{$valueJosn}')",
|
||||
"UPDATE `{$prefix}store_combination` SET `image` = replace(image ,'{$siteUrl}','{$url}'),`images` = replace(images,'{$siteUrlJosn}','{$valueJosn}')",
|
||||
"UPDATE `{$prefix}store_bargain` SET `image` = replace(image ,'{$siteUrl}','{$url}'),`images` = replace(images,'{$siteUrlJosn}','{$valueJosn}')",
|
||||
"UPDATE `{$prefix}system_config` SET `value` = replace(value ,'{$siteUrlJosn}','{$valueJosn}')",
|
||||
"UPDATE `{$prefix}article_category` SET `image` = replace(`image` ,'{$siteUrl}','{$url}')",
|
||||
"UPDATE `{$prefix}article` SET `image_input` = replace(`image_input` ,'{$siteUrl}','{$url}')",
|
||||
"UPDATE `{$prefix}article_content` SET `content` = replace(`content` ,'{$siteUrl}','{$url}')",
|
||||
"UPDATE `{$prefix}store_product_category` SET `pic` = replace(`pic` ,'{$siteUrl}','{$url}')",
|
||||
"UPDATE `{$prefix}system_group_data` SET `value` = replace(value ,'{$siteUrlJosn}','{$valueJosn}')",
|
||||
"UPDATE `{$prefix}store_product_description` SET `description`= replace(description,'{$siteUrl}','{$url}')"
|
||||
];
|
||||
return $this->transaction(function () use ($sql) {
|
||||
try {
|
||||
foreach ($sql as $item) {
|
||||
Db::execute($item);
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
throw new AdminException('替换失败,失败原因:' . $e->getMessage());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 回收站商品彻底删除
|
||||
* @param array $ids 商品ID数组
|
||||
* @return bool
|
||||
*/
|
||||
public function recycleProduct(array $ids)
|
||||
{
|
||||
$product = app()->make(StoreProductServices::class);
|
||||
//清除规格表数据
|
||||
/** @var StoreProductAttrServices $ProductAttr */
|
||||
$productAttr = app()->make(StoreProductAttrServices::class);
|
||||
$productAttr->delete([['product_id', 'in', $ids], ['type', '=', '0']]);
|
||||
|
||||
/** @var StoreProductAttrResultServices $productAttrResult */
|
||||
$productAttrResult = app()->make(StoreProductAttrResultServices::class);
|
||||
$productAttrResult->delete([['product_id', 'in', $ids], ['type', '=', '0']]);
|
||||
|
||||
/** @var StoreProductAttrValueServices $productAttrValue */
|
||||
$productAttrValue = app()->make(StoreProductAttrValueServices::class);
|
||||
$productAttrValue->delete([['product_id', 'in', $ids], ['type', '=', '0']]);
|
||||
|
||||
//删除商品详情
|
||||
/** @var StoreDescriptionServices $productDescription */
|
||||
$productDescription = app()->make(StoreDescriptionServices::class);
|
||||
$productDescription->delete([['product_id', 'in', $ids], ['type', '=', '0']]);
|
||||
|
||||
//删除商品关联数据
|
||||
/** @var StoreProductRelationServices $productRelation */
|
||||
$productRelation = app()->make(StoreProductRelationServices::class);
|
||||
$productRelation->delete([['product_id', 'in', $ids]]);
|
||||
|
||||
//删除商品关联优惠券数据
|
||||
/** @var StoreProductCouponServices $productCoupon */
|
||||
$productCoupon = app()->make(StoreProductCouponServices::class);
|
||||
$productCoupon->delete([['product_id', 'in', $ids]]);
|
||||
|
||||
//删除商品收藏记录
|
||||
/** @var UserRelationServices $productRelation */
|
||||
$productRelation = app()->make(UserRelationServices::class);
|
||||
$productRelation->delete([['relation_id', 'in', $ids], ['category', '=', UserRelationServices::CATEGORY_PRODUCT]]);
|
||||
|
||||
//删除商品的评论
|
||||
/** @var StoreProductReplyServices $productReply */
|
||||
$productReply = app()->make(StoreProductReplyServices::class);
|
||||
$productReply->delete([['product_id', 'in', $ids]]);
|
||||
|
||||
//删除帖子里对应商品
|
||||
$communityRelevanceServices = app()->make(CommunityRelevanceServices::class);
|
||||
$communityRelevanceServices->search(['right_id' => $ids, 'type' => CommunityRelevanceServices::TYPE_COMMUNITY_PRODUCT])->delete();
|
||||
|
||||
$product->search(['id' => $ids])->delete();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
124
app/services/system/SystemDatabackupServices.php
Normal file
124
app/services/system/SystemDatabackupServices.php
Normal file
@@ -0,0 +1,124 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\services\system;
|
||||
|
||||
|
||||
use app\services\BaseServices;
|
||||
use crmeb\services\MysqlBackupService;
|
||||
use think\facade\Db;
|
||||
use think\facade\Env;
|
||||
|
||||
/**
|
||||
* 数据库备份
|
||||
* Class SystemDatabackupServices
|
||||
* @package app\services\system
|
||||
*/
|
||||
class SystemDatabackupServices extends BaseServices
|
||||
{
|
||||
|
||||
/**
|
||||
*
|
||||
* @var MysqlBackupService
|
||||
*/
|
||||
protected $dbBackup;
|
||||
|
||||
/**
|
||||
* 构造方法
|
||||
* SystemDatabackupServices constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->dbBackup = app()->make(MysqlBackupService::class, [[
|
||||
//数据库备份卷大小
|
||||
'compress' => 1,
|
||||
//数据库备份文件是否启用压缩 0不压缩 1 压缩
|
||||
'level' => 5,
|
||||
]]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取数据库列表
|
||||
* @return array
|
||||
* @throws \think\db\exception\BindParamException
|
||||
*/
|
||||
public function getDataList()
|
||||
{
|
||||
$list = $this->dbBackup->dataList();
|
||||
$count = count($list);
|
||||
return compact('list', 'count');
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取表详情
|
||||
* @param string $tablename
|
||||
* @return array
|
||||
*/
|
||||
public function getRead(string $tablename)
|
||||
{
|
||||
$database = Env::get("database.database");
|
||||
$list = Db::query("select * from information_schema.columns where table_name = '" . $tablename . "' and table_schema = '" . $database . "'");
|
||||
$count = count($list);
|
||||
foreach ($list as $key => $f) {
|
||||
$list[$key]['EXTRA'] = ($f['EXTRA'] == 'auto_increment' ? '是' : ' ');
|
||||
}
|
||||
return compact('list', 'count');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return MysqlBackupService
|
||||
*/
|
||||
public function getDbBackup()
|
||||
{
|
||||
return $this->dbBackup;
|
||||
}
|
||||
|
||||
/**
|
||||
* 备份表
|
||||
* @param string $tables
|
||||
* @return string
|
||||
* @throws \think\db\exception\BindParamException
|
||||
*/
|
||||
public function backup(string $tables)
|
||||
{
|
||||
$tables = explode(',', $tables);
|
||||
$data = '';
|
||||
ini_set ("memory_limit","-1");
|
||||
foreach ($tables as $t) {
|
||||
$res = $this->dbBackup->backup($t, 0);
|
||||
if ($res == false && $res != 0) {
|
||||
$data .= $t . '|';
|
||||
}
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取备份列表
|
||||
* @return array
|
||||
*/
|
||||
public function getBackup()
|
||||
{
|
||||
$files = $this->dbBackup->fileList();
|
||||
$data = [];
|
||||
foreach ($files as $key => $t) {
|
||||
$data[$key]['filename'] = $t['filename'];
|
||||
$data[$key]['part'] = $t['part'];
|
||||
$data[$key]['size'] = $t['size'] . 'B';
|
||||
$data[$key]['compress'] = $t['compress'];
|
||||
$data[$key]['backtime'] = $key;
|
||||
$data[$key]['time'] = $t['time'];
|
||||
}
|
||||
krsort($data);//根据时间降序
|
||||
return ['count' => count($data), 'list' => array_values($data)];
|
||||
}
|
||||
|
||||
}
|
||||
76
app/services/system/SystemMenusRelevanceServices.php
Normal file
76
app/services/system/SystemMenusRelevanceServices.php
Normal file
@@ -0,0 +1,76 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\services\system;
|
||||
|
||||
use app\dao\system\SystemMenusRelevanceDao;
|
||||
use app\services\BaseServices;
|
||||
use crmeb\services\CacheService;
|
||||
use think\annotation\Inject;
|
||||
|
||||
/**
|
||||
* 权限菜单关联
|
||||
* Class SystemMenusRelevanceServices
|
||||
* @package app\services\system
|
||||
* @mixin SystemMenusRelevanceDao
|
||||
*/
|
||||
class SystemMenusRelevanceServices extends BaseServices
|
||||
{
|
||||
|
||||
/**
|
||||
* @var SystemMenusRelevanceDao
|
||||
*/
|
||||
#[Inject]
|
||||
protected SystemMenusRelevanceDao $dao;
|
||||
|
||||
/**
|
||||
* 添加关键词
|
||||
* @param $menuId
|
||||
* @param $data
|
||||
* @return true
|
||||
* @throws \ReflectionException
|
||||
* User: liusl
|
||||
* DateTime: 2024/12/25 上午10:04
|
||||
*/
|
||||
public function updateData($menuId, $data)
|
||||
{
|
||||
$haveData = $this->search(['menu_id' => $menuId])->column('keyword');
|
||||
|
||||
$delData = array_diff($haveData, $data);
|
||||
$newData = array_diff($data, $haveData);
|
||||
|
||||
if ($delData) {
|
||||
$this->dao->delete(['menu_id' => $menuId, 'keyword' => $delData]);
|
||||
}
|
||||
|
||||
if ($newData) {
|
||||
$newData = array_map(function ($item) use ($menuId) {
|
||||
return ['menu_id' => $menuId, 'keyword' => $item];
|
||||
}, $newData);
|
||||
$this->dao->saveAll($newData);
|
||||
}
|
||||
CacheService::redisHandler('system_menus')->clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取关键词
|
||||
* @param $menuId
|
||||
* @return array
|
||||
* @throws \ReflectionException
|
||||
* User: liusl
|
||||
* DateTime: 2024/12/25 上午10:04
|
||||
*/
|
||||
public function getKeyword($menuId): array
|
||||
{
|
||||
return $this->search(['menu_id' => $menuId])->column('keyword');
|
||||
}
|
||||
}
|
||||
374
app/services/system/SystemMenusServices.php
Normal file
374
app/services/system/SystemMenusServices.php
Normal file
@@ -0,0 +1,374 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\services\system;
|
||||
|
||||
use app\dao\system\SystemMenusDao;
|
||||
use app\services\BaseServices;
|
||||
use crmeb\exceptions\AdminException;
|
||||
use crmeb\services\FormBuilder as Form;
|
||||
use crmeb\utils\Arr;
|
||||
use think\annotation\Inject;
|
||||
|
||||
/**
|
||||
* 权限菜单
|
||||
* Class SystemMenusServices
|
||||
* @package app\services\system
|
||||
* @mixin SystemMenusDao
|
||||
*/
|
||||
class SystemMenusServices extends BaseServices
|
||||
{
|
||||
|
||||
/**
|
||||
* @var SystemMenusDao
|
||||
*/
|
||||
#[Inject]
|
||||
protected SystemMenusDao $dao;
|
||||
|
||||
/**
|
||||
* 获取菜单没有被修改器修改的数据
|
||||
* @param $menusList
|
||||
* @return array
|
||||
*/
|
||||
public function getMenusData($menusList)
|
||||
{
|
||||
$data = [];
|
||||
foreach ($menusList as $item) {
|
||||
// $item['expand'] = true;
|
||||
$item['selected'] = false;
|
||||
$item['title'] = $item['menu_name'];
|
||||
$data[] = $item->getData();
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取后台权限菜单和权限
|
||||
* @param $rouleId
|
||||
* @param int $level
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getMenusList($rouleId, int $level, int $type = 1)
|
||||
{
|
||||
/** @var SystemRoleServices $systemRoleServices */
|
||||
$systemRoleServices = app()->make(SystemRoleServices::class);
|
||||
$rules = $systemRoleServices->getRoleArray(['status' => 1, 'id' => $rouleId], 'rules');
|
||||
$rulesStr = Arr::unique($rules);
|
||||
$menusList = $this->dao->getMenusRoule(['type' => $type, 'route' => $level ? $rulesStr : '']);
|
||||
$unique = $this->dao->getMenusUnique(['type' => $type, 'unique' => $level ? $rulesStr : '']);
|
||||
return [Arr::getMenuIviewList($this->getMenusData($menusList)), $unique];
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取后台菜单树型结构列表
|
||||
* @param array $where
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getList(array $where)
|
||||
{
|
||||
$menusList = $this->dao->getMenusList($where);
|
||||
$menusList = $this->getMenusData($menusList);
|
||||
return get_tree_children($menusList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取form表单所需要的所要的菜单列表
|
||||
* @return array[]
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
protected function getFormSelectMenus()
|
||||
{
|
||||
$menuList = $this->dao->getMenusRoule(['is_del' => 0], ['id', 'pid', 'menu_name']);
|
||||
$list = get_tree_children($this->getMenusData($menuList), '0', 'pid', 'id');
|
||||
$menus = [['value' => 0, 'label' => '顶级按钮']];
|
||||
foreach ($list as $menu) {
|
||||
$menus[] = ['value' => $menu['id'], 'label' => $menu['html'] . $menu['menu_name']];
|
||||
}
|
||||
return $menus;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
protected function getFormCascaderMenus(int $value = 0, int $type = 1)
|
||||
{
|
||||
$menuList = $this->dao->getMenusRoule(['is_del' => 0, 'type' => $type], ['id as value', 'pid', 'menu_name as label']);
|
||||
$menuList = $this->getMenusData($menuList);
|
||||
if ($value) {
|
||||
$data = get_tree_value($menuList, $value);
|
||||
} else {
|
||||
$data = [];
|
||||
}
|
||||
return [get_tree_children($menuList, 'children', 'value'), array_reverse($data)];
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建权限规格生表单
|
||||
* @param array $formData
|
||||
* @return mixed
|
||||
* @throws \FormBuilder\Exception\FormBuilderException
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function createMenusForm(array $formData = [], int $type = 1)
|
||||
{
|
||||
$field[] = Form::hidden('type', $type);
|
||||
$field[] = Form::input('menu_name', '按钮名称', $formData['menu_name'] ?? '')->required('按钮名称必填');
|
||||
// $field[] = Form::select('pid', '父级id', $formData['pid'] ?? 0)->setOptions($this->getFormSelectMenus())->filterable(1);
|
||||
$field[] = Form::input('menu_path', '路由名称', $formData['menu_path'] ?? '')->placeholder('请输入前台跳转路由地址')->required('请填写前台路由地址');
|
||||
$field[] = Form::input('unique_auth', '权限标识', $formData['unique_auth'] ?? '')->placeholder('不填写则后台自动生成');
|
||||
$params = $formData['params'] ?? '';
|
||||
$field[] = Form::input('params', '参数', is_array($params) ? '' : $params)->placeholder('举例:a/123/b/234');
|
||||
$field[] = Form::frameInput('icon', '图标', $this->url('admin/widget.widgets/icon', ['fodder' => 'icon']), $formData['icon'] ?? '')->icon('md-add')->height('500px');
|
||||
$field[] = Form::number('sort', '排序', (int)($formData['sort'] ?? 0))->min(0);
|
||||
$field[] = Form::radio('auth_type', '类型', $formData['auth_type'] ?? 1)->options([['value' => 2, 'label' => '接口'], ['value' => 1, 'label' => '菜单(菜单只显示三级)']]);
|
||||
$field[] = Form::radio('is_show', '状态', $formData['is_show'] ?? 1)->options([['value' => 0, 'label' => '关闭'], ['value' => 1, 'label' => '开启']]);
|
||||
$field[] = Form::radio('is_show_path', '是否为前端隐藏菜单', $formData['is_show_path'] ?? 0)->options([['value' => 1, 'label' => '是'], ['value' => 0, 'label' => '否']]);
|
||||
[$menuList, $data] = $this->getFormCascaderMenus((int)($formData['pid'] ?? 0), $type);
|
||||
$field[] = Form::cascader('menu_list', '父级id', $data)->data($menuList)->filterable(true);
|
||||
return $field;
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增权限表单
|
||||
* @return array
|
||||
* @throws \FormBuilder\Exception\FormBuilderException
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function createMenus(int $type = 1)
|
||||
{
|
||||
return create_form('添加权限', $this->createMenusForm([], $type), $this->url('/setting/save'));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改权限菜单
|
||||
* @param int $id
|
||||
* @return array
|
||||
* @throws \FormBuilder\Exception\FormBuilderException
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function updateMenus(int $id)
|
||||
{
|
||||
$menusInfo = $this->dao->get($id);
|
||||
if (!$menusInfo) {
|
||||
throw new AdminException('数据不存在');
|
||||
}
|
||||
$menusInfo = $menusInfo->getData();
|
||||
return create_form('修改权限', $this->createMenusForm($menusInfo, $menusInfo['type'] ?? 1), $this->url('/setting/update/' . $id), 'PUT');
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取一条数据
|
||||
* @param int $id
|
||||
* @return mixed
|
||||
*/
|
||||
public function find(int $id)
|
||||
{
|
||||
$menusInfo = $this->dao->get($id);
|
||||
if (!$menusInfo) {
|
||||
throw new AdminException('数据不存在');
|
||||
}
|
||||
$menu = $menusInfo->getData();
|
||||
$menu['pid'] = (int)$menu['pid'];
|
||||
$menu['auth_type'] = (int)$menu['auth_type'];
|
||||
$menu['is_header'] = (int)$menu['is_header'];
|
||||
$menu['is_show'] = (int)$menu['is_show'];
|
||||
$menu['is_show_path'] = (int)$menu['is_show_path'];
|
||||
if (!$menu['path']) {
|
||||
[$menuList, $data] = $this->getFormCascaderMenus($menu['pid']);
|
||||
$menu['path'] = $data;
|
||||
} else {
|
||||
$menu['path'] = explode('/', $menu['path']);
|
||||
if (is_array($menu['path'])) {
|
||||
$menu['path'] = array_map(function ($item) {
|
||||
return (int)$item;
|
||||
}, $menu['path']);
|
||||
}
|
||||
}
|
||||
return $menu;
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除菜单
|
||||
* @param int $id
|
||||
* @return mixed
|
||||
*/
|
||||
public function delete(int $id)
|
||||
{
|
||||
if ($this->dao->count(['pid' => $id])) {
|
||||
throw new AdminException('请先删除改菜单下的子菜单');
|
||||
}
|
||||
return $this->dao->delete($id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取添加身份规格
|
||||
* @param $roles
|
||||
* @param int $type
|
||||
* @param int $is_show
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getMenus($roles, int $type = 1, int $is_show = 1): array
|
||||
{
|
||||
$field = ['menu_name', 'pid', 'id'];
|
||||
$where = ['is_del' => 0, 'type' => $type];
|
||||
if ($is_show) $where['is_show'] = 1;
|
||||
if (!$roles) {
|
||||
$menus = $this->dao->getMenusRoule($where, $field);
|
||||
} else {
|
||||
/** @var SystemRoleServices $service */
|
||||
$service = app()->make(SystemRoleServices::class);
|
||||
//拼接有长度限制
|
||||
// $ids = $service->value([['id', 'in', $roles]], 'GROUP_CONCAT(rules) as ids');
|
||||
$roles = is_string($roles) ? explode(',', $roles) : $roles;
|
||||
$ids = $service->getRoleIds($roles);
|
||||
$menus = $this->dao->getMenusRoule(['rule' => $ids] + $where, $field);
|
||||
}
|
||||
return $this->tidyMenuTier(false, $menus);
|
||||
}
|
||||
|
||||
/**
|
||||
* 组合菜单数据
|
||||
* @param bool $adminFilter
|
||||
* @param $menusList
|
||||
* @param int $pid
|
||||
* @param array $navList
|
||||
* @return array
|
||||
*/
|
||||
public function tidyMenuTier(bool $adminFilter = false, $menusList = [], int $pid = 0, array $navList = []): array
|
||||
{
|
||||
foreach ($menusList as $k => $menu) {
|
||||
$menu = $menu->getData();
|
||||
$menu['title'] = $menu['menu_name'];
|
||||
unset($menu['menu_name']);
|
||||
if ($menu['pid'] == $pid) {
|
||||
unset($menusList[$k]);
|
||||
$menu['children'] = $this->tidyMenuTier($adminFilter, $menusList, $menu['id']);
|
||||
if ($pid == 0 && !count($menu['children'])) continue;
|
||||
if ($menu['children']) $menu['expand'] = true;
|
||||
$navList[] = $menu;
|
||||
}
|
||||
}
|
||||
return $navList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取菜单选择列表
|
||||
* @param int $type 菜单类型
|
||||
* @param string $keyword 搜索关键词
|
||||
* @return array
|
||||
*/
|
||||
public function getSelectList(int $type = 1, string $keyword = '')
|
||||
{
|
||||
// 获取搜索列表
|
||||
$_list = $this->dao->getSearchList($type, $keyword);
|
||||
$list = [];
|
||||
$ids = [];
|
||||
foreach ($_list as $key => $v) {
|
||||
$menu = json_decode($v, true);
|
||||
$pid = $v->getData('pid');
|
||||
$menu['p_id'] = $pid;
|
||||
$list[$key] = $menu;
|
||||
|
||||
$path = explode('/', $menu['path']);
|
||||
$ids = array_merge($ids, $path);
|
||||
}
|
||||
|
||||
// 去除重复的id
|
||||
$ids = array_filter(array_unique($ids));
|
||||
|
||||
// 合并PID列表查询
|
||||
$pidList = [];
|
||||
if ($ids) {
|
||||
$_pidList = $this->dao->search(['id' => $ids])->select();
|
||||
foreach ($_pidList as $key => $v) {
|
||||
$menu = json_decode($v, true);
|
||||
$pid = $v->getData('pid');
|
||||
$menu['p_id'] = $pid;
|
||||
$pidList[$key] = $menu;
|
||||
}
|
||||
}
|
||||
|
||||
// 合并pidList到原始列表
|
||||
$list = array_merge($list, $pidList);
|
||||
|
||||
// 获取符合条件的counts(当前显示的有效菜单项)
|
||||
$counts = $this->dao->getColumn([
|
||||
'is_show' => 1,
|
||||
'auth_type' => 1,
|
||||
'is_del' => 0,
|
||||
'is_show_path' => 0,
|
||||
'keywords' => $keyword
|
||||
], 'pid', '', true);
|
||||
|
||||
// 获取p_counts(菜单路径中有效的PID)
|
||||
$p_counts = $this->dao->getColumn([
|
||||
'id' => $ids
|
||||
], 'pid', '', true);
|
||||
|
||||
// 合并counts和p_counts
|
||||
$counts = array_merge($counts, $p_counts);
|
||||
|
||||
// 对菜单列表进行排序处理
|
||||
$sortList = $this->sortListTier($list);
|
||||
|
||||
// 返回最终结果
|
||||
$data = [];
|
||||
foreach ($sortList as $item) {
|
||||
if (!in_array($item['id'], $counts)) {
|
||||
$data[$item['id']] = $item;
|
||||
$data[$item['id']]['menu_name'] = isset($item['p_name']) && $item['p_name'] ? $item['p_name'] : $item['menu_name'];
|
||||
$data[$item['id']]['type'] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 递归排序菜单层级并拼接父级名称
|
||||
* @param array $menuData 菜单数据引用
|
||||
* @param int $pid 父级ID
|
||||
* @param string $p_name 父级名称
|
||||
* @return array
|
||||
*/
|
||||
public function sortListTier(&$menuData, $pid = 0, $p_name = '')
|
||||
{
|
||||
foreach ($menuData as &$menu) {
|
||||
if ($menu['p_id'] == $pid) {
|
||||
// 拼接父级名称
|
||||
$menu['p_name'] = $p_name ? $p_name . '-' . $menu['menu_name'] : $menu['menu_name'];
|
||||
// 递归查找子菜单
|
||||
$this->sortListTier($menuData, $menu['id'], $menu['p_name']);
|
||||
}
|
||||
}
|
||||
return $menuData;
|
||||
}
|
||||
}
|
||||
188
app/services/system/SystemRecommendServices.php
Normal file
188
app/services/system/SystemRecommendServices.php
Normal file
@@ -0,0 +1,188 @@
|
||||
<?php
|
||||
|
||||
namespace app\services\system;
|
||||
|
||||
use app\dao\system\SystemRecommendDao;
|
||||
use app\services\BaseServices;
|
||||
use app\services\order\StoreCartServices;
|
||||
use app\services\product\product\StoreProductLogServices;
|
||||
use app\services\product\product\StoreProductServices;
|
||||
use app\services\user\UserRelationServices;
|
||||
use crmeb\exceptions\AdminException;
|
||||
use think\annotation\Inject;
|
||||
|
||||
class SystemRecommendServices extends BaseServices
|
||||
{
|
||||
/**
|
||||
* @var SystemRecommendDao
|
||||
*/
|
||||
#[Inject]
|
||||
protected SystemRecommendDao $dao;
|
||||
|
||||
/**
|
||||
* 获取推荐配置列表
|
||||
* @param array $where 查询条件
|
||||
* @return array
|
||||
*/
|
||||
public function getRecommendList($where = [])
|
||||
{
|
||||
[$page, $limit] = $this->getPageValue();
|
||||
$list = $this->dao->recommendList($where, $page, $limit, 'id,name,title,pic,type,update_time,status', 'id asc');
|
||||
foreach ($list as &$item) {
|
||||
$item['update_time'] = date('Y-m-d H:i:s', $item['update_time']);
|
||||
}
|
||||
$count = $this->dao->recommendCount($where);
|
||||
return compact('list', 'count');
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取推荐配置详情
|
||||
* @param int $id 推荐ID
|
||||
* @return array
|
||||
*/
|
||||
public function getRecommendInfo($id)
|
||||
{
|
||||
$info = $this->dao->getOne(['id' => $id]);
|
||||
if ($info) {
|
||||
$info = $info->toArray();
|
||||
$info['specify_recommend_content'] = json_decode($info['specify_recommend_content'], true);
|
||||
$info['personality_recommend_content'] = json_decode($info['personality_recommend_content'], true);
|
||||
$info['sort_recommend_content'] = json_decode($info['sort_recommend_content'], true);
|
||||
} else {
|
||||
$info = [];
|
||||
}
|
||||
return $info;
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑推荐标题
|
||||
* @param int $id 推荐ID
|
||||
* @param string $title 标题
|
||||
* @return bool
|
||||
*/
|
||||
public function editRecommendTitle($id, $title)
|
||||
{
|
||||
$this->dao->update($id, ['title' => $title]);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存推荐配置
|
||||
* @param int $id 推荐ID
|
||||
* @param array $data 配置数据
|
||||
* @return bool
|
||||
* @throws AdminException
|
||||
*/
|
||||
public function saveRecommend($id, $data)
|
||||
{
|
||||
$data['specify_recommend_content'] = json_encode($data['specify_recommend_content']);
|
||||
$data['personality_recommend_content'] = json_encode($data['personality_recommend_content']);
|
||||
$data['sort_recommend_content'] = json_encode($data['sort_recommend_content']);
|
||||
$data['update_time'] = time();
|
||||
if ($id) {
|
||||
$res = $this->dao->update($id, $data);
|
||||
} else {
|
||||
$res = $this->dao->save($data);
|
||||
}
|
||||
if (!$res) {
|
||||
throw new AdminException('保存失败');
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置推荐状态
|
||||
* @param int $id 推荐ID
|
||||
* @param int $status 状态
|
||||
* @return bool
|
||||
*/
|
||||
public function setRecommendStatus($id, $status)
|
||||
{
|
||||
$data = [
|
||||
'status' => $status,
|
||||
'update_time' => time(),
|
||||
];
|
||||
return $this->dao->update((int)$id, $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取推荐商品ID列表
|
||||
* @param int $type 推荐类型
|
||||
* @param int $uid 用户ID
|
||||
* @return array
|
||||
*/
|
||||
public function getRecommendProductIds($type, $uid = 0)
|
||||
{
|
||||
$info = $this->dao->getOne(['type' => $type]);
|
||||
if (!$info || !$info['status']) return ['为您推荐', []];
|
||||
$info = $info->toArray();
|
||||
$specifyProductIds = $personalityProductIds = $sortProductIds = [];
|
||||
$info['specify_recommend_content'] = json_decode($info['specify_recommend_content'], true);
|
||||
$info['personality_recommend_content'] = json_decode($info['personality_recommend_content'], true);
|
||||
$info['sort_recommend_content'] = json_decode($info['sort_recommend_content'], true);
|
||||
if ($info['specify_recommend_status'] == 1) {
|
||||
$specifyProductIds = array_column($info['specify_recommend_content'], 'product_id');
|
||||
}
|
||||
if ($uid != 0 && $info['personality_recommend_status'] == 1) {
|
||||
$productLogServices = app()->make(StoreProductLogServices::class);
|
||||
foreach ($info['personality_recommend_content'] as $item) {
|
||||
switch ($item['value']) {
|
||||
case 1:
|
||||
$cartProductIds = $productLogServices->getColumn([['uid', '=', $uid], ['type', '=', 'cart'], ['add_time', '>', strtotime('-30 days')]], 'product_id');
|
||||
$personalityProductIds = array_merge($personalityProductIds, array_diff($cartProductIds, $personalityProductIds));
|
||||
break;
|
||||
case 2:
|
||||
$relationProductIds = $productLogServices->getColumn([['uid', '=', $uid], ['type', '=', 'collect'], ['add_time', '>', strtotime('-30 days')]], 'product_id');
|
||||
$personalityProductIds = array_merge($personalityProductIds, array_diff($relationProductIds, $personalityProductIds));
|
||||
break;
|
||||
case 3:
|
||||
$visitProductIds = $productLogServices->getColumn([['uid', '=', $uid], ['type', '=', 'visit'], ['add_time', '>', strtotime('-30 days')]], 'product_id');
|
||||
$personalityProductIds = array_merge($personalityProductIds, array_diff($visitProductIds, $personalityProductIds));
|
||||
break;
|
||||
case 4:
|
||||
$payProductIds = $productLogServices->getColumn([['uid', '=', $uid], ['type', '=', 'pay'], ['add_time', '>', strtotime('-30 days')]], 'product_id');
|
||||
$personalityProductIds = array_merge($personalityProductIds, array_diff($payProductIds, $personalityProductIds));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($info['sort_recommend_status'] == 1) {
|
||||
$productLogServices = app()->make(StoreProductLogServices::class);
|
||||
$productServices = app()->make(StoreProductServices::class);
|
||||
foreach ($info['sort_recommend_content'] as $item) {
|
||||
switch ($item['value']) {
|
||||
case 1:
|
||||
$salesProductIds = [];
|
||||
$salesProductList = $productLogServices->getProductIds('pay', 'product_id, COUNT(*) as pay_count', 'pay_count desc', 20);
|
||||
if (count($salesProductList)) $salesProductIds = array_column($salesProductList, 'product_id');
|
||||
$sortProductIds = array_merge($sortProductIds, array_diff($salesProductIds, $sortProductIds));
|
||||
break;
|
||||
case 2:
|
||||
$payPriceProductIds = [];
|
||||
$payPriceProductList = $productLogServices->getProductIds('pay', 'product_id, SUM(pay_price) as total_pay_price', 'total_pay_price desc', 20);
|
||||
if (count($payPriceProductList)) $payPriceProductIds = array_column($payPriceProductList, 'product_id');
|
||||
$sortProductIds = array_merge($sortProductIds, array_diff($payPriceProductIds, $sortProductIds));
|
||||
break;
|
||||
case 3:
|
||||
$addTimeProductIds = $productServices->getProductIds(['is_show' => 1, 'is_del' => 0, 'is_verify' => 1], 'product_id, add_time', 'add_time desc', 20);
|
||||
$sortProductIds = array_merge($sortProductIds, array_diff($addTimeProductIds, $sortProductIds));
|
||||
break;
|
||||
case 4:
|
||||
$starProductIds = $productServices->getProductIds(['is_show' => 1, 'is_del' => 0, 'is_verify' => 1], 'product_id, star', 'star desc, add_time desc', 20);
|
||||
$sortProductIds = array_merge($sortProductIds, array_diff($starProductIds, $sortProductIds));
|
||||
break;
|
||||
case 5:
|
||||
$visitProductIds = [];
|
||||
$visitProductList = $productLogServices->getProductIds('visit', 'product_id, COUNT(*) as visit_count', 'visit_count desc', 20);
|
||||
if (count($visitProductList)) $visitProductIds = array_column($visitProductList, 'product_id');
|
||||
$sortProductIds = array_merge($sortProductIds, array_diff($visitProductIds, $sortProductIds));
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
$productIds = array_merge($specifyProductIds, array_diff($personalityProductIds, $specifyProductIds));
|
||||
$productIds = array_merge($productIds, array_diff($sortProductIds, $productIds));
|
||||
return [$info['title'], $productIds];
|
||||
}
|
||||
}
|
||||
182
app/services/system/SystemRoleServices.php
Normal file
182
app/services/system/SystemRoleServices.php
Normal file
@@ -0,0 +1,182 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\services\system;
|
||||
|
||||
|
||||
use app\Request;
|
||||
use app\services\BaseServices;
|
||||
use app\dao\system\SystemRoleDao;
|
||||
use app\services\store\SystemStoreStaffServices;
|
||||
use crmeb\exceptions\AuthException;
|
||||
use crmeb\utils\ApiErrorCode;
|
||||
use crmeb\services\CacheService;
|
||||
use think\annotation\Inject;
|
||||
|
||||
|
||||
/**
|
||||
* Class SystemRoleServices
|
||||
* @package app\services\system
|
||||
* @mixin SystemRoleDao
|
||||
*/
|
||||
class SystemRoleServices extends BaseServices
|
||||
{
|
||||
|
||||
/**
|
||||
* 当前管理员权限缓存前缀
|
||||
*/
|
||||
const ADMIN_RULES_LEVEL = 'Admin_rules_level_';
|
||||
|
||||
/**
|
||||
* @var SystemRoleDao
|
||||
*/
|
||||
#[Inject]
|
||||
protected SystemRoleDao $dao;
|
||||
|
||||
/**
|
||||
* 获取权限
|
||||
* @return mixed
|
||||
*/
|
||||
public function getRoleArray(array $where = [], string $field = '', string $key = '')
|
||||
{
|
||||
return $this->dao->getRoule($where, $field, $key);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取表单所需的权限名称列表
|
||||
* @param int $level
|
||||
* @param int $type
|
||||
* @param int $relation_id
|
||||
* @return array
|
||||
*/
|
||||
public function getRoleFormSelect(int $level, int $type = 0, int $relation_id = 0)
|
||||
{
|
||||
$list = $this->getRoleArray(['level' => $level, 'type' => $type, 'relation_id' => $relation_id, 'status' => 1]);
|
||||
$options = [];
|
||||
foreach ($list as $id => $roleName) {
|
||||
$options[] = ['label' => $roleName, 'value' => $id];
|
||||
}
|
||||
return $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* 身份管理列表
|
||||
* @param array $where
|
||||
* @return array
|
||||
*/
|
||||
public function getRoleList(array $where)
|
||||
{
|
||||
[$page, $limit] = $this->getPageValue();
|
||||
$list = $this->dao->getRouleList($where, $page, $limit);
|
||||
$count = $this->dao->count($where);
|
||||
/** @var SystemMenusServices $service */
|
||||
$service = app()->make(SystemMenusServices::class);
|
||||
foreach ($list as &$item) {
|
||||
$item['rules'] = implode(',', array_merge($service->column(['id' => $item['rules']], 'menu_name', 'id')));
|
||||
}
|
||||
return compact('count', 'list');
|
||||
}
|
||||
|
||||
/**
|
||||
* 后台验证权限
|
||||
* @param Request $request
|
||||
*/
|
||||
public function verifiAuth(Request $request)
|
||||
{
|
||||
$rule = str_replace('adminapi/', '', trim(strtolower($request->rule()->getRule())));
|
||||
if (in_array($rule, ['setting/admin/logout', 'menuslist'])) {
|
||||
return true;
|
||||
}
|
||||
$method = trim(strtolower($request->method()));
|
||||
$auth = $this->getAllRoles(2);
|
||||
//验证访问接口是否存在
|
||||
if (!in_array($method . '@@' . $rule, array_map(function ($item) {
|
||||
return trim(strtolower($item['methods'])) . '@@' . trim(strtolower(str_replace(' ', '', $item['api_url'])));
|
||||
}, $auth))) {
|
||||
// throw new AuthException(ApiErrorCode::ERR_AUTH);
|
||||
return true;
|
||||
}
|
||||
$auth = $this->getRolesByAuth($request->adminInfo()['roles'], 2);
|
||||
//验证访问接口是否有权限
|
||||
if ($auth && empty(array_filter($auth, function ($item) use ($rule, $method) {
|
||||
if (trim(strtolower($item['api_url'])) === $rule && $method === trim(strtolower($item['methods'])))
|
||||
return true;
|
||||
}))) {
|
||||
// throw new AuthException(ApiErrorCode::ERR_AUTH);
|
||||
throw new AuthException(ApiErrorCode::ERR_AUTH);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有权限
|
||||
* @param int $auth_type
|
||||
* @param int $type
|
||||
* @param string $cachePrefix
|
||||
* @return array|bool|mixed|null
|
||||
*/
|
||||
public function getAllRoles(int $auth_type = 1, int $type = 1, string $cachePrefix = self::ADMIN_RULES_LEVEL)
|
||||
{
|
||||
$cacheName = md5($cachePrefix . '_' . $auth_type . '_' . $type . '_ALl');
|
||||
return CacheService::redisHandler('system_menus')->remember($cacheName, function () use ($auth_type, $type) {
|
||||
/** @var SystemMenusServices $menusService */
|
||||
$menusService = app()->make(SystemMenusServices::class);
|
||||
return $menusService->getColumn([['auth_type', '=', $auth_type], ['type', '=', $type]], 'api_url,methods');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定权限
|
||||
* @param array $rules
|
||||
* @param int $auth_type
|
||||
* @param int $type
|
||||
* @param string $cachePrefix
|
||||
* @return array|bool|mixed|null
|
||||
*/
|
||||
public function getRolesByAuth(array $rules, int $auth_type = 1, int $type = 1, string $cachePrefix = self::ADMIN_RULES_LEVEL)
|
||||
{
|
||||
if (empty($rules)) return [];
|
||||
$cacheName = md5($cachePrefix . '_' . $auth_type . '_' . $type . '_' . implode('_', $rules));
|
||||
return CacheService::redisHandler('system_menus')->remember($cacheName, function () use ($rules, $auth_type, $type) {
|
||||
/** @var SystemMenusServices $menusService */
|
||||
$menusService = app()->make(SystemMenusServices::class);
|
||||
return $menusService->getColumn([['id', 'IN', $this->getRoleIds($rules)], ['auth_type', '=', $auth_type], ['type', '=', $type]], 'api_url,methods');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取权限id
|
||||
* @param array $rules
|
||||
* @return array
|
||||
*/
|
||||
public function getRoleIds(array $rules)
|
||||
{
|
||||
$rules = $this->dao->getColumn([['id', 'IN', $rules], ['status', '=', '1']], 'rules', 'id');
|
||||
return array_unique(explode(',', implode(',', $rules)));
|
||||
}
|
||||
|
||||
/**
|
||||
* 门店角色状态更改改变角色下店员、管理员状态
|
||||
* @param int $store_id
|
||||
* @param int $role_id
|
||||
* @param $status
|
||||
* @return mixed
|
||||
*/
|
||||
public function setStaffStatus(int $store_id, int $role_id, $status)
|
||||
{
|
||||
/** @var SystemStoreStaffServices $storeStaffServices */
|
||||
$storeStaffServices = app()->make(SystemStoreStaffServices::class);
|
||||
if ($status) {
|
||||
return $storeStaffServices->update(['store_id' => $store_id, 'roles' => $role_id, 'is_del' => 0, 'status' => 0], ['status' => 1]);
|
||||
} else {
|
||||
return $storeStaffServices->update(['store_id' => $store_id, 'roles' => $role_id, 'status' => 1], ['status' => 0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
110
app/services/system/SystemSignRewardServices.php
Normal file
110
app/services/system/SystemSignRewardServices.php
Normal file
@@ -0,0 +1,110 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\services\system;
|
||||
|
||||
|
||||
use app\services\BaseServices;
|
||||
use app\dao\system\SystemSignRewardDao;
|
||||
use crmeb\exceptions\AdminException;
|
||||
use crmeb\services\FormBuilder as Form;
|
||||
use think\annotation\Inject;
|
||||
use think\facade\Route as Url;
|
||||
|
||||
|
||||
/**
|
||||
* Class SystemSignRewardServices
|
||||
* @package app\services\system
|
||||
* @mixin SystemSignRewardDao
|
||||
*/
|
||||
class SystemSignRewardServices extends BaseServices
|
||||
{
|
||||
|
||||
/**
|
||||
* @var SystemSignRewardDao
|
||||
*/
|
||||
#[Inject]
|
||||
protected SystemSignRewardDao $dao;
|
||||
|
||||
/**
|
||||
* 签到奖励列表
|
||||
* @param $type
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getList($type = 0)
|
||||
{
|
||||
[$page, $limit] = $this->getPageValue();
|
||||
$list = $this->dao->selectList(['type' => $type], '*', $page, $limit, 'days asc');
|
||||
$count = $this->dao->count(['type' => $type]);
|
||||
return compact('list', 'count');
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增修改签到奖励表单
|
||||
* @param $id
|
||||
* @param $type
|
||||
* @return mixed
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function rewardsForm($id = 0, $type = 0)
|
||||
{
|
||||
$info = $this->dao->get($id);
|
||||
if ($info) $type = $info['type'];
|
||||
$form[] = Form::hidden('type', $type);
|
||||
$form[] = Form::number('days', $type == 1 ? '累积签到天数:' : '连续签到天数:', (int)($info['days'] ?? 0))->max(sys_config('sign_mode') == 1 ? 7 : 30);
|
||||
$form[] = Form::number('point', '赠送积分:', (int)($info['point'] ?? 0))->max(999)->min(0);
|
||||
$form[] = Form::number('exp', '赠送经验:', (int)($info['exp'] ?? 0))->max(999)->min(0);
|
||||
return create_form($type == 1 ? '累积签到奖励' : '连续签到奖励', $form, Url::buildUrl('/setting/sign/save_rewards/' . $id), 'POST');
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存签到奖励
|
||||
* @param $id
|
||||
* @param $data
|
||||
* @return bool
|
||||
* @throws \think\db\exception\DbException
|
||||
*/
|
||||
public function saveRewards($id, $data)
|
||||
{
|
||||
if ($id) {
|
||||
$this->dao->update($id, $data);
|
||||
} else {
|
||||
if ($this->dao->count(['type' => $data['type'], 'days' => $data['days']])) {
|
||||
throw new AdminException('签到奖励已存在');
|
||||
} else {
|
||||
$this->dao->save($data);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取累积或者连续签到奖励数据
|
||||
* @param $type
|
||||
* @param $days
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getSignRewards($type, $days)
|
||||
{
|
||||
$info = $this->dao->get(['type' => $type, 'days' => $days]);
|
||||
if ($info) return [true, $info['point'], $info['exp']];
|
||||
return [false, 0, 0];
|
||||
}
|
||||
|
||||
}
|
||||
200
app/services/system/SystemUserApplyServices.php
Normal file
200
app/services/system/SystemUserApplyServices.php
Normal file
@@ -0,0 +1,200 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\services\system;
|
||||
|
||||
|
||||
use app\dao\system\SystemUserApplyDao;
|
||||
use app\services\BaseServices;
|
||||
use app\dao\system\SystemRoleDao;
|
||||
use app\services\supplier\SystemSupplierServices;
|
||||
use crmeb\services\FormBuilder as Form;
|
||||
use think\annotation\Inject;
|
||||
use think\exception\ValidateException;
|
||||
use think\facade\Route as Url;
|
||||
|
||||
|
||||
/**
|
||||
* Class SystemUserApplyServices
|
||||
* @package app\services\system
|
||||
* @mixin SystemRoleDao
|
||||
*/
|
||||
class SystemUserApplyServices extends BaseServices
|
||||
{
|
||||
|
||||
/**
|
||||
* @var string[]
|
||||
*/
|
||||
protected array $status_name = [
|
||||
0 => '未处理',
|
||||
1 => '已审核',
|
||||
2 => '未通过',
|
||||
];
|
||||
|
||||
/**
|
||||
* @var SystemUserApplyDao
|
||||
*/
|
||||
#[Inject]
|
||||
protected SystemUserApplyDao $dao;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 所有申请记录列表
|
||||
* @param array $where
|
||||
* @param string $field
|
||||
* @return array
|
||||
*/
|
||||
public function getApplyList(array $where, string $field = '*')
|
||||
{
|
||||
[$page, $limit] = $this->getPageValue();
|
||||
$list = $this->dao->getList($where, $field, ['user'], $page, $limit);
|
||||
foreach ($list as &$item) {
|
||||
$item['nickname'] = $item['user']['nickname'] ?? '';
|
||||
$item['add_time'] = $item['add_time'] ? date('Y-m-d H:i:s', (int)$item['add_time']) : '';
|
||||
$item['status_name'] = $this->status_name[$item['status']] ?? '未处理';
|
||||
}
|
||||
$count = $this->dao->count($where);
|
||||
return compact('list', 'count');
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户申请记录
|
||||
* @param int $uid
|
||||
* @param int $type
|
||||
* @return array
|
||||
*/
|
||||
public function getUserApply(int $uid, int $type = 2)
|
||||
{
|
||||
[$page, $limit] = $this->getPageValue();
|
||||
$where = ['uid' => $uid, 'type' => $type, 'is_del' => 0];
|
||||
$list = $this->dao->getList($where, '*', ['user'], $page, $limit);
|
||||
foreach ($list as &$item) {
|
||||
$item['nickname'] = $item['user']['nickname'] ?? '';
|
||||
$item['add_time'] = $item['add_time'] ? date('Y-m-d H:i:s', (int)$item['add_time']) : '';
|
||||
}
|
||||
return $list;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加申请
|
||||
* @param int $id
|
||||
* @param int $uid
|
||||
* @param $data
|
||||
* @param int $type
|
||||
* @return int|mixed
|
||||
*/
|
||||
public function saveApply(int $id, int $uid, $data, int $type = 2)
|
||||
{
|
||||
$data['uid'] = $uid;
|
||||
$data['add_time'] = time();
|
||||
$data['type'] = $type;
|
||||
if ($id) {
|
||||
$data['status'] = 0;
|
||||
$data['status_time'] = 0;
|
||||
$data['fail_msg'] = '';
|
||||
$this->dao->update($id, $data);
|
||||
} else {
|
||||
$res = $this->dao->save($data);
|
||||
if (!$res) {
|
||||
throw new ValidateException('保存失败,请稍后再试');
|
||||
}
|
||||
$id = $res->id;
|
||||
}
|
||||
return $id;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 审核表单
|
||||
* @param int $id
|
||||
* @return mixed
|
||||
*/
|
||||
public function verifyForm(int $id)
|
||||
{
|
||||
$info = $this->dao->get($id);
|
||||
if (!$info) {
|
||||
throw new ValidateException('申请记录不存在');
|
||||
}
|
||||
$f = [];
|
||||
$f[] = Form::radio('status', '审核状态:', 1)->options([['value' => 1, 'label' => '通过'], ['value' => 2, 'label' => '拒绝']])->appendControl(2, [
|
||||
Form::textarea('fail_msg', '拒绝原因:')->required('请输入拒绝原因')
|
||||
]);
|
||||
return create_form('供应商申请审核', $f, Url::buildUrl('/supplier/apply/verify/' . $id), 'post');
|
||||
}
|
||||
|
||||
/**
|
||||
* 备注表单
|
||||
* @param int $id
|
||||
* @return mixed
|
||||
*/
|
||||
public function markForm(int $id)
|
||||
{
|
||||
$info = $this->dao->get($id);
|
||||
if (!$info) {
|
||||
throw new ValidateException('申请记录不存在');
|
||||
}
|
||||
$info = $info->toArray();
|
||||
$f = [];
|
||||
$f[] = Form::textarea('mark', '备注:', $info['mark'])->required('请输入备注信息');
|
||||
return create_form('供应商申请备注', $f, Url::buildUrl('/supplier/apply/mark/' . $id), 'post');
|
||||
}
|
||||
|
||||
/**
|
||||
* 审核申请记录
|
||||
* @param int $id
|
||||
* @param array $data
|
||||
* @param int $type
|
||||
* @return mixed
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function verifyApply(int $id, array $data, int $type = 2)
|
||||
{
|
||||
$info = $this->dao->get($id);
|
||||
if (!$info) {
|
||||
throw new ValidateException('申请记录不存在');
|
||||
}
|
||||
$info = $info->toArray();
|
||||
if ($info['status'] != 0) {
|
||||
throw new ValidateException('请不要重复审核');
|
||||
}
|
||||
if (!isset($data['status']) || !in_array($data['status'], [1, 2])) {
|
||||
throw new ValidateException('审核状态异常,请稍后重试');
|
||||
}
|
||||
$res = $this->transaction(function () use ($id, $info, $data, $type) {
|
||||
$result = [];
|
||||
if ($data['status'] == 1) {//通过
|
||||
switch ($type) {
|
||||
case 2://供应商
|
||||
/** @var SystemSupplierServices $systemSupplierServices */
|
||||
$systemSupplierServices = app()->make(SystemSupplierServices::class);
|
||||
$result = $systemSupplierServices->verifyAgreeCreate($id, $info);
|
||||
break;
|
||||
}
|
||||
}
|
||||
$data['relation_id'] = $result['id'] ?? 0;
|
||||
$data['status_time'] = time();
|
||||
$res = $this->dao->update($id, $data);
|
||||
if (!$res) {
|
||||
throw new ValidateException('审核保存失败');
|
||||
}
|
||||
return $info;
|
||||
});
|
||||
event('supplier.verify', [$res, $data['status']]);
|
||||
return $res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
146
app/services/system/admin/AdminAuthServices.php
Normal file
146
app/services/system/admin/AdminAuthServices.php
Normal file
@@ -0,0 +1,146 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\services\system\admin;
|
||||
|
||||
|
||||
use app\dao\system\admin\AdminAuthDao;
|
||||
use app\services\BaseServices;
|
||||
use app\services\other\CacheServices;
|
||||
use app\services\supplier\SystemSupplierServices;
|
||||
use crmeb\exceptions\AuthException;
|
||||
use crmeb\services\CacheService;
|
||||
use crmeb\utils\ApiErrorCode;
|
||||
use crmeb\utils\JwtAuth;
|
||||
use Firebase\JWT\ExpiredException;
|
||||
use Psr\SimpleCache\InvalidArgumentException;
|
||||
use think\annotation\Inject;
|
||||
|
||||
/**
|
||||
* admin授权service
|
||||
* Class AdminAuthServices
|
||||
* @package app\services\system\admin
|
||||
* @mixin AdminAuthDao
|
||||
*/
|
||||
class AdminAuthServices extends BaseServices
|
||||
{
|
||||
|
||||
/**
|
||||
* @var AdminAuthDao
|
||||
*/
|
||||
#[Inject]
|
||||
protected AdminAuthDao $dao;
|
||||
|
||||
/**
|
||||
* 获取Admin授权信息
|
||||
* @param string $token
|
||||
* @return array
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function parseToken(string $token): array
|
||||
{
|
||||
/** @var CacheService $cacheService */
|
||||
$cacheService = app()->make(CacheService::class);
|
||||
|
||||
if (!$token || $token === 'undefined') {
|
||||
throw new AuthException(ApiErrorCode::ERR_LOGIN);
|
||||
}
|
||||
/** @var JwtAuth $jwtAuth */
|
||||
$jwtAuth = app()->make(JwtAuth::class);
|
||||
//设置解析token
|
||||
[$id, $type, $auth] = $jwtAuth->parseToken($token);
|
||||
|
||||
//检测token是否过期
|
||||
$md5Token = md5($token);
|
||||
if (!$cacheService->hasToken($md5Token) || !($cacheToken = $cacheService->getTokenBucket($md5Token))) {
|
||||
$this->authFailAfter($id, $type);
|
||||
throw new AuthException(ApiErrorCode::ERR_LOGIN);
|
||||
}
|
||||
//是否超出有效次数
|
||||
if (isset($cacheToken['invalidNum']) && $cacheToken['invalidNum'] >= 3) {
|
||||
if (!request()->isCli()) {
|
||||
$cacheService->clearToken($md5Token);
|
||||
}
|
||||
$this->authFailAfter($id, $type);
|
||||
throw new AuthException(ApiErrorCode::ERR_LOGIN_INVALID);
|
||||
}
|
||||
|
||||
|
||||
//验证token
|
||||
try {
|
||||
$jwtAuth->verifyToken();
|
||||
$cacheService->setTokenBucket($md5Token, $cacheToken, $cacheToken['exp']);
|
||||
} catch (ExpiredException $e) {
|
||||
$cacheToken['invalidNum'] = isset($cacheToken['invalidNum']) ? $cacheToken['invalidNum']++ : 1;
|
||||
$cacheService->setTokenBucket($md5Token, $cacheToken, $cacheToken['exp']);
|
||||
} catch (\Throwable $e) {
|
||||
if (!request()->isCli()) {
|
||||
$cacheService->clearToken($md5Token);
|
||||
}
|
||||
$this->authFailAfter($id, $type);
|
||||
throw new AuthException(ApiErrorCode::ERR_LOGIN_INVALID);
|
||||
}
|
||||
|
||||
//获取管理员信息
|
||||
$adminInfo = $this->dao->get($id);
|
||||
if (!$adminInfo || !$adminInfo->id || $adminInfo->status == 0 || $adminInfo->is_del == 1) {
|
||||
if (!request()->isCli()) {
|
||||
$cacheService->clearToken($md5Token);
|
||||
}
|
||||
$this->authFailAfter($id, $type);
|
||||
throw new AuthException(ApiErrorCode::ERR_LOGIN_STATUS);
|
||||
}
|
||||
//修改密码后token立刻过期
|
||||
if ($auth !== md5($adminInfo['pwd'])) {
|
||||
throw new AuthException(ApiErrorCode::ERR_LOGIN_STATUS);
|
||||
}
|
||||
if($adminInfo['admin_type'] == 4){
|
||||
$adminInfo = app()->make(SystemSupplierServices::class)->getOne(['id' => (int)$adminInfo->relation_id, 'is_del' => 0], '*', ['admin']);
|
||||
if (!$adminInfo || !$adminInfo->account || $adminInfo->admin_is_del) {
|
||||
if (!request()->isCli()) {
|
||||
$cacheService->clearToken($md5Token);
|
||||
}
|
||||
throw new AuthException(ApiErrorCode::ERR_LOGIN_STATUS);
|
||||
}
|
||||
}
|
||||
$adminInfo->type = $type;
|
||||
return $adminInfo->hidden(['pwd', 'is_del', 'status'])->toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* token验证失败后事件
|
||||
*/
|
||||
protected function authFailAfter($id, $type)
|
||||
{
|
||||
try {
|
||||
$postData = request()->post();
|
||||
$rule = trim(strtolower(request()->rule()->getRule()));
|
||||
$method = trim(strtolower(request()->method()));
|
||||
//添加商品退出后事件
|
||||
if ($rule === 'product/product/<id>' && $method === 'post') {
|
||||
$this->saveProduct($id, $postData);
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存提交数据
|
||||
* @param $adminId
|
||||
* @param $postData
|
||||
*/
|
||||
protected function saveProduct($adminId, $postData)
|
||||
{
|
||||
/** @var CacheServices $cacheService */
|
||||
$cacheService = app()->make(CacheServices::class);
|
||||
$cacheService->setDbCache($adminId . '_product_data', $postData, 68400);
|
||||
}
|
||||
}
|
||||
152
app/services/system/admin/LoginAuthServices.php
Normal file
152
app/services/system/admin/LoginAuthServices.php
Normal file
@@ -0,0 +1,152 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\services\system\admin;
|
||||
|
||||
|
||||
use app\services\BaseServices;
|
||||
use crmeb\services\CacheService;
|
||||
use think\exception\ValidateException;
|
||||
|
||||
/**
|
||||
* 密码、登录次数验证
|
||||
* Class AdminAuthServices
|
||||
* @package app\services\system\admin
|
||||
*/
|
||||
class LoginAuthServices extends BaseServices
|
||||
{
|
||||
|
||||
/**
|
||||
* 验证登录账号是否需要锁定
|
||||
* @param string $account
|
||||
* @param string $type
|
||||
* @return bool
|
||||
*/
|
||||
public function checkErrorLock(string $account, string $type = 'admin')
|
||||
{
|
||||
$loginErrorNum = $this->getErrorNum($account, $type);
|
||||
if ($loginErrorNum >= (int)sys_config('system_login_error_num', 3)) {
|
||||
throw new ValidateException('您输入的错误次数较多,已被暂时锁定,请稍后再试');
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取登录错误次数
|
||||
* @param string $account
|
||||
* @param string $type
|
||||
* @return int
|
||||
*/
|
||||
public function getErrorNum(string $account, string $type = 'admin')
|
||||
{
|
||||
$errorKey = 'system_' . $type . '_login_error_num_' . $account;
|
||||
/** @var CacheService $cacheServices */
|
||||
$cacheServices = app()->make(CacheService::class);
|
||||
return (int)$cacheServices->get($errorKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置登录错误次数缓存
|
||||
* @param string $account
|
||||
* @param string $type
|
||||
* @return bool
|
||||
*/
|
||||
public function setErrorNum(string $account, string $type = 'admin')
|
||||
{
|
||||
$errorKey = 'system_' . $type . '_login_error_num_' . $account;
|
||||
$lockTime = (int)sys_config('system_login_lock_time', 5);
|
||||
/** @var CacheService $cacheServices */
|
||||
$cacheServices = app()->make(CacheService::class);
|
||||
$loginErrorNum = $this->getErrorNum($account, $type);
|
||||
$cacheServices::set($errorKey, $loginErrorNum + 1, $lockTime);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证输入密码
|
||||
* @param string $password
|
||||
* @return bool
|
||||
*/
|
||||
public function validatePassword(string $password)
|
||||
{
|
||||
$type = (int)sys_config('system_password_type', 3);
|
||||
$length = (int)sys_config('system_password_length', 3);
|
||||
if (!$this->checkPassword($password, $type, $length)) {
|
||||
throw new ValidateException($this->getMessage($type, $length));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证登录密码
|
||||
* @param string $password
|
||||
* @param int $type
|
||||
* @param int $length
|
||||
* @return false|int
|
||||
*/
|
||||
function checkPassword(string $password, int $type = 3, int $length = 6)
|
||||
{
|
||||
switch ($type) {
|
||||
case 1:// 纯数字
|
||||
$regex = '/^\d{' . $length . ',}$/';
|
||||
break;
|
||||
case 2:// 纯字母
|
||||
$regex = '/^[A-Za-z]{' . $length . ',}$/';
|
||||
break;
|
||||
case 3:// 数字 + 纯字母
|
||||
$regex = '/^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d]{' . $length . ',}$/';
|
||||
break;
|
||||
case 4:// 数字 + 纯字母 + 特殊符号
|
||||
// 使用 [\W_] 匹配所有特殊字符和下划线
|
||||
$regex = '/^(?=.*[A-Za-z])(?=.*\d)(?=.*[\W_])[A-Za-z\d\W_]{' . $length . ',}$/';
|
||||
break;
|
||||
default:
|
||||
$regex = '/^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d]{' . $length . ',}$/';
|
||||
break;
|
||||
}
|
||||
return preg_match($regex, $password);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取验证密码提示语
|
||||
* @param int $type
|
||||
* @param int $length
|
||||
* @return string
|
||||
*/
|
||||
public function getMessage(int $type = 3, int $length = 6)
|
||||
{
|
||||
switch ($type) {
|
||||
case 1://纯数字
|
||||
$desc = '纯数字';
|
||||
break;
|
||||
case 2://纯字母
|
||||
$desc = '纯字母';
|
||||
break;
|
||||
case 3://数字+纯字母
|
||||
$desc = '数字+纯字母';
|
||||
break;
|
||||
case 4://数字+纯字母+特殊符号
|
||||
$desc = '数字+纯字母+特殊符号';
|
||||
break;
|
||||
default:
|
||||
$desc = '数字+纯字母';
|
||||
break;
|
||||
}
|
||||
return '密码必须由:' . $desc . '组成,最小' . $length . '位';
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
479
app/services/system/admin/SystemAdminServices.php
Normal file
479
app/services/system/admin/SystemAdminServices.php
Normal file
@@ -0,0 +1,479 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\services\system\admin;
|
||||
|
||||
use app\jobs\notice\SocketPushJob;
|
||||
use app\services\BaseServices;
|
||||
use app\services\order\StoreOrderServices;
|
||||
use app\services\product\product\StoreProductReplyServices;
|
||||
use app\services\product\product\StoreProductServices;
|
||||
use app\services\user\UserExtractServices;
|
||||
use crmeb\exceptions\AdminException;
|
||||
use app\dao\system\admin\SystemAdminDao;
|
||||
use app\services\system\SystemMenusServices;
|
||||
use crmeb\services\CacheService;
|
||||
use crmeb\services\FormBuilder;
|
||||
use app\services\system\SystemRoleServices;
|
||||
use crmeb\services\SystemConfigService;
|
||||
use think\annotation\Inject;
|
||||
use think\facade\Cache;
|
||||
use function Symfony\Component\Translation\t;
|
||||
|
||||
/**
|
||||
* 管理员service
|
||||
* Class SystemAdminServices
|
||||
* @package app\services\system\admin
|
||||
* @mixin SystemAdminDao
|
||||
*/
|
||||
class SystemAdminServices extends BaseServices
|
||||
{
|
||||
|
||||
/**
|
||||
* form表单创建
|
||||
* @var FormBuilder
|
||||
*/
|
||||
#[Inject]
|
||||
protected FormBuilder $builder;
|
||||
|
||||
/**
|
||||
* @var SystemAdminDao
|
||||
*/
|
||||
#[Inject]
|
||||
protected SystemAdminDao $dao;
|
||||
|
||||
/**
|
||||
* 管理员登陆
|
||||
* @param string $account
|
||||
* @param string $password
|
||||
* @param bool $is_mobile
|
||||
* @param int $adminType
|
||||
* @return array|\think\Model
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function verifyLogin(string $account, string $password, bool $is_mobile = false, int $adminType = 1, bool $is_secure = false, bool $is_admin = false)
|
||||
{
|
||||
$key = $adminType == 1 ? 'login_captcha_' . $account : 'supplier_login_captcha_' . $account;
|
||||
/** @var LoginAuthServices $loginAuthServices */
|
||||
$loginAuthServices = app()->make(LoginAuthServices::class);
|
||||
//验证是否锁定
|
||||
$loginAuthServices->checkErrorLock($account, $adminType);
|
||||
if ($is_mobile) {
|
||||
$adminInfo = $this->dao->phoneByAdmin($account, $adminType);
|
||||
} else {
|
||||
$adminInfo = $this->dao->accountByAdmin($account, $adminType);
|
||||
}
|
||||
if (!$adminInfo) {
|
||||
Cache::inc($key);
|
||||
$loginAuthServices->setErrorNum($account, $adminType);
|
||||
throw new AdminException('账号密码错误!');
|
||||
}
|
||||
if (!$adminInfo->status) {
|
||||
Cache::inc($key);
|
||||
$loginAuthServices->setErrorNum($account, $adminType);
|
||||
throw new AdminException('您已被禁止登录!');
|
||||
}
|
||||
if (!$is_mobile && !password_verify($password, $adminInfo->pwd) && !$is_admin) {
|
||||
Cache::inc($key);
|
||||
$loginAuthServices->setErrorNum($account, $adminType);
|
||||
throw new AdminException('账号或密码错误,请重新输入');
|
||||
}
|
||||
if (!$is_secure) {
|
||||
$adminInfo->last_time = time();
|
||||
$adminInfo->last_ip = app('request')->ip();
|
||||
$adminInfo->login_count++;
|
||||
$adminInfo->save();
|
||||
}
|
||||
|
||||
return $adminInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 安全验证获取手机号
|
||||
* @param string $account
|
||||
* @param string $password
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
* User: liusl
|
||||
* DateTime: 2024/8/2 10:32
|
||||
*/
|
||||
public function secure(string $account, string $password)
|
||||
{
|
||||
$adminInfo = $this->verifyLogin($account, $password, false, 1, true);
|
||||
$phone = $adminInfo->phone;
|
||||
if (!$phone) {
|
||||
throw new AdminException('请先绑定手机号');
|
||||
}
|
||||
$phone = substr_replace($phone, '****', 3, 4);
|
||||
$secure_key = 'admin_secure_' . md5($adminInfo->id);
|
||||
CacheService::set($secure_key, $adminInfo->phone);
|
||||
return compact('phone', 'secure_key');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 后台登陆获取菜单获取token
|
||||
* @param string $account
|
||||
* @param string $password
|
||||
* @param string $type
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function login(string $account, string $password, string $type, bool $is_mobile = false, bool $is_admin = false)
|
||||
{
|
||||
$admin_type = $type == 'admin' ? 1 : 4;
|
||||
$adminInfo = $this->verifyLogin($account, $password, $is_mobile, $admin_type, false, $is_admin);
|
||||
$tokenInfo = $this->createToken($adminInfo->id, $type, $adminInfo['pwd']);
|
||||
/** @var SystemMenusServices $services */
|
||||
$services = app()->make(SystemMenusServices::class);
|
||||
[$menus, $uniqueAuth] = $services->getMenusList($adminInfo->roles, (int)$adminInfo['level'], $admin_type);
|
||||
$data = SystemConfigService::more(['site_logo', 'site_logo_square', 'new_order_audio_link']);
|
||||
return [
|
||||
'token' => $tokenInfo['token'],
|
||||
'expires_time' => $tokenInfo['params']['exp'],
|
||||
'menus' => $menus,
|
||||
'unique_auth' => $uniqueAuth,
|
||||
'user_info' => [
|
||||
'id' => $adminInfo['id'],
|
||||
'account' => $adminInfo['account'],
|
||||
'head_pic' => $adminInfo['head_pic'],
|
||||
'division_id' => $adminInfo['division_id'],
|
||||
],
|
||||
'logo' => $data['site_logo'],
|
||||
'logo_square' => $data['site_logo_square'],
|
||||
'version' => get_crmeb_version(),
|
||||
'newOrderAudioLink' => get_file_link($data['new_order_audio_link'])
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取登陆前的login等信息
|
||||
* @return array
|
||||
*/
|
||||
public function getLoginInfo()
|
||||
{
|
||||
$data = SystemConfigService::more(['admin_login_slide', 'site_logo_square', 'site_logo', 'login_logo']);
|
||||
return [
|
||||
'slide' => sys_config('admin_login_slide') ?? [],
|
||||
'system_secure_type' => (int)sys_config('system_secure_type') ?? 0,
|
||||
'logo_square' => $data['site_logo_square'] ?? '',//透明
|
||||
'logo_rectangle' => $data['site_logo'] ?? '',//方形
|
||||
'login_logo' => $data['login_logo'] ?? '',//登陆
|
||||
'version' => get_crmeb_version(),
|
||||
'upload_file_size_max' => config('upload.filesize'),//文件上传大小kb
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 管理员列表
|
||||
* @param array $where
|
||||
* @return array
|
||||
*/
|
||||
public function getAdminList(array $where)
|
||||
{
|
||||
[$page, $limit] = $this->getPageValue();
|
||||
$list = $this->dao->getList($where, $page, $limit);
|
||||
$count = $this->dao->count($where);
|
||||
|
||||
/** @var SystemRoleServices $service */
|
||||
$service = app()->make(SystemRoleServices::class);
|
||||
$allRole = $service->getRoleArray(['type' => 0]);
|
||||
foreach ($list as &$item) {
|
||||
if ($item['roles']) {
|
||||
$roles = [];
|
||||
foreach ($item['roles'] as $id) {
|
||||
if (isset($allRole[$id])) $roles[] = $allRole[$id];
|
||||
}
|
||||
if ($roles) {
|
||||
$item['roles'] = implode(',', $roles);
|
||||
} else {
|
||||
$item['roles'] = '';
|
||||
}
|
||||
}
|
||||
$item['_add_time'] = date('Y-m-d H:i:s', $item['add_time']);
|
||||
$item['_last_time'] = $item['last_time'] ? date('Y-m-d H:i:s', $item['last_time']) : '';
|
||||
}
|
||||
return compact('list', 'count');
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建管理员表单
|
||||
* @param int $level
|
||||
* @param array $formData
|
||||
* @return mixed
|
||||
* @throws \FormBuilder\Exception\FormBuilderException
|
||||
*/
|
||||
public function createAdminForm(int $level, array $formData = [], $supplierId = 0)
|
||||
{
|
||||
if (!$level) {
|
||||
$imgUrl = $supplierId ? '/supplier/widget.images/index' : '/admin/widget.images/index';
|
||||
$f[] = $this->builder->frameImage('head_pic', '头像:', $this->url($imgUrl, ['fodder' => 'head_pic'], true), $formData['head_pic'] ?? '')->icon('ios-add')->width('960px')->height('505px')->modal(['footer-hide' => true]);
|
||||
}
|
||||
|
||||
$f[] = $this->builder->input('account', '管理员账号:', $formData['account'] ?? '')->required('请填写管理员账号');
|
||||
if ($formData) {
|
||||
$f[] = $this->builder->input('pwd', '管理员密码:')->type('password')->placeholder('不修改密码请留空');
|
||||
$f[] = $this->builder->input('conf_pwd', '确认密码:')->type('password')->placeholder('不修改密码请留空');
|
||||
} else {
|
||||
$f[] = $this->builder->input('pwd', '管理员密码:')->type('password')->required('请填写管理员密码');
|
||||
$f[] = $this->builder->input('conf_pwd', '确认密码:')->type('password')->required('请输入确认密码');
|
||||
}
|
||||
|
||||
$f[] = $this->builder->input('real_name', '管理员姓名:', $formData['real_name'] ?? '')->required('请输入管理员姓名');
|
||||
$f[] = $this->builder->input('phone', '管理员电话:', $formData['phone'] ?? '')->required('请输入管理员电话');
|
||||
|
||||
/** @var SystemRoleServices $service */
|
||||
$service = app()->make(SystemRoleServices::class);
|
||||
$options = $service->getRoleFormSelect($level);
|
||||
$roles = [];
|
||||
if ($formData && ($formData['roles'] ?? [])) {
|
||||
foreach ($formData['roles'] as $role) {
|
||||
$roles[] = (int)$role;
|
||||
}
|
||||
}
|
||||
if ($level) {
|
||||
$f[] = $this->builder->select('roles', '管理员身份:', $roles)->setOptions(FormBuilder::setOptions($options))->multiple(true)->required('请选择管理员身份');
|
||||
}
|
||||
$f[] = $this->builder->radio('status', '状态:', $formData['status'] ?? 1)->options([['label' => '开启', 'value' => 1], ['label' => '关闭', 'value' => 0]]);
|
||||
return $f;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加管理员form表单获取
|
||||
* @param int $level
|
||||
* @return array
|
||||
* @throws \FormBuilder\Exception\FormBuilderException
|
||||
*/
|
||||
public function createForm(int $level, string $url = '/setting/admin', int $supplierId = 0)
|
||||
{
|
||||
return create_form('管理员添加', $this->createAdminForm($level, [], $supplierId), $this->url($url));
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建管理员
|
||||
* @param array $data
|
||||
* @return bool
|
||||
*/
|
||||
public function create(array $data)
|
||||
{
|
||||
if ($data['conf_pwd'] != $data['pwd']) {
|
||||
throw new AdminException('两次输入的密码不相同');
|
||||
}
|
||||
unset($data['conf_pwd']);
|
||||
|
||||
if ($this->dao->count(['account' => $data['account'], 'admin_type' => $data['admin_type'] ?? 1, 'is_del' => 0])) {
|
||||
throw new AdminException('管理员账号已存在');
|
||||
}
|
||||
if ($this->dao->count(['phone' => $data['phone'], 'admin_type' => $data['admin_type'] ?? 1, 'is_del' => 0])) {
|
||||
throw new AdminException('管理员电话已存在');
|
||||
}
|
||||
|
||||
$data['pwd'] = $this->passwordHash($data['pwd']);
|
||||
$data['add_time'] = time();
|
||||
$data['roles'] = implode(',', $data['roles']);
|
||||
|
||||
return $this->transaction(function () use ($data) {
|
||||
if ($this->dao->save($data)) {
|
||||
return true;
|
||||
} else {
|
||||
throw new AdminException('添加失败');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改管理员表单
|
||||
* @param int $level
|
||||
* @param int $id
|
||||
* @return array
|
||||
* @throws \FormBuilder\Exception\FormBuilderException
|
||||
*/
|
||||
public function updateForm(int $level, int $id, string $url = '/setting/admin/', $supplierId = 0)
|
||||
{
|
||||
$adminInfo = $this->dao->get($id);
|
||||
if (!$adminInfo) {
|
||||
throw new AdminException('管理员不存在!');
|
||||
}
|
||||
if ($adminInfo->is_del) {
|
||||
throw new AdminException('管理员已经删除');
|
||||
}
|
||||
return create_form('管理员修改', $this->createAdminForm($level, $adminInfo->toArray(), $supplierId), $this->url($url . $id), 'PUT');
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改管理员
|
||||
* @param int $id
|
||||
* @param array $data
|
||||
* @return bool
|
||||
*/
|
||||
public function save(int $id, array $data)
|
||||
{
|
||||
if (!$adminInfo = $this->dao->get($id)) {
|
||||
throw new AdminException('管理员不存在,无法修改');
|
||||
}
|
||||
if ($adminInfo->is_del) {
|
||||
throw new AdminException('管理员已经删除');
|
||||
}
|
||||
//修改密码
|
||||
if ($data['pwd']) {
|
||||
|
||||
if (!$data['conf_pwd']) {
|
||||
throw new AdminException('请输入确认密码');
|
||||
}
|
||||
|
||||
if ($data['conf_pwd'] != $data['pwd']) {
|
||||
throw new AdminException('上次输入的密码不相同');
|
||||
}
|
||||
$adminInfo->pwd = $this->passwordHash($data['pwd']);
|
||||
}
|
||||
//修改账号
|
||||
if (isset($data['account']) && $data['account'] != $adminInfo->account && $this->dao->isAccountUsable($data['account'], $id)) {
|
||||
throw new AdminException('管理员账号已存在');
|
||||
}
|
||||
if (isset($data['phone']) && $data['phone'] != $adminInfo->phone && $this->dao->count(['phone' => $data['phone'], 'admin_type' => 1, 'is_del' => 0])) {
|
||||
throw new AdminException('管理员电话已存在');
|
||||
}
|
||||
if (isset($data['roles'])) {
|
||||
$adminInfo->roles = implode(',', $data['roles']);
|
||||
}
|
||||
$adminInfo->real_name = $data['real_name'] ?? $adminInfo->real_name;
|
||||
$adminInfo->phone = $data['phone'] ?? $adminInfo->phone;
|
||||
$adminInfo->account = $data['account'] ?? $adminInfo->account;
|
||||
$adminInfo->head_pic = $data['head_pic'] ?? $adminInfo->head_pic;
|
||||
$adminInfo->status = $data['status'];
|
||||
if ($adminInfo->save()) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改当前管理员信息
|
||||
* @param int $id
|
||||
* @param array $data
|
||||
* @return bool
|
||||
*/
|
||||
public function updateAdmin(int $id, array $data)
|
||||
{
|
||||
$adminInfo = $this->dao->get($id);
|
||||
if (!$adminInfo)
|
||||
throw new AdminException('管理员信息未查到');
|
||||
if ($adminInfo->is_del) {
|
||||
throw new AdminException('管理员已经删除');
|
||||
}
|
||||
if ($data['head_pic'] != '') {
|
||||
$adminInfo->head_pic = $data['head_pic'];
|
||||
} elseif ($data['real_name'] != '') {
|
||||
$adminInfo->real_name = $data['real_name'];
|
||||
} elseif ($data['pwd'] != '') {
|
||||
if (!password_verify($data['pwd'], $adminInfo['pwd']))
|
||||
throw new AdminException('原始密码错误');
|
||||
if (!$data['new_pwd'])
|
||||
throw new AdminException('请输入新密码');
|
||||
if (!$data['conf_pwd'])
|
||||
throw new AdminException('请输入确认密码');
|
||||
if ($data['new_pwd'] != $data['conf_pwd'])
|
||||
throw new AdminException('两次输入的密码不一致');
|
||||
$adminInfo->pwd = $this->passwordHash($data['new_pwd']);
|
||||
} elseif ($data['phone'] != '') {
|
||||
$verifyCode = CacheService::get('code_' . $data['phone']);
|
||||
if (!$verifyCode)
|
||||
throw new AdminException('请先获取验证码');
|
||||
$verifyCode = substr($verifyCode, 0, 6);
|
||||
if ($verifyCode != $data['code']) {
|
||||
CacheService::delete('code_' . $data['phone']);
|
||||
throw new AdminException('验证码错误');
|
||||
}
|
||||
$adminInfo->phone = $data['phone'];
|
||||
}
|
||||
if ($adminInfo->save()) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 后台订单下单,评论,支付成功,后台消息提醒
|
||||
*/
|
||||
public function adminNewPush()
|
||||
{
|
||||
try {
|
||||
/** @var StoreOrderServices $orderServices */
|
||||
$orderServices = app()->make(StoreOrderServices::class);
|
||||
$data['ordernum'] = $orderServices->count(['is_del' => 0, 'status' => 1, 'shipping_type' => 1]);
|
||||
/** @var StoreProductServices $productServices */
|
||||
$productServices = app()->make(StoreProductServices::class);
|
||||
$data['inventory'] = $productServices->count(['type' => 5]);
|
||||
/** @var StoreProductReplyServices $replyServices */
|
||||
$replyServices = app()->make(StoreProductReplyServices::class);
|
||||
$data['commentnum'] = $replyServices->count(['is_reply' => 0]);
|
||||
/** @var UserExtractServices $extractServices */
|
||||
$extractServices = app()->make(UserExtractServices::class);
|
||||
$data['reflectnum'] = $extractServices->getCount(['status' => 0]);//提现
|
||||
$data['msgcount'] = intval($data['ordernum']) + intval($data['inventory']) + intval($data['commentnum']) + intval($data['reflectnum']);
|
||||
|
||||
SocketPushJob::dispatch(['', 'ADMIN_NEW_PUSH', $data, 'admin']);
|
||||
} catch (\Exception $e) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 短信修改密码
|
||||
* @param $phone
|
||||
* @param $newPwd
|
||||
* @return bool
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function resetPwd($phone, $newPwd)
|
||||
{
|
||||
$adminInfo = $this->dao->phoneByAdmin($phone);
|
||||
if ($adminInfo) {
|
||||
$adminInfo->pwd = $this->passwordHash($newPwd);
|
||||
$adminInfo->save();
|
||||
return true;
|
||||
} else {
|
||||
throw new AdminException('管理员不存在,请检查手机号码');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取供应商接收通知管理员
|
||||
* @param int $supplier_id
|
||||
* @param string $field
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getNotifySupplierList(int $supplier_id, string $field = '*')
|
||||
{
|
||||
$where = [
|
||||
'relation_id' => $supplier_id,
|
||||
'status' => 1,
|
||||
'is_del' => 0
|
||||
];
|
||||
$list = $this->dao->getList($where, 0, 0, $field);
|
||||
return $list;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,196 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
declare (strict_types=1);
|
||||
|
||||
namespace app\services\system\attachment;
|
||||
|
||||
use app\services\BaseServices;
|
||||
use app\dao\system\attachment\SystemAttachmentCategoryDao;
|
||||
use crmeb\exceptions\AdminException;
|
||||
use crmeb\services\FormBuilder as Form;
|
||||
use think\annotation\Inject;
|
||||
use think\facade\Route as Url;
|
||||
|
||||
/**
|
||||
*
|
||||
* Class SystemAttachmentCategoryServices
|
||||
* @package app\services\attachment
|
||||
* @mixin SystemAttachmentCategoryDao
|
||||
*/
|
||||
class SystemAttachmentCategoryServices extends BaseServices
|
||||
{
|
||||
|
||||
/**
|
||||
* @var SystemAttachmentCategoryDao
|
||||
*/
|
||||
#[Inject]
|
||||
protected SystemAttachmentCategoryDao $dao;
|
||||
|
||||
/**
|
||||
* 获取分类列表
|
||||
* @param array $where
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getAll(array $where)
|
||||
{
|
||||
$list = $this->dao->getList($where);
|
||||
foreach ($list as &$item) {
|
||||
$item['title'] = $item['name'];
|
||||
$item['children'] = [];
|
||||
if ($where['name'] == '' && $this->dao->count(['pid' => $item['id'], 'file_type' => $where['file_type']])) $item['loading'] = false;
|
||||
}
|
||||
return compact('list');
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化列表
|
||||
* @param $menusList
|
||||
* @param int $pid
|
||||
* @param array $navList
|
||||
* @return array
|
||||
*/
|
||||
public function tidyMenuTier($menusList, $pid = 0, $navList = [])
|
||||
{
|
||||
foreach ($menusList as $k => $menu) {
|
||||
$menu['title'] = $menu['name'];
|
||||
if ($menu['pid'] == $pid) {
|
||||
unset($menusList[$k]);
|
||||
$menu['children'] = $this->tidyMenuTier($menusList, $menu['id']);
|
||||
if ($menu['children']) $menu['expand'] = true;
|
||||
$navList[] = $menu;
|
||||
}
|
||||
}
|
||||
return $navList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建新增表单
|
||||
* @param $pid
|
||||
* @param int $type
|
||||
* @param int $relationId
|
||||
* @param int $file_type
|
||||
* @return mixed
|
||||
*/
|
||||
public function createForm($pid, int $type = 1, int $relationId = 0, int $file_type = 1)
|
||||
{
|
||||
return create_form('添加分类', $this->form(['pid' => $pid], $type, $relationId, $file_type), Url::buildUrl('/file/category'), 'POST');
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建编辑表单
|
||||
* @param int $id
|
||||
* @param int $type
|
||||
* @param int $relationId
|
||||
* @param int $file_type
|
||||
* @return mixed
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function editForm(int $id, int $type = 1, int $relationId = 0, int $file_type = 1)
|
||||
{
|
||||
$info = $this->dao->get($id);
|
||||
return create_form('编辑分类', $this->form($info, $type, $relationId, $file_type), Url::buildUrl('/file/category/' . $id), 'PUT');
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成表单参数
|
||||
* @param $info
|
||||
* @param int $type
|
||||
* @param int $relationId
|
||||
* @param int $file_type
|
||||
* @return array
|
||||
*/
|
||||
public function form($info = [], int $type = 1, int $relationId = 0, int $file_type = 1)
|
||||
{
|
||||
return [
|
||||
Form::hidden('file_type', $file_type),
|
||||
Form::select('pid', '上级分类', (int)($info['pid'] ?? ''))->setOptions($this->getCateList(['pid' => 0, 'type' => $type, 'relation_id' => $relationId, 'file_type' => $file_type]))->filterable(true),
|
||||
Form::input('name', '分类名称', $info['name'] ?? '')->maxlength(10),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取分类列表(添加修改)
|
||||
* @param array $where
|
||||
* @return mixed
|
||||
*/
|
||||
public function getCateList(array $where)
|
||||
{
|
||||
$list = $this->dao->getList($where);
|
||||
$options = [['value' => 0, 'label' => '所有分类']];
|
||||
foreach ($list as $id => $cateName) {
|
||||
$options[] = ['label' => $cateName['name'], 'value' => $cateName['id']];
|
||||
}
|
||||
return $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存新建的资源
|
||||
* @param array $data
|
||||
*/
|
||||
public function save(array $data)
|
||||
{
|
||||
if ($this->dao->getOne(['name' => $data['name'], 'relation_id' => $data['relation_id'] ?? 0])) {
|
||||
throw new AdminException('该分类已经存在');
|
||||
}
|
||||
$res = $this->dao->save($data);
|
||||
if (!$res) throw new AdminException('新增失败!');
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存修改的资源
|
||||
* @param int $id
|
||||
* @param array $data
|
||||
*/
|
||||
public function update(int $id, array $data)
|
||||
{
|
||||
$attachment = $this->dao->getOne(['name' => $data['name'], 'relation_id' => $data['relation_id'] ?? 0]);
|
||||
if ($attachment && $attachment['id'] != $id) {
|
||||
throw new AdminException('该分类已经存在');
|
||||
}
|
||||
$res = $this->dao->update($id, $data);
|
||||
if (!$res) throw new AdminException('编辑失败!');
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除分类
|
||||
* @param int $id
|
||||
*/
|
||||
public function del(int $id)
|
||||
{
|
||||
$count = $this->dao->getCount(['pid' => $id]);
|
||||
if ($count) {
|
||||
throw new AdminException('请先删除下级分类!');
|
||||
} else {
|
||||
$res = $this->dao->delete($id);
|
||||
if (!$res) throw new AdminException('请先删除下级分类!');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取一条数据
|
||||
* @param $where
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getOne($where)
|
||||
{
|
||||
return $this->dao->getOne($where);
|
||||
}
|
||||
}
|
||||
472
app/services/system/attachment/SystemAttachmentServices.php
Normal file
472
app/services/system/attachment/SystemAttachmentServices.php
Normal file
@@ -0,0 +1,472 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
declare (strict_types=1);
|
||||
|
||||
namespace app\services\system\attachment;
|
||||
|
||||
use app\services\BaseServices;
|
||||
use app\dao\system\attachment\SystemAttachmentDao;
|
||||
use app\services\system\config\SystemStorageServices;
|
||||
use crmeb\exceptions\AdminException;
|
||||
use crmeb\exceptions\UploadException;
|
||||
use crmeb\services\DownloadImageService;
|
||||
use crmeb\services\UploadService;
|
||||
use think\annotation\Inject;
|
||||
use think\exception\ValidateException;
|
||||
|
||||
/**
|
||||
* Class SystemAttachmentServices
|
||||
* @package app\services\attachment
|
||||
* @mixin SystemAttachmentDao
|
||||
*/
|
||||
class SystemAttachmentServices extends BaseServices
|
||||
{
|
||||
|
||||
/**
|
||||
* @var SystemAttachmentDao
|
||||
*/
|
||||
#[Inject]
|
||||
protected SystemAttachmentDao $dao;
|
||||
|
||||
/**
|
||||
* 获取单个资源
|
||||
* @param array $where
|
||||
* @param string $field
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getInfo(array $where, string $field = '*')
|
||||
{
|
||||
return $this->dao->getOne($where, $field);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取图片列表
|
||||
* @param array $where
|
||||
* @return array
|
||||
*/
|
||||
public function getImageList(array $where)
|
||||
{
|
||||
[$page, $limit] = $this->getPageValue();
|
||||
$list = $this->dao->getList($where, $page, $limit);
|
||||
if ($list) {
|
||||
$site_url = sys_config('site_url');
|
||||
foreach ($list as &$item) {
|
||||
if ($item['file_type'] == 1) {
|
||||
if ($site_url) {
|
||||
$item['satt_dir'] = (strpos($item['satt_dir'], $site_url) !== false || strstr($item['satt_dir'], 'http') !== false) ? $item['satt_dir'] : $site_url . $item['satt_dir'];
|
||||
$item['att_dir'] = (strpos($item['att_dir'], $site_url) !== false || strstr($item['att_dir'], 'http') !== false) ? $item['satt_dir'] : $site_url . $item['att_dir'];
|
||||
}
|
||||
}
|
||||
$item['att_size'] = formatFileSize($item['att_size']);
|
||||
$item['time'] = date('Y-m-d H:i:s', $item['time']);
|
||||
}
|
||||
$list = get_thumb_water($list, 'mid', ['satt_dir']);
|
||||
}
|
||||
$where['module_type'] = 1;
|
||||
$count = $this->dao->count($where);
|
||||
return compact('list', 'count');
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除图片
|
||||
* @param string $ids
|
||||
*/
|
||||
public function del(string $ids)
|
||||
{
|
||||
$ids = explode(',', $ids);
|
||||
if (empty($ids)) throw new AdminException('请选择要删除的图片');
|
||||
foreach ($ids as $v) {
|
||||
$attinfo = $this->dao->get((int)$v);
|
||||
if ($attinfo) {
|
||||
try {
|
||||
$upload = UploadService::init($attinfo['image_type']);
|
||||
if ($attinfo['image_type'] == 1) {
|
||||
$fileArr = parse_url($attinfo['att_dir']);
|
||||
$filePath = $fileArr['path'] ?? $attinfo['att_dir'];
|
||||
if (strpos($filePath, '/') == 0) {
|
||||
$filePath = substr($filePath, 1);
|
||||
}
|
||||
if ($filePath) $upload->delete($filePath);
|
||||
} else {
|
||||
if ($attinfo['name']) $upload->delete($attinfo['name']);
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
}
|
||||
$this->dao->delete((int)$v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 图片上传
|
||||
* @param int $pid
|
||||
* @param string $file
|
||||
* @param int $upload_type
|
||||
* @param int $type
|
||||
* @return mixed
|
||||
*/
|
||||
public function upload(int $pid, string $file, int $upload_type, int $type)
|
||||
{
|
||||
if ($upload_type == 0) {
|
||||
$upload_type = (int)sys_config('upload_type', 1);
|
||||
}
|
||||
try {
|
||||
$path = make_path('attach', 2, true);
|
||||
$upload = UploadService::init($upload_type);
|
||||
$res = $upload->to($path)->setAuthThumb((bool)sys_config('image_thumb_status'))->validate()->move($file);
|
||||
if ($res === false) {
|
||||
throw new UploadException($upload->getError());
|
||||
} else {
|
||||
$fileInfo = $upload->getUploadInfo();
|
||||
//保存附件记录
|
||||
if ($type == 0) $this->saveAttachment($fileInfo, $pid, $type, 0, 1, $upload_type);
|
||||
return ['real_name' => $res->realName, 'src' => $res->filePath];
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
throw new UploadException($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
* @return \crmeb\basic\BaseModel
|
||||
*/
|
||||
public function move(array $data)
|
||||
{
|
||||
$res = $this->dao->move($data);
|
||||
if (!$res) throw new AdminException('移动失败或不能重复移动到同一分类下');
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加信息
|
||||
* @param array $data
|
||||
*/
|
||||
public function save(array $data)
|
||||
{
|
||||
$this->dao->save($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加附件记录
|
||||
* @param $name
|
||||
* @param $att_size
|
||||
* @param $att_type
|
||||
* @param $att_dir
|
||||
* @param string $satt_dir
|
||||
* @param int $pid
|
||||
* @param int $imageType
|
||||
* @param int $time
|
||||
* @return SystemAttachment
|
||||
*/
|
||||
public function attachmentAdd($name, $att_size, $att_type, $att_dir, $satt_dir = '', $pid = 0, $imageType = 1, $time = 0, $module_type = 1, $file_type = 1)
|
||||
{
|
||||
$data['name'] = $name;
|
||||
$data['att_dir'] = $att_dir;
|
||||
$data['satt_dir'] = $satt_dir;
|
||||
$data['att_size'] = $att_size;
|
||||
$data['att_type'] = $att_type;
|
||||
$data['image_type'] = $imageType;
|
||||
$data['module_type'] = $module_type;
|
||||
$data['time'] = $time ? $time : time();
|
||||
$data['pid'] = $pid;
|
||||
$data['file_type'] = $file_type;
|
||||
if (!$this->dao->save($data)) {
|
||||
throw new ValidateException('添加附件失败');
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 推广名片生成
|
||||
* @param $name
|
||||
*/
|
||||
public function getLikeNameList($name)
|
||||
{
|
||||
return $this->dao->getLikeNameList(['like_name' => $name], 0, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除昨日海报
|
||||
* @return bool
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function emptyYesterdayAttachment()
|
||||
{
|
||||
try {
|
||||
$list = $this->dao->getYesterday();
|
||||
foreach ($list as $key => $item) {
|
||||
$upload = UploadService::init((int)$item['image_type']);
|
||||
if ($item['image_type'] == 1) {
|
||||
$att_dir = $item['att_dir'];
|
||||
if ($att_dir && strstr($att_dir, 'uploads') !== false) {
|
||||
if (strstr($att_dir, 'http') === false) $upload->delete($att_dir); else {
|
||||
$filedir = substr($att_dir, strpos($att_dir, 'uploads'));
|
||||
if ($filedir) $upload->delete($filedir);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ($item['name']) $upload->delete($item['name']);
|
||||
}
|
||||
}
|
||||
$this->dao->delYesterday();
|
||||
return true;
|
||||
} catch (\Exception $e) {
|
||||
$this->dao->delYesterday();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 门店图片上传
|
||||
* @param int $pid
|
||||
* @param string $file
|
||||
* @param int $relationId
|
||||
* @param int $type
|
||||
* @return mixed
|
||||
*/
|
||||
public function storeUpload(int $pid, string $file, int $relationId, int $type = 2, int $upload_type = 0, string $uploadToken = '')
|
||||
{
|
||||
try {
|
||||
if ($upload_type == 0) {
|
||||
$upload_type = (int)sys_config('upload_type', 1);
|
||||
}
|
||||
$path = make_path('attach/' . ($type == 4 ? 'supplier' : ($type == 2 ? 'store' : '')), 2, true);
|
||||
$upload = UploadService::init($upload_type);
|
||||
$res = $upload->to($path)->validate()->setAuthThumb(true)->move($file);
|
||||
if ($res === false) {
|
||||
throw new UploadException($upload->getError());
|
||||
} else {
|
||||
$fileInfo = $upload->getUploadInfo();
|
||||
//保存附件记录
|
||||
$this->saveAttachment($fileInfo, $pid, $type, $relationId, 1, $upload_type, $uploadToken);
|
||||
return ['real_name' => $res->realName, 'src' => $res->filePath];
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
throw new UploadException($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 视频分片上传
|
||||
* @param $data
|
||||
* @param $file
|
||||
* @param int $type
|
||||
* @param int $relation_id
|
||||
* @return mixed
|
||||
*/
|
||||
public function videoUpload($data, $file, int $type = 1, int $relation_id = 0)
|
||||
{
|
||||
$data['chunkNumber'] = (int)$data['chunkNumber'];
|
||||
$public_dir = app()->getRootPath() . 'public';
|
||||
$store_dir = '';
|
||||
switch ($type) {
|
||||
case 2:
|
||||
$store_dir = 'store' . DIRECTORY_SEPARATOR;
|
||||
break;
|
||||
case 4:
|
||||
$store_dir = 'supplier' . DIRECTORY_SEPARATOR;
|
||||
break;
|
||||
}
|
||||
$dir = '/uploads/video/' . $store_dir . date('Y') . DIRECTORY_SEPARATOR . date('m') . DIRECTORY_SEPARATOR . date('d');
|
||||
$all_dir = $public_dir . $dir;
|
||||
if (!is_dir($all_dir)) mkdir($all_dir, 0777, true);
|
||||
$filename = $all_dir . '/' . $data['filename'] . '__' . $data['chunkNumber'];
|
||||
move_uploaded_file($file->getPathName(), $filename);
|
||||
$res['code'] = 0;
|
||||
$res['msg'] = 'error';
|
||||
$res['file_path'] = '';
|
||||
if ($data['chunkNumber'] == $data['totalChunks']) {
|
||||
$blob = '';
|
||||
for ($i = 1; $i <= $data['totalChunks']; $i++) {
|
||||
$blob .= file_get_contents($all_dir . '/' . $data['filename'] . '__' . $i);
|
||||
}
|
||||
file_put_contents($all_dir . '/' . $data['filename'], $blob);
|
||||
for ($i = 1; $i <= $data['totalChunks']; $i++) {
|
||||
@unlink($all_dir . '/' . $data['filename'] . '__' . $i);
|
||||
}
|
||||
if (file_exists($all_dir . '/' . $data['filename'])) {
|
||||
$res['code'] = 2;
|
||||
$res['msg'] = 'success';
|
||||
$res['file_path'] = $dir . '/' . $data['filename'];
|
||||
}
|
||||
} else {
|
||||
if (file_exists($all_dir . '/' . $data['filename'] . '__' . $data['chunkNumber'])) {
|
||||
$res['code'] = 1;
|
||||
$res['msg'] = 'waiting';
|
||||
$res['file_path'] = '';
|
||||
}
|
||||
}
|
||||
$res['name'] = $res['dir'] = $res['file_path'];
|
||||
if (strpos($res['file_path'], 'http') === false) {
|
||||
$res['dir'] = $res['file_path'] = sys_config('site_url') . $res['file_path'];
|
||||
}
|
||||
if ($res['code'] == 2) {
|
||||
$res['size'] = getFileHeaders($res['file_path'])['size'] ?? 0;
|
||||
$this->saveAttachment($res, (int)($data['pid'] ?? 0), $type, $relation_id, 2);
|
||||
}
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* 云端上传的视频保存记录
|
||||
* @param array $data
|
||||
* @param int $type
|
||||
* @param int $relation_id
|
||||
* @param int $upload_type
|
||||
* @return bool
|
||||
*/
|
||||
public function saveOssVideoAttachment(array $data, int $type = 1, int $relation_id = 0, int $upload_type = 1)
|
||||
{
|
||||
$fileInfo = [];
|
||||
$fileInfo['name'] = $data['path'];
|
||||
$fileInfo['cover_image'] = $data['cover_image'];
|
||||
if (!$fileInfo['cover_image'] && $upload_type != 1) {//云端视频
|
||||
$res = UploadService::init($upload_type)->videoCoverImage($data['path'], 'mid');
|
||||
$fileInfo['cover_image'] = $res['mid'] ?? '';
|
||||
}
|
||||
$fileInfo['size'] = getFileHeaders($data['path'])['size'] ?? 0;
|
||||
if ($upload_type != 1) {
|
||||
$config = app()->make(SystemStorageServices::class)->getConfig($upload_type);
|
||||
$uploadUrl = $config['domain'];
|
||||
$parsedUrl = parse_url($fileInfo['name']);
|
||||
$path = $parsedUrl['path'] ?? '';
|
||||
$fileInfo['name'] = rtrim($uploadUrl, '/') . $path;
|
||||
}
|
||||
$fileInfo['real_name'] = $fileInfo['name'];
|
||||
$this->saveAttachment($fileInfo, (int)$data['pid'], $type, $relation_id, 2, $upload_type);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存附件信息
|
||||
* @param $fileInfo
|
||||
* @param int $pid
|
||||
* @param int $type
|
||||
* @param int $relation_id
|
||||
* @param int $file_type
|
||||
* @param int $upload_type
|
||||
* @return bool
|
||||
*/
|
||||
public function saveAttachment($fileInfo, int $pid = 0, int $type = 1, int $relation_id = 0, int $file_type = 1, int $upload_type = 1)
|
||||
{
|
||||
$fileType = pathinfo($fileInfo['name'], PATHINFO_EXTENSION);
|
||||
if ($fileInfo && !in_array($fileType, ['xlsx', 'xls'])) {
|
||||
$data['file_type'] = $file_type;
|
||||
$data['type'] = $type == 0 ? 1 : $type;
|
||||
$data['relation_id'] = $relation_id;
|
||||
$data['name'] = $fileInfo['name'];
|
||||
$data['real_name'] = $fileInfo['real_name'] ?? $fileInfo['name'] ?? '';
|
||||
$data['att_dir'] = $fileInfo['dir'] ?? $fileInfo['name'] ?? '';
|
||||
if ($data['att_dir'] && strpos($data['att_dir'], 'http') === false) {
|
||||
$data['att_dir'] = sys_config('site_url') . $data['att_dir'];
|
||||
}
|
||||
$data['satt_dir'] = $fileInfo['thumb_path'] ?? $fileInfo['cover_image'] ?? '';
|
||||
if ($file_type == 2) {
|
||||
if (!$data['satt_dir']) {//视频 默认封面
|
||||
$data['satt_dir'] = sys_config('site_url') . '/statics/images/video_default_cover.png';
|
||||
}
|
||||
if ($data['real_name'] && strpos($data['real_name'], '/') !== false) {
|
||||
$nameArr = explode('/', $data['real_name']);
|
||||
$data['real_name'] = end($nameArr) ?? $data['real_name'];
|
||||
}
|
||||
}
|
||||
|
||||
$data['att_size'] = $fileInfo['size'] ?? '';
|
||||
$data['att_type'] = $fileInfo['type'] ?? '';
|
||||
$data['image_type'] = $upload_type;
|
||||
$data['module_type'] = 1;
|
||||
$data['time'] = $fileInfo['time'] ?? time();
|
||||
$data['pid'] = $pid;
|
||||
$this->dao->save($data);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 网络图片上传
|
||||
* @param $data
|
||||
* @return bool
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function onlineUpload(array $data, int $type = 1, int $relation_id = 0)
|
||||
{
|
||||
//生成附件目录
|
||||
if (make_path('attach', 3, true) === '') {
|
||||
throw new AdminException('无法创建文件夹,请检查您的上传目录权限');
|
||||
}
|
||||
|
||||
//上传图片
|
||||
/** @var SystemAttachmentServices $systemAttachmentService */
|
||||
$systemAttachmentService = app()->make(SystemAttachmentServices::class);
|
||||
$siteUrl = sys_config('site_url');
|
||||
|
||||
foreach ($data['images'] as $image) {
|
||||
try {
|
||||
$uploadValue = app()->make(DownloadImageService::class)->thumb(true)->downloadOnlineImage($image);
|
||||
} catch (\Throwable $e) {
|
||||
throw new AdminException('文件下载失败,请更换链接');
|
||||
}
|
||||
|
||||
if (is_array($uploadValue)) {
|
||||
//TODO 拼接图片地址
|
||||
if ($uploadValue['image_type'] == 1) {
|
||||
$imagePath = $siteUrl . $uploadValue['path'];
|
||||
} else {
|
||||
$imagePath = $uploadValue['path'];
|
||||
}
|
||||
//写入数据库
|
||||
if (!$uploadValue['is_exists']) {
|
||||
$systemAttachmentService->save([
|
||||
'type' => $type == 0 ? 1 : $type,
|
||||
'relation_id' => $relation_id,
|
||||
'name' => $uploadValue['name'],
|
||||
'real_name' => $uploadValue['name'],
|
||||
'att_dir' => $imagePath,
|
||||
'satt_dir' => $imagePath,
|
||||
'att_size' => $uploadValue['size'],
|
||||
'att_type' => $uploadValue['mime'],
|
||||
'image_type' => $uploadValue['image_type'],
|
||||
'module_type' => 1,
|
||||
'time' => time(),
|
||||
'pid' => $data['pid']
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除门店、供应商附件
|
||||
* @param array $where
|
||||
* @param int $type
|
||||
* @param int $relation_id
|
||||
* @return bool
|
||||
*/
|
||||
public function delAttachment(array $where = [], int $type = 0, int $relation_id = 0)
|
||||
{
|
||||
$where['type'] = $type;
|
||||
$where['relation_id'] = $relation_id;
|
||||
//删除附件
|
||||
$attachments = $this->dao->getColumn($where, 'att_id');
|
||||
if ($attachments) {
|
||||
$idsArr = array_chunk($attachments, 100);
|
||||
foreach ($idsArr as $ids) {
|
||||
$this->del(implode(',', $ids));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
130
app/services/system/config/ConfigServices.php
Normal file
130
app/services/system/config/ConfigServices.php
Normal file
@@ -0,0 +1,130 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\services\system\config;
|
||||
|
||||
|
||||
use app\dao\store\StoreConfigDao;
|
||||
use app\services\BaseServices;
|
||||
use crmeb\services\SystemConfigService;
|
||||
|
||||
/**
|
||||
* Class ConfigServices
|
||||
* @package app\services\system\config
|
||||
* @mixin StoreConfigDao
|
||||
*/
|
||||
class ConfigServices extends BaseServices
|
||||
{
|
||||
//打印机类型
|
||||
const PRINTER_NAME = [
|
||||
1 => 'yi_lian_yun',
|
||||
2 => 'fei_e_yun',
|
||||
];
|
||||
|
||||
//平台打印机配置
|
||||
const PRINTER_KEY = [
|
||||
'switch' => 'pay_success_printing_switch',
|
||||
'print_type' => 'print_type',
|
||||
'printing_client_id', 'printing_api_key', 'develop_id', 'terminal_number',
|
||||
'fey_user', 'fey_ukey', 'fey_sn',
|
||||
];
|
||||
//配置字段对应
|
||||
const PRINTER_CONFIG_KEY = [
|
||||
'yi_lian_yun' => ['printing_client_id' => 'clientId', 'printing_api_key' => 'apiKey', 'develop_id' => 'partner', 'terminal_number' => 'terminal'],
|
||||
'fei_e_yun' => ['fey_user' => 'feyUser', 'fey_ukey' => 'feyUkey', 'fey_sn' => 'feySn'],
|
||||
];
|
||||
|
||||
//门店打印机配置
|
||||
const STORE_PRINTER_KEY = [
|
||||
'switch' => 'store_pay_success_printing_switch',
|
||||
'print_type' => 'store_print_type',
|
||||
'store_printing_client_id', 'store_printing_api_key', 'store_develop_id', 'store_terminal_number',
|
||||
'store_fey_user', 'store_fey_ukey', 'store_fey_sn',
|
||||
];
|
||||
|
||||
//门店配置字段对应
|
||||
const STORE_PRINTER_CONFIG_KEY = [
|
||||
'yi_lian_yun' => ['store_printing_client_id' => 'clientId', 'store_printing_api_key' => 'apiKey', 'store_develop_id' => 'partner', 'store_terminal_number' => 'terminal'],
|
||||
'fei_e_yun' => ['store_fey_user' => 'feyUser', 'store_fey_ukey' => 'feyUkey', 'store_fey_sn' => 'feySn'],
|
||||
];
|
||||
|
||||
//供应商打印机配置
|
||||
const SUPPLIER_PRINTER_KEY = [
|
||||
'switch' => 'store_pay_success_printing_switch',
|
||||
'print_type' => 'store_print_type',
|
||||
'store_printing_client_id', 'store_printing_api_key', 'store_develop_id', 'store_terminal_number',
|
||||
'store_fey_user', 'store_fey_ukey', 'store_fey_sn',
|
||||
];
|
||||
|
||||
//供应商配置字段对应
|
||||
const SUPPLIER_PRINTER_CONFIG_KEY = [
|
||||
'yi_lian_yun' => ['store_printing_client_id' => 'clientId', 'store_printing_api_key' => 'apiKey', 'store_develop_id' => 'partner', 'store_terminal_number' => 'terminal'],
|
||||
'fei_e_yun' => ['store_fey_user' => 'feyUser', 'store_fey_ukey' => 'feyUkey', 'store_fey_sn' => 'feySn'],
|
||||
];
|
||||
|
||||
const CONFIG_TYPE = [
|
||||
'printing_deploy' => self::PRINTER_KEY,
|
||||
'store_printing_deploy' => self::STORE_PRINTER_KEY,
|
||||
'supplier_printing_deploy' => self::SUPPLIER_PRINTER_KEY
|
||||
];
|
||||
|
||||
/**
|
||||
* StoreConfigServices constructor.
|
||||
* @param StoreConfigDao $dao
|
||||
*/
|
||||
public function __construct(StoreConfigDao $dao)
|
||||
{
|
||||
$this->dao = $dao;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取小票打印配置
|
||||
* @param int $type
|
||||
* @param int $relation_id
|
||||
* @return array
|
||||
*/
|
||||
public function getPrintingConfig(int $type = 0, int $relation_id = 0) : array
|
||||
{
|
||||
/** @var SystemConfigService $configService */
|
||||
$configService = app('sysConfig');
|
||||
switch ($type) {
|
||||
case 0://平台
|
||||
$keys = self::PRINTER_KEY;
|
||||
$configKey = self::PRINTER_CONFIG_KEY;
|
||||
break;
|
||||
case 2://供应商
|
||||
$keys = self::SUPPLIER_PRINTER_KEY;
|
||||
$configKey = self::SUPPLIER_PRINTER_CONFIG_KEY;
|
||||
$configService->setSupplier($relation_id);
|
||||
break;
|
||||
default:
|
||||
$keys = self::PRINTER_KEY;
|
||||
$configKey = self::PRINTER_CONFIG_KEY;
|
||||
break;
|
||||
}
|
||||
$key = array_values($keys);
|
||||
$config = $configService->more($key);
|
||||
$switch = $config[$keys['switch']] ?? 0;
|
||||
$printType = $config[$keys['print_type']] ?? 1;
|
||||
$name = self::PRINTER_NAME[$printType] ?? 'yi_lian_yun';
|
||||
$configKey = $configKey[$name];
|
||||
$configData = [];
|
||||
foreach ($config as $key => $value) {
|
||||
if (isset($configKey[$key])) {
|
||||
$configData[$configKey[$key]] = $value;
|
||||
}
|
||||
}
|
||||
return [$switch, $name, $configData];
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
2867
app/services/system/config/SystemConfigServices.php
Normal file
2867
app/services/system/config/SystemConfigServices.php
Normal file
File diff suppressed because it is too large
Load Diff
140
app/services/system/config/SystemConfigTabServices.php
Normal file
140
app/services/system/config/SystemConfigTabServices.php
Normal file
@@ -0,0 +1,140 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\services\system\config;
|
||||
|
||||
|
||||
use app\dao\system\config\SystemConfigTabDao;
|
||||
use app\services\BaseServices;
|
||||
use crmeb\exceptions\AdminException;
|
||||
use crmeb\services\FormBuilder as Form;
|
||||
use think\annotation\Inject;
|
||||
|
||||
/**
|
||||
* 系统配置分类
|
||||
* Class SystemConfigTabServices
|
||||
* @package app\services\system\config
|
||||
* @mixin SystemConfigTabDao
|
||||
*/
|
||||
class SystemConfigTabServices extends BaseServices
|
||||
{
|
||||
/**
|
||||
* @var SystemConfigTabDao
|
||||
*/
|
||||
#[Inject]
|
||||
protected SystemConfigTabDao $dao;
|
||||
|
||||
/**
|
||||
* 系统设置头部分类读取
|
||||
* @param int $pid
|
||||
* @param int $is_store
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getConfigTab(int $pid, int $is_store = 0)
|
||||
{
|
||||
$list = $this->dao->getConfigTabAll(['status' => 1, 'pid' => $pid, 'is_store' => $is_store], ['id', 'id as value', 'title as label', 'pid', 'icon', 'type'], $pid ? [] : [['type', '=', '0']]);
|
||||
return get_tree_children($list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取配置分类列表
|
||||
* @param array $where
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getConfgTabList(array $where)
|
||||
{
|
||||
[$page, $limit] = $this->getPageValue();
|
||||
$list = $this->dao->getConfgTabList($where, $page, $limit);
|
||||
$count = $this->dao->count($where);
|
||||
$menusValue = [];
|
||||
foreach ($list as $item) {
|
||||
$menusValue[] = $item->getData();
|
||||
}
|
||||
$list = get_tree_children($menusValue);
|
||||
return compact('list', 'count');
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取配置分类选择下拉树
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getSelectForm()
|
||||
{
|
||||
$menuList = $this->dao->getConfigTabAll([], ['id as value', 'pid', 'title as label']);
|
||||
$menus = [['value' => 0, 'label' => '顶级按钮']];
|
||||
$list = get_tree_children($menuList, 'children', 'value');
|
||||
$menus = array_merge($menus, $list);
|
||||
// foreach ($list as $menu) {
|
||||
// $menus[] = ['value' => $menu['id'], 'label' => $menu['html'] . $menu['title']];
|
||||
// }
|
||||
return $menus;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建form表单
|
||||
* @param array $formData
|
||||
* @return array
|
||||
* @throws \FormBuilder\Exception\FormBuilderException
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function createConfigTabForm(array $formData = [])
|
||||
{
|
||||
$pid[] = isset($formData['pid']) ? $formData['pid'] : 0;
|
||||
// $form[] = Form::radio('is_store', '类型', $formData['is_store'] ?? 0)->options([['value' => 0, 'label' => '总后台'], ['value' => 1, 'label' => '门店后台']]);
|
||||
$form[] = Form::cascader('pid', '父级分类:', $pid)->data($this->getSelectForm())->changeOnSelect(true);
|
||||
$form[] = Form::input('title', '分类名称:', $formData['title'] ?? '');
|
||||
$form[] = Form::input('eng_title', '分类字段英文:', $formData['eng_title'] ?? '');
|
||||
$form[] = Form::frameInput('icon', '图标:', $this->url('admin/widget.widgets/icon', ['fodder' => 'icon'], true), $formData['icon'] ?? '')->icon('ios-ionic')->height('435px');
|
||||
$form[] = Form::radio('type', '类型:', $formData['type'] ?? 0)->options([
|
||||
['value' => 0, 'label' => '系统'],
|
||||
['value' => 3, 'label' => '其它']
|
||||
]);
|
||||
$form[] = Form::radio('status', '状态:', $formData['status'] ?? 1)->options([['value' => 1, 'label' => '显示'], ['value' => 2, 'label' => '隐藏']]);
|
||||
$form[] = Form::number('sort', '排序:', (int)($formData['sort'] ?? 0))->min(0);
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加配置分类表单
|
||||
* @return array
|
||||
* @throws \FormBuilder\Exception\FormBuilderException
|
||||
*/
|
||||
public function createForm()
|
||||
{
|
||||
return create_form('添加配置分类', $this->createConfigTabForm(), $this->url('/setting/config_class'));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改配置分类表单
|
||||
* @param int $id
|
||||
* @return array
|
||||
* @throws \FormBuilder\Exception\FormBuilderException
|
||||
*/
|
||||
public function updateForm(int $id)
|
||||
{
|
||||
$configTabInfo = $this->dao->get($id);
|
||||
if (!$configTabInfo) {
|
||||
throw new AdminException('没有查到数据,无法修改!');
|
||||
}
|
||||
return create_form('编辑配置分类', $this->createConfigTabForm($configTabInfo->toArray()), $this->url('/setting/config_class/' . $id), 'PUT');
|
||||
}
|
||||
}
|
||||
385
app/services/system/config/SystemGroupDataServices.php
Normal file
385
app/services/system/config/SystemGroupDataServices.php
Normal file
@@ -0,0 +1,385 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\services\system\config;
|
||||
|
||||
use app\dao\system\config\SystemGroupDataDao;
|
||||
use app\services\BaseServices;
|
||||
use crmeb\exceptions\AdminException;
|
||||
use crmeb\services\FormBuilder as Form;
|
||||
use think\annotation\Inject;
|
||||
|
||||
/**
|
||||
* 组合数据数据集
|
||||
* Class SystemGroupDataServices
|
||||
* @package app\services\system\config
|
||||
* @mixin SystemGroupDataDao
|
||||
*/
|
||||
class SystemGroupDataServices extends BaseServices
|
||||
{
|
||||
|
||||
/**
|
||||
* @var SystemGroupDataDao
|
||||
*/
|
||||
#[Inject]
|
||||
protected SystemGroupDataDao $dao;
|
||||
|
||||
/**
|
||||
* @param int $id
|
||||
* @return mixed|string
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
* @author 等风来
|
||||
* @email 136327134@qq.com
|
||||
* @date 2022/11/3
|
||||
*/
|
||||
public function cacheInfoValue(int $id)
|
||||
{
|
||||
$groupData = $this->cacheRemember($id, function () use ($id) {
|
||||
$res = $this->dao->get($id);
|
||||
return $res ? $res->toArray() : null;
|
||||
});
|
||||
|
||||
return $groupData['value'] ?? '';
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取某个配置下的数据从新组合成新得数据返回
|
||||
* @param string $configName
|
||||
* @param int $limit
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getConfigNameValue(string $configName, int $limit = 0)
|
||||
{
|
||||
/** @var SystemGroupServices $systemGroupServices */
|
||||
$systemGroupServices = app()->make(SystemGroupServices::class);
|
||||
$value = $this->dao->getGroupDate((int)$systemGroupServices->getConfigNameId($configName), $limit);
|
||||
$data = [];
|
||||
foreach ($value as $key => $item) {
|
||||
$data[$key]["id"] = $item["id"];
|
||||
if (isset($item['status'])) $data[$key]["status"] = $item["status"];
|
||||
$fields = json_decode($item["value"], true) ?: [];
|
||||
foreach ($fields as $index => $field) {
|
||||
if ($field['type'] == 'upload') {
|
||||
$data[$key][$index] = set_file_url($field['value']);
|
||||
} else {
|
||||
$data[$key][$index] = $field["value"];
|
||||
}
|
||||
}
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取组合数据列表
|
||||
* @param array $where
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getGroupDataList(array $where)
|
||||
{
|
||||
[$page, $limit] = $this->getPageValue();
|
||||
$list = $this->dao->getGroupDataList($where, $page, $limit);
|
||||
$count = $this->dao->count($where);
|
||||
$type = '';
|
||||
$gid = (int)$where['gid'];
|
||||
/** @var SystemGroupServices $services */
|
||||
$services = app()->make(SystemGroupServices::class);
|
||||
$group = $services->getOne(['id' => $gid], 'id,config_name,fields');
|
||||
|
||||
$header = json_decode($group['fields'], true) ?? [];
|
||||
$title = [];
|
||||
$param = [];
|
||||
foreach ($header as $item) {
|
||||
if ($group['config_name'] == 'order_details_images' && $item['title'] == 'order_status') {
|
||||
$status = str_replace("\r\n", "\n", $item["param"]);//防止不兼容
|
||||
$status = explode("\n", $status);
|
||||
if (is_array($status) && !empty($status)) {
|
||||
foreach ($status as $index => $v) {
|
||||
$vl = explode('=>', $v);
|
||||
if (isset($vl[0]) && isset($vl[1])) {
|
||||
$param[$vl[0]] = $vl[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($item['type'] == 'upload' || $item['type'] == 'uploads') {
|
||||
$title[$item['title']] = [];
|
||||
$type = $item['title'];
|
||||
} else {
|
||||
$title[$item['title']] = '';
|
||||
}
|
||||
}
|
||||
foreach ($list as $key => $value) {
|
||||
$list[$key] = array_merge($value, $title);
|
||||
$infos = json_decode($value['value'], true) ?: [];
|
||||
|
||||
foreach ($infos as $index => $info) {
|
||||
if ($group['config_name'] == 'user_recharge_quota' && $index == 'is_welfare') {
|
||||
$info['value'] = $info['value'] == 1 ? '是' : '否';
|
||||
}
|
||||
if ($group['config_name'] == 'order_details_images' && $index == 'order_status') {
|
||||
$list[$key][$index] = ($param[$info['value']] ?? '') . '/' . $info['value'];
|
||||
} else {
|
||||
if ($info['type'] == 'upload') {
|
||||
$list[$key][$index] = [set_file_url($info['value'])];
|
||||
} elseif ($info['type'] == 'checkbox') {
|
||||
$list[$key][$index] = implode(",", $info["value"]);
|
||||
} else {
|
||||
$list[$key][$index] = $info['value'];
|
||||
}
|
||||
}
|
||||
}
|
||||
unset($list[$key]['value']);
|
||||
}
|
||||
return compact('list', 'count', 'type', 'gid');
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据gid判断出是否能再次添加组合数据
|
||||
* @param int $gid
|
||||
* @param int $count
|
||||
* @param string $key
|
||||
* @return bool
|
||||
*/
|
||||
public function isGroupGidSave(int $gid, int $count, string $key): bool
|
||||
{
|
||||
/** @var SystemGroupServices $services */
|
||||
$services = app()->make(SystemGroupServices::class);
|
||||
$configName = $services->value(['id' => $gid], 'config_name');
|
||||
if ($configName == $key) {
|
||||
return $this->dao->count(['gid' => $gid]) >= $count;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建表单
|
||||
* @param int $gid
|
||||
* @param array $groupData
|
||||
* @return mixed
|
||||
* @throws \FormBuilder\Exception\FormBuilderException
|
||||
*/
|
||||
public function createGroupForm(int $gid, array $groupData = [])
|
||||
{
|
||||
$groupDataValue = isset($groupData["value"]) ? json_decode($groupData["value"], true) : [];
|
||||
/** @var SystemGroupServices $services */
|
||||
$services = app()->make(SystemGroupServices::class);
|
||||
$configName = $services->value(['id' => $gid], 'config_name');
|
||||
$fields = $services->getValueFields($gid);
|
||||
$f[] = Form::hidden('gid', $gid);
|
||||
foreach ($fields as $key => $value) {
|
||||
$info = [];
|
||||
if (isset($value["param"])) {
|
||||
$value["param"] = str_replace("\r\n", "\n", $value["param"]);//防止不兼容
|
||||
$params = explode("\n", $value["param"]);
|
||||
if (is_array($params) && !empty($params)) {
|
||||
foreach ($params as $index => $v) {
|
||||
$vl = explode('=>', $v);
|
||||
if (isset($vl[0]) && isset($vl[1])) {
|
||||
$info[$index]["value"] = $vl[0];
|
||||
$info[$index]["label"] = $vl[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$fvalue = isset($groupDataValue[$value['title']]['value']) ? $groupDataValue[$value['title']]['value'] : '';
|
||||
switch ($value["type"]) {
|
||||
case 'input':
|
||||
if (($gid == 55 && $value['title'] == 'sign_num') || in_array($configName, ['user_recharge_quota'])) {
|
||||
if ('user_recharge_quota' === $configName) {
|
||||
$f[] = Form::number($value["title"], $value["name"] . ':', $fvalue)->min(0)->max(999999)->required();
|
||||
} else {
|
||||
$f[] = Form::number($value["title"], $value["name"] . ':', (int)$fvalue)->precision(0);
|
||||
}
|
||||
} else {
|
||||
$f[] = Form::input($value["title"], $value["name"] . ':', $fvalue);
|
||||
}
|
||||
break;
|
||||
case 'textarea':
|
||||
$f[] = Form::input($value["title"], $value["name"] . ':', $fvalue)->type('textarea')->placeholder($value['param']);
|
||||
break;
|
||||
case 'radio':
|
||||
$f[] = Form::radio($value["title"], $value["name"] . ':', $fvalue ?: $info[0]["value"] ?? '')->options($info);
|
||||
break;
|
||||
case 'checkbox':
|
||||
$f[] = Form::checkbox($value["title"], $value["name"] . ':', $fvalue ?: $info[0] ?? '')->options($info);
|
||||
break;
|
||||
case 'select':
|
||||
$f[] = Form::select($value["title"], $value["name"] . ':', $fvalue !== '' ? $fvalue : $info[0] ?? '')->options($info)->multiple(false);
|
||||
break;
|
||||
case 'upload':
|
||||
if (!empty($fvalue)) {
|
||||
$image = is_string($fvalue) ? $fvalue : $fvalue[0];
|
||||
} else {
|
||||
$image = '';
|
||||
}
|
||||
$f[] = Form::frameImage($value["title"], $value["name"] . ':', $this->url('admin/widget.images/index', ['fodder' => $value["title"], 'big' => 1], true), $image)->icon('ios-image')->width('960px')->height('505px')->modal(['footer-hide' => true]);
|
||||
break;
|
||||
case 'uploads':
|
||||
if ($fvalue) {
|
||||
if (is_string($fvalue)) $fvalue = [$fvalue];
|
||||
$images = !empty($fvalue) ? $fvalue : [];
|
||||
} else {
|
||||
$images = [];
|
||||
}
|
||||
$f[] = Form::frameImages($value["title"], $value["name"] . ':', $this->url('admin/widget.images/index', ['fodder' => $value["title"], 'big' => 1, 'type' => 'many', 'maxLength' => 5], true), $images)->maxLength(5)->icon('ios-images')->width('960px')->height('505px')->modal(['footer-hide' => true])->spin(0);
|
||||
break;
|
||||
default:
|
||||
$f[] = Form::input($value["title"], $value["name"] . ':', $fvalue);
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
$f[] = Form::number('sort', '排序:', (int)($groupData["sort"] ?? 1))->min(0);
|
||||
$f[] = Form::radio('status', '状态:', (int)($groupData["status"] ?? 1))->options([['value' => 1, 'label' => '显示'], ['value' => 0, 'label' => '隐藏']]);
|
||||
return $f;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取添加组合数据表单
|
||||
* @param int $gid
|
||||
* @return array
|
||||
* @throws \FormBuilder\Exception\FormBuilderException
|
||||
*/
|
||||
public function createForm(int $gid)
|
||||
{
|
||||
return create_form('添加数据', $this->createGroupForm($gid), $this->url('/setting/group_data'));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取修改组合数据表单
|
||||
* @param int $gid
|
||||
* @param int $id
|
||||
* @return array
|
||||
* @throws \FormBuilder\Exception\FormBuilderException
|
||||
*/
|
||||
public function updateForm(int $gid, int $id)
|
||||
{
|
||||
$groupData = $this->dao->get($id);
|
||||
if (!$groupData) {
|
||||
throw new AdminException('修改失败未查到数据!');
|
||||
}
|
||||
return create_form('编辑数据', $this->createGroupForm($gid, $groupData->toArray()), $this->url('/setting/group_data/' . $id), 'PUT');
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据id获取当前记录中的数据
|
||||
* @param $id
|
||||
* @return mixed
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
* @throws \think\exception\DbException
|
||||
*/
|
||||
public function getDateValue($id)
|
||||
{
|
||||
$value = $this->dao->get($id);
|
||||
$data = [];
|
||||
if ($value) {
|
||||
$data["id"] = $value["id"];
|
||||
$data["status"] = $value["status"];
|
||||
$fields = json_decode($value["value"], true);
|
||||
foreach ($fields as $index => $field) {
|
||||
$data[$index] = $field["value"];
|
||||
}
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据id获取数据
|
||||
* @param array $ids
|
||||
* @param string $field
|
||||
*/
|
||||
public function getGroupDataColumn(array $ids)
|
||||
{
|
||||
$systemGroup = [];
|
||||
if (!empty($ids)) {
|
||||
$systemGroupData = $this->dao->idByGroupList($ids);
|
||||
if (!empty($systemGroupData))
|
||||
$systemGroup = array_combine(array_column($systemGroupData, 'id'), $systemGroupData);
|
||||
}
|
||||
return $systemGroup;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加数据配置
|
||||
* @param $data
|
||||
*/
|
||||
public function saveAll(array $data)
|
||||
{
|
||||
return $this->dao->saveAll($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据gid删除数据
|
||||
* @param int $gid
|
||||
* @return mixed
|
||||
*/
|
||||
public function delGroupDate(int $gid)
|
||||
{
|
||||
return $this->dao->delGroupDate($gid);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量保存组合数据
|
||||
* @param array $params 数据参数
|
||||
* @param string $config_name 配置名称
|
||||
* @return bool
|
||||
* @throws AdminException
|
||||
*/
|
||||
public function saveAllData(array $params, string $config_name)
|
||||
{
|
||||
/** @var SystemGroupServices $systemGroupServices */
|
||||
$systemGroupServices = app()->make(SystemGroupServices::class);
|
||||
$gid = $systemGroupServices->value(['config_name' => $config_name], 'id');
|
||||
$group = $systemGroupServices->getOne(['id' => $gid], 'id,config_name,fields');
|
||||
$fields = json_decode($group['fields'], true) ?? [];
|
||||
$this->transaction(function () use ($gid, $params, $fields) {
|
||||
$this->delGroupDate($gid);
|
||||
$data = [];
|
||||
$sort = count($params);
|
||||
foreach ($params as $k => $v) {
|
||||
$value = [];
|
||||
foreach ($v as $key => $param) {
|
||||
foreach ($fields as $index => $field) {
|
||||
if ($key == $field["title"]) {
|
||||
if ($param == "")
|
||||
throw new AdminException($field["name"] . "不能为空!");
|
||||
else {
|
||||
$value[$key]["type"] = $field["type"];
|
||||
$value[$key]["value"] = $param;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$data[$k] = [
|
||||
"gid" => $gid,
|
||||
"add_time" => time(),
|
||||
"value" => json_encode($value),
|
||||
"sort" => $sort,
|
||||
"status" => $v["status"] ?? 1
|
||||
];
|
||||
$sort--;
|
||||
}
|
||||
$this->dao->saveAll($data);
|
||||
});
|
||||
\crmeb\services\GroupDataService::clear();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
93
app/services/system/config/SystemGroupServices.php
Normal file
93
app/services/system/config/SystemGroupServices.php
Normal file
@@ -0,0 +1,93 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\services\system\config;
|
||||
|
||||
use app\dao\system\config\SystemGroupDao;
|
||||
use app\services\BaseServices;
|
||||
use think\annotation\Inject;
|
||||
|
||||
/**
|
||||
* 组合数据
|
||||
* Class SystemGroupServices
|
||||
* @package app\services\system\config
|
||||
* @mixin SystemGroupDao
|
||||
*/
|
||||
class SystemGroupServices extends BaseServices
|
||||
{
|
||||
|
||||
/**
|
||||
* @var SystemGroupDao
|
||||
*/
|
||||
#[Inject]
|
||||
protected SystemGroupDao $dao;
|
||||
|
||||
/**
|
||||
* 获取组合数据列表
|
||||
* @param array $where
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getGroupList(array $where, array $field = ['*'])
|
||||
{
|
||||
[$page, $limit] = $this->getPageValue();
|
||||
$list = $this->dao->getGroupList($where, $field, $page, $limit);
|
||||
$count = $this->dao->count($where);
|
||||
foreach ($list as $key => $value) {
|
||||
if (isset($value['fields'])) {
|
||||
$list[$key]['typelist'] = $value['fields'];
|
||||
unset($list[$key]['fields']);
|
||||
}
|
||||
}
|
||||
return compact('list', 'count');
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取组合数据tab下的header头部
|
||||
* @param int $id
|
||||
* @return array
|
||||
*/
|
||||
public function getGroupDataTabHeader(int $id)
|
||||
{
|
||||
$data = $this->getValueFields($id);
|
||||
$header = [];
|
||||
foreach ($data as $key => $item) {
|
||||
if ($item['type'] == 'upload' || $item['type'] == 'uploads') {
|
||||
$header[$key]['key'] = $item['title'];
|
||||
$header[$key]['minWidth'] = 60;
|
||||
$header[$key]['type'] = 'img';
|
||||
} elseif ($item['title'] == 'url' || $item['title'] == 'wap_url' || $item['title'] == 'link' || $item['title'] == 'wap_link') {
|
||||
$header[$key]['key'] = $item['title'];
|
||||
$header[$key]['minWidth'] = 200;
|
||||
} else {
|
||||
$header[$key]['key'] = $item['title'];
|
||||
$header[$key]['minWidth'] = 100;
|
||||
}
|
||||
$header[$key]['title'] = $item['name'];
|
||||
}
|
||||
array_unshift($header, ['key' => 'id', 'title' => '编号', 'width' => 55]);
|
||||
array_push($header, ['slot' => 'status', 'title' => '是否可用', 'minWidth' => 80], ['key' => 'sort', 'title' => '排序', 'minWidth' => 80], ['slot' => 'action', 'fixed' => 'right', 'title' => '操作', 'minWidth' => 120]);
|
||||
return compact('header');
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取组合数据fields字段
|
||||
* @param int $id
|
||||
* @return array|mixed
|
||||
*/
|
||||
public function getValueFields(int $id)
|
||||
{
|
||||
return json_decode($this->dao->value(['id' => $id], 'fields'), true) ?: [];
|
||||
}
|
||||
|
||||
}
|
||||
597
app/services/system/config/SystemStorageServices.php
Normal file
597
app/services/system/config/SystemStorageServices.php
Normal file
@@ -0,0 +1,597 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\services\system\config;
|
||||
|
||||
|
||||
use app\dao\system\config\SystemStorageDao;
|
||||
use app\services\BaseServices;
|
||||
use crmeb\services\FormBuilder;
|
||||
use crmeb\services\UploadService;
|
||||
use think\annotation\Inject;
|
||||
use think\exception\ValidateException;
|
||||
|
||||
/**
|
||||
* Class SystemStorageServices
|
||||
* @package app\services\system\config
|
||||
* @mixin SystemStorageDao
|
||||
*/
|
||||
class SystemStorageServices extends BaseServices
|
||||
{
|
||||
|
||||
/**
|
||||
* @var SystemStorageDao
|
||||
*/
|
||||
#[Inject]
|
||||
protected SystemStorageDao $dao;
|
||||
|
||||
/**
|
||||
* @param array $where
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getList(array $where)
|
||||
{
|
||||
[$page, $limit] = $this->getPageValue();
|
||||
$config = $this->getStorageConfig((int)$where['type']);
|
||||
$where['access_key'] = $config['accessKey'];
|
||||
$list = $this->dao->getStorageList($where, ['*'], $page, $limit);
|
||||
foreach ($list as &$item) {
|
||||
$item['_add_time'] = date('Y-m-d H:i:s', $item['add_time']);
|
||||
$item['_update_time'] = date('Y-m-d H:i:s', $item['update_time']);
|
||||
$service = UploadService::init($item['type']);
|
||||
$region = $service->getRegion();
|
||||
foreach ($region as $value) {
|
||||
if (strstr($item['region'], $value['value'])) {
|
||||
$item['_region'] = $value['label'];
|
||||
}
|
||||
}
|
||||
if (!$item['cname']) {
|
||||
$item['cname'] = str_replace(['http://', 'https://'], '', $item['domain']);
|
||||
}
|
||||
}
|
||||
$count = $this->dao->getCount($where);
|
||||
return compact('list', 'count');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $type
|
||||
* @return array
|
||||
* @throws \FormBuilder\Exception\FormBuilderException
|
||||
*/
|
||||
public function getFormStorage(int $type)
|
||||
{
|
||||
$upload = UploadService::init($type);
|
||||
|
||||
$config = $this->getStorageConfig($type);
|
||||
$ruleConfig = [];
|
||||
if (!$config['accessKey']) {
|
||||
$ruleConfig = [
|
||||
FormBuilder::input('accessKey', 'AccessKeyId:', $config['accessKey'] ?? '')->required(),
|
||||
FormBuilder::input('secretKey', 'AccessKeySecret:', $config['secretKey'] ?? '')->required(),
|
||||
];
|
||||
}
|
||||
|
||||
if ($type === 4 && isset($config['appid']) && !$config['appid']) {
|
||||
$ruleConfig[] = FormBuilder::input('appid', 'APPID', $config['appid'] ?? '')->required();
|
||||
}
|
||||
|
||||
$rule = [
|
||||
FormBuilder::input('name', '空间名称')->required(),
|
||||
FormBuilder::select('region', '空间区域')->options($upload->getRegion())->required(),
|
||||
FormBuilder::radio('acl', '读写权限', 'public-read')->options([
|
||||
['label' => '公共读(推荐)', 'value' => 'public-read'],
|
||||
['label' => '公共读写', 'value' => 'public-read-write'],
|
||||
])->required(),
|
||||
];
|
||||
|
||||
$rule = array_merge($ruleConfig, $rule);
|
||||
return create_form('添加云空间', $rule, '/setting/config/storage/' . $type);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $type
|
||||
* @return array
|
||||
*/
|
||||
public function getStorageConfig(int $type)
|
||||
{
|
||||
$config = [
|
||||
'accessKey' => '',
|
||||
'secretKey' => ''
|
||||
];
|
||||
switch ($type) {
|
||||
case 2://七牛
|
||||
$config = [
|
||||
'accessKey' => sys_config('qiniu_accessKey', ''),
|
||||
'secretKey' => sys_config('qiniu_secretKey', ''),
|
||||
];
|
||||
break;
|
||||
case 3:// oss 阿里云
|
||||
$config = [
|
||||
'accessKey' => sys_config('accessKey', ''),
|
||||
'secretKey' => sys_config('secretKey', ''),
|
||||
];
|
||||
break;
|
||||
case 4:// cos 腾讯云
|
||||
$config = [
|
||||
'accessKey' => sys_config('tengxun_accessKey', ''),
|
||||
'secretKey' => sys_config('tengxun_secretKey', ''),
|
||||
'appid' => sys_config('tengxun_appid', ''),
|
||||
];
|
||||
break;
|
||||
case 5:// cos 京东云
|
||||
$config = [
|
||||
'accessKey' => sys_config('jd_accessKey', ''),
|
||||
'secretKey' => sys_config('jd_secretKey', ''),
|
||||
'storageRegion' => sys_config('jd_storage_region'),
|
||||
];
|
||||
break;
|
||||
case 6:// cos 华为云
|
||||
$config = [
|
||||
'accessKey' => sys_config('hw_accessKey', ''),
|
||||
'secretKey' => sys_config('hw_secretKey', ''),
|
||||
];
|
||||
break;
|
||||
case 7:// cos 天翼云
|
||||
$config = [
|
||||
'accessKey' => sys_config('ty_accessKey', ''),
|
||||
'secretKey' => sys_config('ty_secretKey', ''),
|
||||
];
|
||||
break;
|
||||
}
|
||||
return $config;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $type
|
||||
* @return array
|
||||
* @throws \FormBuilder\Exception\FormBuilderException
|
||||
*/
|
||||
public function getFormStorageConfig(int $type)
|
||||
{
|
||||
$config = $this->getStorageConfig($type);
|
||||
$rule = [
|
||||
FormBuilder::hidden('type', $type),
|
||||
FormBuilder::input('accessKey', 'AccessKeyId:', $config['accessKey'] ?? '')->required(),
|
||||
FormBuilder::input('secretKey', 'AccessKeySecret:', $config['secretKey'] ?? '')->required(),
|
||||
];
|
||||
|
||||
if ($type === 4) {
|
||||
$rule[] = FormBuilder::input('appid', 'APPID', $config['appid'] ?? '')->required();
|
||||
}
|
||||
|
||||
if ($type === 5) {
|
||||
$rule[] = FormBuilder::input('storageRegion', 'Region', $config['storageRegion'] ?? '')->required();
|
||||
}
|
||||
|
||||
|
||||
return create_form('配置信息', $rule, '/setting/config/storage/config');
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除空间
|
||||
* @param int $id
|
||||
* @return bool
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function deleteStorage(int $id)
|
||||
{
|
||||
$storageInfo = $this->dao->get(['is_delete' => 0, 'id' => $id]);
|
||||
if (!$storageInfo) {
|
||||
throw new ValidateException('删除的云存储不存在');
|
||||
}
|
||||
if ($storageInfo->status) {
|
||||
throw new ValidateException('云存储正在使用中,需要启动其他空间才能删除');
|
||||
}
|
||||
|
||||
try {
|
||||
$upload = UploadService::init($storageInfo->type);
|
||||
$res = $upload->deleteBucket($storageInfo->name, $storageInfo->region);
|
||||
if (false === $res) {
|
||||
throw new ValidateException($upload->getError());
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
if ($e->getMessage() == 'The specified bucket does not exist.') {
|
||||
$storageInfo->is_delete = 1;
|
||||
$storageInfo->save();
|
||||
return true;
|
||||
}
|
||||
throw new ValidateException($e->getMessage());
|
||||
}
|
||||
$storageInfo->is_delete = 1;
|
||||
$storageInfo->save();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存云存储配置
|
||||
* @param int $type 存储类型(2:七牛 3:阿里云 4:腾讯云 5:京东云 6:华为云 7:天翼云)
|
||||
* @param array $data 配置数据
|
||||
* @return bool|void
|
||||
*/
|
||||
public function saveConfig(int $type, array $data)
|
||||
{
|
||||
//保存配置信息
|
||||
if (1 !== $type) {
|
||||
$accessKey = $secretKey = $appid = $storageRegion = '';
|
||||
if (isset($data['accessKey']) && isset($data['secretKey']) && $data['accessKey'] && $data['secretKey']) {
|
||||
$accessKey = $data['accessKey'];
|
||||
$secretKey = $data['secretKey'];
|
||||
unset($data['accessKey'], $data['secretKey']);
|
||||
}
|
||||
if (isset($data['appid']) && $data['appid']) {
|
||||
$appid = $data['appid'];
|
||||
unset($data['appid']);
|
||||
}
|
||||
if (isset($data['storageRegion']) && $data['storageRegion']) {
|
||||
$storageRegion = $data['storageRegion'];
|
||||
unset($data['storageRegion']);
|
||||
}
|
||||
if (!$accessKey || !$secretKey) {
|
||||
return true;
|
||||
}
|
||||
/** @var SystemConfigServices $make */
|
||||
$make = app()->make(SystemConfigServices::class);
|
||||
switch ($type) {
|
||||
case 2://七牛
|
||||
$make->update('qiniu_accessKey', ['value' => json_encode($accessKey)], 'menu_name');
|
||||
$make->update('qiniu_secretKey', ['value' => json_encode($secretKey)], 'menu_name');
|
||||
break;
|
||||
case 3:// oss 阿里云
|
||||
$make->update('accessKey', ['value' => json_encode($accessKey)], 'menu_name');
|
||||
$make->update('secretKey', ['value' => json_encode($secretKey)], 'menu_name');
|
||||
break;
|
||||
case 4:// cos 腾讯云
|
||||
$make->update('tengxun_accessKey', ['value' => json_encode($accessKey)], 'menu_name');
|
||||
$make->update('tengxun_secretKey', ['value' => json_encode($secretKey)], 'menu_name');
|
||||
$make->update('tengxun_appid', ['value' => json_encode($appid)], 'menu_name');
|
||||
break;
|
||||
case 5:// oss 京东云
|
||||
$make->update('jd_accessKey', ['value' => json_encode($accessKey)], 'menu_name');
|
||||
$make->update('jd_secretKey', ['value' => json_encode($secretKey)], 'menu_name');
|
||||
$make->update('jd_storage_region', ['value' => json_encode($storageRegion)], 'menu_name');
|
||||
break;
|
||||
case 6:// oss 华为云
|
||||
$make->update('hw_accessKey', ['value' => json_encode($accessKey)], 'menu_name');
|
||||
$make->update('hw_secretKey', ['value' => json_encode($secretKey)], 'menu_name');
|
||||
break;
|
||||
case 7:// oss 天翼云
|
||||
$make->update('ty_accessKey', ['value' => json_encode($accessKey)], 'menu_name');
|
||||
$make->update('ty_secretKey', ['value' => json_encode($secretKey)], 'menu_name');
|
||||
break;
|
||||
}
|
||||
\crmeb\services\SystemConfigService::clear();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存云存储
|
||||
* @param int $type
|
||||
* @param array $data
|
||||
* @return mixed
|
||||
*/
|
||||
public function saveStorage(int $type, array $data)
|
||||
{
|
||||
//保存配置信息
|
||||
$this->saveConfig($type, $data);
|
||||
$name = $data['name'];
|
||||
|
||||
switch ($type) {
|
||||
case 3://阿里云oss
|
||||
$data['region'] = $this->getReagionHost($type, $data['region']);
|
||||
break;
|
||||
case 4://腾讯云cos
|
||||
$name = $data['name'] . '-' . sys_config('tengxun_appid');
|
||||
break;
|
||||
}
|
||||
|
||||
if ($this->dao->count(['type' => $type, 'name' => $name])) {
|
||||
throw new ValidateException('云空间名称不能重复');
|
||||
}
|
||||
//保存云存储
|
||||
$data['type'] = $type;
|
||||
$upload = UploadService::init($type);
|
||||
$res = $upload->createBucket($data['name'], $data['region'], $data['acl']);
|
||||
if (false === $res) {
|
||||
throw new ValidateException($upload->getError());
|
||||
}
|
||||
|
||||
$data['domain'] = $this->getDomain($type, $data['name'], $data['region'], sys_config('tengxun_appid'));
|
||||
if (2 === $type) {
|
||||
$domianList = $upload->getDomian($data['name']);
|
||||
$data['domain'] = $domianList[count($domianList) - 1];
|
||||
} else {
|
||||
$data['cname'] = $data['domain'];
|
||||
}
|
||||
|
||||
$data['name'] = $name;
|
||||
$data['add_time'] = time();
|
||||
$data['update_time'] = time();
|
||||
$config = $this->getStorageConfig($type);
|
||||
$data['access_key'] = $config['accessKey'];
|
||||
return $this->dao->save($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 同步云储存桶
|
||||
* @param int $type
|
||||
* @return bool
|
||||
*/
|
||||
public function synchronization(int $type)
|
||||
{
|
||||
$data = [];
|
||||
switch ($type) {
|
||||
case 2://七牛
|
||||
$config = $this->getStorageConfig($type);
|
||||
$upload = UploadService::init($type);
|
||||
$list = $upload->listbuckets();
|
||||
if (false === $list) {
|
||||
throw new ValidateException('同步失败,失败原因:' . $upload->getError());
|
||||
}
|
||||
foreach ($list as $item) {
|
||||
if (!$this->dao->count(['name' => $item['id'], 'is_delete' => 0, 'access_key' => $config['accessKey']])) {
|
||||
$data[] = [
|
||||
'type' => $type,
|
||||
'access_key' => $config['accessKey'],
|
||||
'name' => $item['id'],
|
||||
'region' => $item['region'],
|
||||
'acl' => $item['private'] == 0 ? 'public-read' : 'private',
|
||||
'status' => 0,
|
||||
'is_delete' => 0,
|
||||
'add_time' => time(),
|
||||
'update_time' => time()
|
||||
];
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 3:// oss 阿里云
|
||||
$upload = UploadService::init($type);
|
||||
$list = $upload->listbuckets();
|
||||
$config = $this->getStorageConfig($type);
|
||||
foreach ($list as $item) {
|
||||
if (!$this->dao->count(['name' => $item['name'], 'is_delete' => 0, 'access_key' => $config['accessKey']])) {
|
||||
$region = $this->getReagionHost($type, $item['location']);
|
||||
$data[] = [
|
||||
'type' => $type,
|
||||
'access_key' => $config['accessKey'],
|
||||
'name' => $item['name'],
|
||||
'region' => $region,
|
||||
'acl' => 'public-read',
|
||||
'domain' => $this->getDomain($type, $item['name'], $region),
|
||||
'status' => 0,
|
||||
'is_delete' => 0,
|
||||
'add_time' => strtotime($item['createTime']),
|
||||
'update_time' => time()
|
||||
];
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 4:// cos 腾讯云
|
||||
$upload = UploadService::init($type);
|
||||
$list = $upload->listbuckets();
|
||||
if (!empty($list['Name'])) {
|
||||
$newList = $list;
|
||||
$list = [];
|
||||
$list[] = $newList;
|
||||
}
|
||||
$config = $this->getStorageConfig($type);
|
||||
foreach ($list as $item) {
|
||||
if (($id = $this->dao->value(['name' => $item['Name'], 'is_delete' => 0, 'access_key' => $config['accessKey']], 'id'))) {
|
||||
$this->dao->update($id, [
|
||||
'update_time' => time(),
|
||||
'region' => $item['Location'],
|
||||
'name' => $item['Name'],
|
||||
'domain' => sys_config('tengxun_appid') ? $this->getDomain($type, $item['Name'], $item['Location']) : '',
|
||||
'cname' => str_replace('https://','',sys_config('tengxun_appid') ? $this->getDomain($type, $item['Name'], $item['Location']) : ''),
|
||||
]);
|
||||
} else {
|
||||
$data[] = [
|
||||
'type' => $type,
|
||||
'access_key' => $config['accessKey'],
|
||||
'name' => $item['Name'],
|
||||
'region' => $item['Location'],
|
||||
'acl' => 'public-read',
|
||||
'status' => 0,
|
||||
'domain' => sys_config('tengxun_appid') ? $this->getDomain($type, $item['Name'], $item['Location']) : '',
|
||||
'cname' => str_replace('https://','',sys_config('tengxun_appid') ? $this->getDomain($type, $item['Name'], $item['Location']) : ''),
|
||||
'is_delete' => 0,
|
||||
'add_time' => strtotime($item['CreationDate']),
|
||||
'update_time' => time()
|
||||
];
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 5:// cos 京东云
|
||||
$upload = UploadService::init($type);
|
||||
$list = $upload->listbuckets();
|
||||
$config = $this->getStorageConfig($type);
|
||||
$location = $config['storageRegion'] ?? 'cn-north-1';
|
||||
foreach ($list as $item) {
|
||||
if (!$this->dao->count(['name' => $item['Name'], 'access_key' => $config['accessKey']])) {
|
||||
$data[] = [
|
||||
'type' => $type,
|
||||
'access_key' => $config['accessKey'],
|
||||
'name' => $item['Name'],
|
||||
'region' => $location,
|
||||
'acl' => 'public-read',
|
||||
'status' => 0,
|
||||
'domain' => $this->getDomain($type, $item['Name'], $location),
|
||||
'is_delete' => 0,
|
||||
'add_time' => time(),
|
||||
'update_time' => time()
|
||||
];
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 6:// cos 华为云
|
||||
case 7:// cos 天翼云
|
||||
$upload = UploadService::init($type);
|
||||
$list = $upload->listbuckets();
|
||||
if (!empty($list['Name'])) {
|
||||
$newList = $list;
|
||||
$list = [];
|
||||
$list[] = $newList;
|
||||
}
|
||||
$config = $this->getStorageConfig($type);
|
||||
foreach ($list as $item) {
|
||||
if (!$this->dao->count(['name' => $item['Name'], 'access_key' => $config['accessKey']])) {
|
||||
$data[] = [
|
||||
'type' => $type,
|
||||
'access_key' => $config['accessKey'],
|
||||
'name' => $item['Name'],
|
||||
'region' => $item['Location'],
|
||||
'acl' => 'public-read',
|
||||
'status' => 0,
|
||||
'domain' => $this->getDomain($type, $item['Name'], $item['Location']),
|
||||
'is_delete' => 0,
|
||||
'add_time' => strtotime($item['CreationDate']),
|
||||
'update_time' => time()
|
||||
];
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
if ($data) {
|
||||
$this->dao->saveAll($data);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $type
|
||||
* @param string $reagion
|
||||
* @return mixed|string
|
||||
*/
|
||||
public function getReagionHost(int $type, string $reagion)
|
||||
{
|
||||
$upload = UploadService::init($type);
|
||||
$reagionList = $upload->getRegion();
|
||||
foreach ($reagionList as $item) {
|
||||
if (strstr($item['value'], $reagion) !== false) {
|
||||
return $item['value'];
|
||||
}
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取域名
|
||||
* @param int $type
|
||||
* @param string $name
|
||||
* @param string $reagion
|
||||
* @param string $appid
|
||||
* @return string
|
||||
*/
|
||||
public function getDomain(int $type, string $name, string $reagion, string $appid = '')
|
||||
{
|
||||
$domainName = '';
|
||||
switch ($type) {
|
||||
case 3:// oss 阿里云
|
||||
$domainName = 'https://' . $name . '.' . $reagion;
|
||||
break;
|
||||
case 4:// cos 腾讯云
|
||||
$domainName = 'https://' . $name . ($appid ? '-' . $appid : '') . '.cos.' . $reagion . '.myqcloud.com';
|
||||
break;
|
||||
case 5:// cos 京东云
|
||||
$domainName = 'https://' . $name . '.s3.' . $reagion . '.jdcloud-oss.com';
|
||||
break;
|
||||
case 6:// cos 华为云
|
||||
$domainName = 'https://' . $name . '.obs.' . $reagion . '.myhuaweicloud.com';
|
||||
break;
|
||||
case 7:// cos 天翼云
|
||||
$domainName = 'https://' . $name . '.obs.' . $reagion . '.ctyun.cn';
|
||||
break;
|
||||
}
|
||||
return $domainName;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取云存储配置
|
||||
* @param int $type
|
||||
* @return array|string[]
|
||||
*/
|
||||
public function getConfig(int $type)
|
||||
{
|
||||
$res = ['name' => '', 'region' => '', 'domain' => '', 'cname' => ''];
|
||||
try {
|
||||
$config = $this->dao->get(['type' => $type, 'status' => 1, 'is_delete' => 0]);
|
||||
if ($config) {
|
||||
return ['name' => $config->name, 'region' => $config->region, 'domain' => $config->domain, 'cname' => $config->cname];
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
|
||||
}
|
||||
return $res;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取修改域名表单
|
||||
* @param int $id
|
||||
* @return array
|
||||
* @throws \FormBuilder\Exception\FormBuilderException
|
||||
*/
|
||||
public function getUpdateDomainForm(int $id)
|
||||
{
|
||||
$domain = $this->dao->value(['id' => $id], 'domain');
|
||||
$rule = [
|
||||
FormBuilder::input('domain', '空间域名', $domain),
|
||||
];
|
||||
return create_form('修改空间域名', $rule, '/setting/config/storage/domain/' . $id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改域名并绑定
|
||||
* @param int $id
|
||||
* @param string $domain
|
||||
* @return bool
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function updateDomain(int $id, string $domain, array $data = [])
|
||||
{
|
||||
$info = $this->dao->get($id);
|
||||
if (!$info) {
|
||||
throw new ValidateException('没有查询到数据');
|
||||
}
|
||||
if ($info->domain != $domain) {
|
||||
if (4 === ((int)$info->type)) {
|
||||
$info->domain = $domain;
|
||||
return $info->save();
|
||||
}
|
||||
$info->domain = $domain;
|
||||
$upload = UploadService::init($info->type);
|
||||
//是否添加过域名不存在需要绑定域名
|
||||
$domainList = $upload->getDomian($info->name, $info->region);
|
||||
$domainParse = parse_url($domain);
|
||||
if (!in_array($domainParse['host'], $domainList)) {
|
||||
//绑定域名到云储存桶
|
||||
$res = $upload->bindDomian($info->name, $domain, $info->region);
|
||||
if (false === $res) {
|
||||
throw new ValidateException($upload->getError());
|
||||
}
|
||||
}
|
||||
//七牛云需要通过接口获取cname
|
||||
if (2 === ((int)$info->type)) {
|
||||
$resDomain = $upload->getDomianInfo($domain);
|
||||
$info->cname = $resDomain['cname'] ?? '';
|
||||
}
|
||||
return $info->save();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
86
app/services/system/form/SystemFormDataServices.php
Normal file
86
app/services/system/form/SystemFormDataServices.php
Normal file
@@ -0,0 +1,86 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
declare (strict_types=1);
|
||||
|
||||
namespace app\services\system\form;
|
||||
|
||||
|
||||
use app\dao\system\form\SystemFormDataDao;
|
||||
use app\services\BaseServices;
|
||||
use app\dao\diy\DiyDao;
|
||||
use think\annotation\Inject;
|
||||
use think\exception\ValidateException;
|
||||
|
||||
|
||||
/**
|
||||
* 系统表单
|
||||
* Class SystemFormDataServices
|
||||
* @package app\services\system\form
|
||||
* @mixin DiyDao
|
||||
*/
|
||||
class SystemFormDataServices extends BaseServices
|
||||
{
|
||||
|
||||
/**
|
||||
* @var SystemFormDataDao
|
||||
*/
|
||||
#[Inject]
|
||||
protected SystemFormDataDao $dao;
|
||||
|
||||
|
||||
/**
|
||||
* 获取表单收集数据列表
|
||||
* @param int $id
|
||||
* @param array $where
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getFormDataList(int $id = 0, array $where = [])
|
||||
{
|
||||
$where['is_del'] = 0;
|
||||
if ($id) $where['system_form_id'] = $id;
|
||||
[$page, $limit] = $this->getPageValue();
|
||||
$list = $this->dao->getList($where, ['*'], $page, $limit, ['user', 'systemForm']);
|
||||
$count = $this->dao->count($where);
|
||||
return compact('list', 'count');
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存系统表单收集数据
|
||||
* @param array $form
|
||||
* @param int $type
|
||||
* @return bool
|
||||
*/
|
||||
public function setFormData(array $form, int $type = 1)
|
||||
{
|
||||
if (!$form) {
|
||||
throw new ValidateException('缺少表单收集数据');
|
||||
}
|
||||
/** @var SystemFormServices $systemFormServices */
|
||||
$systemFormServices = app()->make(SystemFormServices::class);
|
||||
$form['value'] = $systemFormServices->handleForm($form['value'] ?? []);
|
||||
|
||||
$form['value'] = json_encode($form['value']);
|
||||
$data = ['type' => $type, 'add_time' => time()];
|
||||
switch ($type) {
|
||||
case 1://订单
|
||||
$data = array_merge($data, $form);
|
||||
break;
|
||||
}
|
||||
if ($data) {
|
||||
$this->dao->save($data);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
103
app/services/system/form/SystemFormServices.php
Normal file
103
app/services/system/form/SystemFormServices.php
Normal file
@@ -0,0 +1,103 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
declare (strict_types=1);
|
||||
|
||||
namespace app\services\system\form;
|
||||
|
||||
use app\dao\system\form\SystemFormDao;
|
||||
use app\services\BaseServices;
|
||||
use app\dao\diy\DiyDao;
|
||||
use think\annotation\Inject;
|
||||
|
||||
|
||||
/**
|
||||
* 系统表单
|
||||
* Class SystemFormServices
|
||||
* @package app\services\diy
|
||||
* @mixin DiyDao
|
||||
*/
|
||||
class SystemFormServices extends BaseServices
|
||||
{
|
||||
|
||||
/**
|
||||
* form类型
|
||||
* @var string[]
|
||||
*/
|
||||
protected $formType = [
|
||||
'checkboxs' => '多选框',
|
||||
'citys' => '城市',
|
||||
'dates' => '日期',
|
||||
'dateranges' => '日期范围',
|
||||
'radios' => '单选框',
|
||||
'selects' => '下拉框',
|
||||
'texts' => '文本框',
|
||||
'times' => '时间',
|
||||
'timeranges' => '时间范围',
|
||||
'uploadPicture' => '图片'
|
||||
];
|
||||
|
||||
/**
|
||||
* @var SystemFormDao
|
||||
*/
|
||||
#[Inject]
|
||||
protected SystemFormDao $dao;
|
||||
|
||||
|
||||
/**
|
||||
* 获取系统表单
|
||||
* @param array $where
|
||||
* @param array $field
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getFormList(array $where = [], array $field = ['*'])
|
||||
{
|
||||
[$page, $limit] = $this->getPageValue();
|
||||
$list = $this->dao->getFormList($where, $field, $page, $limit);
|
||||
$count = $this->dao->count($where + ['is_del' => 0]);
|
||||
return compact('list', 'count');
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理表单数据
|
||||
* @param array $form
|
||||
* @return array
|
||||
*/
|
||||
public function handleForm(array $form)
|
||||
{
|
||||
$info = [];
|
||||
if ($form) {
|
||||
$infoOne = [];
|
||||
foreach ($form as $item) {
|
||||
$infoOne['id'] = $item['id'] ?? '';
|
||||
$infoOne['type'] = $item['name'] ?? '';
|
||||
$infoOne['name'] = $this->formType[$infoOne['type']] ?? '';
|
||||
$infoOne['title'] = $item['titleConfig']['value'] ?? '';
|
||||
$infoOne['tip'] = $item['tipConfig']['value'] ?? '';
|
||||
$infoOne['list'] = [];
|
||||
$infoOne['require'] = $item['titleShow']['val'] ?? false;
|
||||
switch ($item['name']) {
|
||||
case 'checkboxs':
|
||||
case 'radios':
|
||||
case 'selects':
|
||||
$infoOne['list'] = $item['wordsConfig']['list'] ?? [];
|
||||
break;
|
||||
}
|
||||
$infoOne['value'] = $item['value'] ?? '';
|
||||
$info[] = $infoOne;
|
||||
}
|
||||
}
|
||||
return $info;
|
||||
}
|
||||
|
||||
}
|
||||
81
app/services/system/log/ClearServices.php
Normal file
81
app/services/system/log/ClearServices.php
Normal file
@@ -0,0 +1,81 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\services\system\log;
|
||||
|
||||
|
||||
use app\services\BaseServices;
|
||||
|
||||
/**
|
||||
* Class ClearServices
|
||||
* @package app\services\system\log
|
||||
*/
|
||||
class ClearServices extends BaseServices
|
||||
{
|
||||
/** 递归删除文件
|
||||
* @param $dirName
|
||||
* @param bool $subdir
|
||||
*/
|
||||
protected function delDirAndFile($dirName)
|
||||
{
|
||||
$list = glob($dirName . '*');
|
||||
foreach ($list as $file) {
|
||||
if (is_dir($file))
|
||||
$this->delDirAndFile($file . DS);
|
||||
else
|
||||
@unlink($file);
|
||||
}
|
||||
@rmdir($dirName);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除日志
|
||||
*/
|
||||
public function deleteLog()
|
||||
{
|
||||
$root = app()->getRootPath() . 'runtime' . DS;
|
||||
$this->delDirAndFile($root . 'admin' . DS . 'log' . DS);
|
||||
$this->delDirAndFile($root . 'api' . DS . 'log' . DS);
|
||||
$this->delDirAndFile($root . 'log' . DS);
|
||||
}
|
||||
|
||||
/**
|
||||
* 刷新数据缓存
|
||||
*/
|
||||
public function refresCache()
|
||||
{
|
||||
$root = app()->getRootPath() . 'runtime' . DS;
|
||||
$adminRoute = $root . 'admin';
|
||||
$apiRoute = $root . 'api';
|
||||
$cacheRoute = $root . 'cache';
|
||||
$cache = [];
|
||||
|
||||
if (is_dir($adminRoute))
|
||||
$cache[$adminRoute] = scandir($adminRoute);
|
||||
if (is_dir($apiRoute))
|
||||
$cache[$apiRoute] = scandir($apiRoute);
|
||||
if (is_dir($cacheRoute))
|
||||
$cache[$cacheRoute] = scandir($cacheRoute);
|
||||
|
||||
foreach ($cache as $p => $list) {
|
||||
foreach ($list as $file) {
|
||||
if (!in_array($file, ['.', '..', 'log', 'schema', 'admin.php'])) {
|
||||
$path = $p . DS . $file;
|
||||
if (is_file($path)) {
|
||||
@unlink($path);
|
||||
} else {
|
||||
$this->delDirAndFile($path . DS);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
255
app/services/system/log/SystemFileServices.php
Normal file
255
app/services/system/log/SystemFileServices.php
Normal file
@@ -0,0 +1,255 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\services\system\log;
|
||||
|
||||
|
||||
use app\dao\system\log\SystemFileDao;
|
||||
use app\services\BaseServices;
|
||||
use crmeb\exceptions\AdminException;
|
||||
use crmeb\services\CacheService;
|
||||
use crmeb\services\FileService as FileClass;
|
||||
use think\annotation\Inject;
|
||||
|
||||
/**
|
||||
* 文件校验
|
||||
* Class SystemFileServices
|
||||
* @package app\services\system\log
|
||||
* @mixin SystemFileDao
|
||||
*/
|
||||
class SystemFileServices extends BaseServices
|
||||
{
|
||||
|
||||
/**
|
||||
* @var SystemFileDao
|
||||
*/
|
||||
#[Inject]
|
||||
protected SystemFileDao $dao;
|
||||
|
||||
/**
|
||||
* 获取文件校验列表
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getFileList()
|
||||
{
|
||||
$rootPath = app()->getRootPath();
|
||||
$key = 'system_file_app_crmeb_public';
|
||||
$arr = CacheService::get(md5($key));
|
||||
if (!$arr) {
|
||||
$app = $this->getDir($rootPath . 'app');
|
||||
$extend = $this->getDir($rootPath . 'crmeb');
|
||||
$arr = array_merge($app, $extend);
|
||||
CacheService::set(md5($key), $arr, 3600 * 24);
|
||||
}
|
||||
$fileAll = [];//本地文件
|
||||
$cha = [];//不同的文件
|
||||
$len = strlen($rootPath);
|
||||
$fileKey = 'system_file_app_msyql';
|
||||
$file = CacheService::get(md5($fileKey));
|
||||
if (!$file) {
|
||||
$file = $this->dao->getAll();//数据库中的文件
|
||||
CacheService::set(md5($fileKey), $file, 3600 * 24);
|
||||
}
|
||||
if (empty($file)) {
|
||||
foreach ($arr as $k => $v) {
|
||||
$update_time = stat($v);
|
||||
$fileAll[$k]['cthash'] = md5_file($v);
|
||||
$fileAll[$k]['filename'] = substr($v, $len);
|
||||
$fileAll[$k]['atime'] = $update_time['atime'];
|
||||
$fileAll[$k]['mtime'] = $update_time['mtime'];
|
||||
$fileAll[$k]['ctime'] = $update_time['ctime'];
|
||||
}
|
||||
$data_num = array_chunk($fileAll, 100);
|
||||
$res = true;
|
||||
$res = $this->transaction(function () use ($data_num, $res) {
|
||||
foreach ($data_num as $k => $v) {
|
||||
$res = $res && $this->dao->saveAll($v);
|
||||
}
|
||||
return $res;
|
||||
});
|
||||
if ($res) {
|
||||
$cha = [];//不同的文件
|
||||
} else {
|
||||
$cha = $fileAll;
|
||||
}
|
||||
} else {
|
||||
$file = array_combine(array_column($file, 'filename'), $file);
|
||||
$insertData = [];
|
||||
foreach ($arr as $ko => $vo) {
|
||||
$update_time = stat($vo);
|
||||
$cthash = md5_file($vo);
|
||||
$fileName = substr($vo, $len);
|
||||
$data = [
|
||||
'filename' => $fileName,
|
||||
'cthash' => $cthash,
|
||||
'atime' => $update_time['atime'] ?? 0,
|
||||
'mtime' => $update_time['mtime'] ?? 0,
|
||||
'ctime' => $update_time['ctime'] ?? 0,
|
||||
];
|
||||
if (isset($file[$fileName])) {
|
||||
$data ['type'] = $file[$fileName]['cthash'] != $cthash ? '已修改' : '新增的';
|
||||
unset($file[$fileName]);
|
||||
} else {//新增
|
||||
$insertData[] = $data;
|
||||
$data['type'] = '新增的';
|
||||
}
|
||||
$data['atime'] = (int)$data['atime'] ? date('Y-m-d H:i:s', (int)$data['atime']) : '';
|
||||
$data['mtime'] = (int)$data['mtime'] ? date('Y-m-d H:i:s', (int)$data['mtime']) : '';
|
||||
$data['ctime'] = (int)$data['ctime'] ? date('Y-m-d H:i:s', (int)$data['ctime']) : '';
|
||||
$cha[] = $data;
|
||||
}
|
||||
if ($insertData) {
|
||||
$this->dao->saveAll($insertData);
|
||||
CacheService::delete(md5($fileKey));
|
||||
}
|
||||
foreach ($file as $k => $v) {
|
||||
$cha[] = [
|
||||
'filename' => $v['filename'],
|
||||
'cthash' => $v['cthash'],
|
||||
'atime' => (int)$v['atime'] ? date('Y-m-d H:i:s', (int)$v['atime']) : '',
|
||||
'mtime' => (int)$v['mtime'] ? date('Y-m-d H:i:s', (int)$v['mtime']) : '',
|
||||
'ctime' => (int)$v['ctime'] ? date('Y-m-d H:i:s', (int)$v['ctime']) : '',
|
||||
'type' => '已删除',
|
||||
|
||||
];
|
||||
}
|
||||
}
|
||||
$ctime = array_column($cha, 'ctime');
|
||||
array_multisort($ctime, SORT_DESC, $cha);
|
||||
return $cha;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文件夹中的文件 包括子文件
|
||||
* @param $dir
|
||||
* @return array
|
||||
*/
|
||||
public function getDir($dir)
|
||||
{
|
||||
$data = [];
|
||||
$this->searchDir($dir, $data);
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文件夹中的文件 包括子文件 不能直接用 直接使用 $this->getDir()方法 P156
|
||||
* @param $path
|
||||
* @param $data
|
||||
*/
|
||||
public function searchDir($path, &$data)
|
||||
{
|
||||
if (is_dir($path) && !strpos($path, 'uploads')) {
|
||||
$files = scandir($path);
|
||||
foreach ($files as $file) {
|
||||
if ($file != '.' && $file != '..') {
|
||||
$this->searchDir($path . '/' . $file, $data);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (is_file($path)) {
|
||||
$data[] = $path;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开目录获取文件列表
|
||||
* @return array
|
||||
*/
|
||||
public function opendir()
|
||||
{
|
||||
$fileAll = array('dir' => [], 'file' => []);
|
||||
//根目录
|
||||
$rootdir = app()->getRootPath();
|
||||
// return $rootdir;
|
||||
//当前目录
|
||||
$request_dir = app('request')->param('dir');
|
||||
//防止查看站点以外的目录
|
||||
if (strpos($request_dir, $rootdir) === false) {
|
||||
$request_dir = $rootdir;
|
||||
}
|
||||
//判断是否是返回上级
|
||||
if (app('request')->param('superior') && !empty($request_dir)) {
|
||||
if (strpos(dirname($request_dir), $rootdir) !== false) {
|
||||
$dir = dirname($request_dir);
|
||||
} else {
|
||||
$dir = $rootdir;
|
||||
}
|
||||
|
||||
} else {
|
||||
$dir = !empty($request_dir) ? $request_dir : $rootdir;
|
||||
$dir = rtrim($dir, DS) . DS . app('request')->param('filedir');
|
||||
}
|
||||
$list = scandir($dir);
|
||||
foreach ($list as $key => $v) {
|
||||
if ($v != '.' && $v != '..') {
|
||||
if (is_dir($dir . DS . $v)) {
|
||||
$fileAll['dir'][] = FileClass::listInfo($dir . DS . $v);
|
||||
}
|
||||
if (is_file($dir . DS . $v)) {
|
||||
$fileAll['file'][] = FileClass::listInfo($dir . DS . $v);
|
||||
}
|
||||
}
|
||||
}
|
||||
//兼容windows
|
||||
$uname = php_uname('s');
|
||||
if (strstr($uname, 'Windows') !== false) {
|
||||
$dir = ltrim($dir, '\\');
|
||||
$rootdir = str_replace('\\', '\\\\', $rootdir);
|
||||
}
|
||||
$list = array_merge($fileAll['dir'], $fileAll['file']);
|
||||
foreach ($list as $key => $value) {
|
||||
$list[$key]['real_path'] = str_replace($rootdir, '', $value['pathname']);
|
||||
$list[$key]['mtime'] = date('Y-m-d H:i:s', $value['mtime']);
|
||||
}
|
||||
return compact('dir', 'list');
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取文件内容
|
||||
* @param string $filepath 文件路径
|
||||
* @return array
|
||||
*/
|
||||
public function openfile($filepath)
|
||||
{
|
||||
$content = FileClass::readFile($filepath);//防止页面内嵌textarea标签
|
||||
$ext = FileClass::getExt($filepath);
|
||||
$extarray = [
|
||||
'js' => 'text/javascript'
|
||||
, 'php' => 'text/x-php'
|
||||
, 'html' => 'text/html'
|
||||
, 'sql' => 'text/x-mysql'
|
||||
, 'css' => 'text/x-scss'];
|
||||
$mode = empty($extarray[$ext]) ? '' : $extarray[$ext];
|
||||
return compact('content', 'mode', 'filepath');
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存文件内容
|
||||
* @param string $filepath 文件路径
|
||||
* @param string $comment 文件内容
|
||||
* @return bool
|
||||
* @throws AdminException
|
||||
*/
|
||||
public function savefile($filepath, $comment)
|
||||
{
|
||||
//兼容windows
|
||||
$uname = php_uname('s');
|
||||
if (strstr($uname, 'Windows') !== false)
|
||||
$filepath = ltrim(str_replace('/', DS, $filepath), '.');
|
||||
if (!FileClass::isWritable($filepath)) {
|
||||
throw new AdminException('没有权限');
|
||||
}
|
||||
return FileClass::writeFile($filepath, $comment);
|
||||
}
|
||||
}
|
||||
91
app/services/system/log/SystemLogServices.php
Normal file
91
app/services/system/log/SystemLogServices.php
Normal file
@@ -0,0 +1,91 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\services\system\log;
|
||||
|
||||
|
||||
use app\dao\system\log\SystemLogDao;
|
||||
use app\services\BaseServices;
|
||||
use app\services\system\admin\SystemAdminServices;
|
||||
use app\services\system\SystemMenusServices;
|
||||
use think\annotation\Inject;
|
||||
|
||||
/**
|
||||
* 系统日志
|
||||
* Class SystemLogServices
|
||||
* @package app\services\system\log
|
||||
* @mixin SystemLogDao
|
||||
*/
|
||||
class SystemLogServices extends BaseServices
|
||||
{
|
||||
|
||||
/**
|
||||
* @var SystemLogDao
|
||||
*/
|
||||
#[Inject]
|
||||
protected SystemLogDao $dao;
|
||||
|
||||
/**
|
||||
* 记录访问日志
|
||||
* @param int $adminId
|
||||
* @param string $adminName
|
||||
* @param string $module
|
||||
* @param string $rule
|
||||
* @param string $ip
|
||||
* @param string $type
|
||||
* @return bool
|
||||
*/
|
||||
public function recordAdminLog(int $adminId, string $adminName, string $module, string $rule, string $ip, string $type)
|
||||
{
|
||||
/** @var SystemMenusServices $service */
|
||||
$service = app()->make(SystemMenusServices::class);
|
||||
$data = [
|
||||
'method' => $module,
|
||||
'add_time' => time(),
|
||||
'admin_name' => $adminName,
|
||||
'path' => $rule,
|
||||
'page' => $service->getVisitName($rule) ?: '未知',
|
||||
'ip' => $ip,
|
||||
'type' => $type
|
||||
];
|
||||
if ($type == 'store') {
|
||||
$data['store_id'] = $adminId;
|
||||
} else {
|
||||
$data['admin_id'] = $adminId;
|
||||
}
|
||||
if ($this->dao->save($data)) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取系统日志列表
|
||||
* @param array $where
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getLogList(array $where, int $level)
|
||||
{
|
||||
[$page, $limit] = $this->getPageValue();
|
||||
if (!$where['admin_id']) {
|
||||
/** @var SystemAdminServices $service */
|
||||
$service = app()->make(SystemAdminServices::class);
|
||||
$where['admin_id'] = $service->getAdminIds($level);
|
||||
}
|
||||
$list = $this->dao->getLogList($where, $page, $limit);
|
||||
$count = $this->dao->count($where);
|
||||
return compact('list', 'count');
|
||||
}
|
||||
}
|
||||
366
app/services/system/timer/SystemTimerServices.php
Normal file
366
app/services/system/timer/SystemTimerServices.php
Normal file
@@ -0,0 +1,366 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\services\system\timer;
|
||||
|
||||
use app\services\BaseServices;
|
||||
use crmeb\exceptions\AdminException;
|
||||
use app\dao\system\timer\SystemTimerDao;
|
||||
use think\annotation\Inject;
|
||||
|
||||
/**
|
||||
* 定时器service
|
||||
* Class SystemTimerServices
|
||||
* @package app\services\system\timer
|
||||
* @mixin SystemTimerDao
|
||||
*/
|
||||
class SystemTimerServices extends BaseServices
|
||||
{
|
||||
|
||||
/**
|
||||
* @var array|string[]
|
||||
*/
|
||||
protected array $taskName = [
|
||||
'auto_cancel' => '自动取消订单',
|
||||
'auto_take' => '自动确认收货',
|
||||
'auto_comment' => '自动好评',
|
||||
'auto_clear_integral' => '自动清空用户积分',
|
||||
'auto_off_user_svip' => '自动取消用户到期svip',
|
||||
'auto_agent' => '自动解绑上下级',
|
||||
'auto_clear_poster' => '自动清除昨日海报',
|
||||
'auto_sms_code' => '更新短信状态',
|
||||
'auto_live' => '自动更新直播产品状态和直播间状态',
|
||||
'auto_pink' => '拼团状态自动更新',
|
||||
'auto_show' => '自动上下架商品',
|
||||
'auto_channel' => '渠道码定时任务',
|
||||
'auto_moment' => '定时创建发送朋友圈任务',
|
||||
'auto_group_task' => '定时发送群发任务',
|
||||
'auto_seckill' => '定时清理秒杀数据过期的数据缓存',
|
||||
'rebate_points_orders' => '未支付积分订单退积分',
|
||||
'reminder_unverified_remind' => '次卡商品未核销短信提醒',
|
||||
'sign_remind_time' => '用户签到提醒',
|
||||
'auto_presale_product' => '预售商品到期处理数据',
|
||||
'auto_card_code' => '清理到期礼品卡',
|
||||
'holiday_gift_push_task'=>'节日有礼赠送礼品',
|
||||
];
|
||||
|
||||
/**
|
||||
* @var SystemTimerDao
|
||||
*/
|
||||
#[Inject]
|
||||
protected SystemTimerDao $dao;
|
||||
|
||||
/**
|
||||
* 获取定时任务名称
|
||||
* @return array|string[]
|
||||
*/
|
||||
public function getTasKName()
|
||||
{
|
||||
return $this->taskName;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取定时器列表
|
||||
* @param array $where
|
||||
* @return array
|
||||
*/
|
||||
public function getTimerList(array $where)
|
||||
{
|
||||
[$page, $limit] = $this->getPageValue();
|
||||
$list = $this->dao->getList($where, $page, $limit);
|
||||
foreach ($list as $key => &$item) {
|
||||
$item['last_execution_time'] = $item['last_execution_time'] > 0 ? date('Y-m-d H:i:s', $item['last_execution_time']) : '';
|
||||
switch ($item['type']) {
|
||||
case 1:
|
||||
$item['execution_cycle'] = '每隔' . $item['cycle'] . '分钟执行';
|
||||
break;
|
||||
case 2:
|
||||
$arr = explode('/', $item['cycle']);
|
||||
$item['execution_cycle'] = '每' . $arr[0] . '小时, 第' . $arr[1] . '分钟 执行';
|
||||
break;
|
||||
case 3:
|
||||
$item['execution_cycle'] = '每小时, 第' . $item['cycle'] . '分钟执行';
|
||||
break;
|
||||
case 4:
|
||||
$arr = explode('/', $item['cycle']);
|
||||
$item['execution_cycle'] = '每天, ' . $arr[0] . '点' . $arr[1] . '分 执行';
|
||||
break;
|
||||
case 5:
|
||||
$arr = explode('/', $item['cycle']);
|
||||
$item['execution_cycle'] = '每隔' . $arr[0] . '天, ' . $arr[1] . '点' . $arr[2] . '分 执行';
|
||||
break;
|
||||
case 6:
|
||||
$arr = explode('/', $item['cycle']);
|
||||
$item['execution_cycle'] = '每周' . $arr[0] . ', ' . $arr[1] . '点' . $arr[2] . '分执行';
|
||||
break;
|
||||
case 7:
|
||||
$arr = explode('/', $item['cycle']);
|
||||
$item['execution_cycle'] = '每月, ' . $arr[0] . '日 ' . $arr[1] . '点' . $arr[2] . '分执行';
|
||||
break;
|
||||
case 8:
|
||||
$arr = explode('/', $item['cycle']);
|
||||
$item['execution_cycle'] = '每年' . $arr[0] . '月' . $arr[1] . '日 ' . $arr[2] . '点' . $arr[3] . '分执行';
|
||||
break;
|
||||
default:
|
||||
$item['execution_cycle'] = '周期有误!';
|
||||
break;
|
||||
}
|
||||
}
|
||||
$count = $this->dao->count($where);
|
||||
return compact('list', 'count');
|
||||
}
|
||||
|
||||
/**设置或更新定时任务缓存
|
||||
* @return void
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function setAllTimerCache()
|
||||
{
|
||||
$where['is_del'] = 0;
|
||||
$list = $this->dao->getList($where, 0, 0);
|
||||
foreach ($list as $key => &$value) {
|
||||
if (!$value['update_execution_time']) {
|
||||
$update_time = time();
|
||||
$value['update_execution_time'] = $update_time;
|
||||
$this->dao->update($value['id'], ['update_execution_time' => $update_time]);
|
||||
}
|
||||
}
|
||||
$this->dao->cacheCreate($list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置定时器状态
|
||||
* @param $id
|
||||
* @param $is_show
|
||||
*/
|
||||
public function setShow(int $id, int $is_show)
|
||||
{
|
||||
$this->dao->update($id, ['is_open' => $is_show]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除定时器
|
||||
* @param string $id
|
||||
*/
|
||||
public function del(int $id)
|
||||
{
|
||||
if (!$id) throw new AdminException('请选择要删除的定时任务');
|
||||
$this->dao->delete((int)$id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增数据
|
||||
* @param $data
|
||||
*/
|
||||
public function createData($data)
|
||||
{
|
||||
if ($this->dao->be(['mark' => $data['mark'], 'name' => $data['name']])) {
|
||||
throw new AdminException('该定时任务已经存在');
|
||||
}
|
||||
$data['add_time'] = time();
|
||||
$data['update_execution_time'] = time();
|
||||
$res = $this->dao->save($data);
|
||||
if (!$res) throw new AdminException('添加失败');
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存修改数据
|
||||
* @param $id
|
||||
* @param $data
|
||||
*/
|
||||
public function editData($id, $data)
|
||||
{
|
||||
if (!$this->dao->be(['id' => $id])) {
|
||||
throw new AdminException('该定时任务不存在');
|
||||
}
|
||||
$data['update_execution_time'] = time();
|
||||
$res = $this->dao->update($id, $data);
|
||||
if (!$res) throw new AdminException('修改失败');
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**更新缓存
|
||||
* @param $id
|
||||
* @return bool
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function updateOneTimerCache($id)
|
||||
{
|
||||
if (!$id) throw new AdminException('参数错误');
|
||||
$timer = $this->dao->get($id);
|
||||
$this->dao->cacheUpdate($timer->toArray());
|
||||
return true;
|
||||
}
|
||||
|
||||
/**删除缓存
|
||||
* @param $id
|
||||
* @return bool
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function delOneTimerCache($id)
|
||||
{
|
||||
if (!$id) throw new AdminException('参数错误');
|
||||
$this->dao->cacheDelById($id);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**获取单条定时器数据
|
||||
* @param $id
|
||||
* @return void
|
||||
*/
|
||||
public function getOneTimer($id)
|
||||
{
|
||||
if (!$id) throw new AdminException('请选择要删除的定时任务');
|
||||
$timer = $this->dao->get($id);
|
||||
if (!$timer) throw new AdminException('该定时任务不存在');
|
||||
return $timer->toArray();
|
||||
}
|
||||
|
||||
/**获取下次执行时间
|
||||
* @param $type
|
||||
* @param $cycle
|
||||
* @param $time
|
||||
* @param $start_time
|
||||
* @return array
|
||||
*/
|
||||
public function getTimerCycleTime($type, $cycle, $time, $start_time = 0)
|
||||
{
|
||||
if (!$time) $time = time();
|
||||
switch ($type) {
|
||||
case 1: // N分钟
|
||||
$cycle_time = 60 * $cycle;
|
||||
$i = $time - $start_time;
|
||||
$more = $i % $cycle_time;
|
||||
if ($more == 0) {
|
||||
$cycle_time = $time;
|
||||
} else {
|
||||
$cycle_time = $time - $more + $cycle_time;
|
||||
}
|
||||
break;
|
||||
case 2: //N小时
|
||||
$arr = explode('/', $cycle);
|
||||
$todaystart = strtotime(date('Y-m-d H' . ':00:00', $time));
|
||||
$start_time = strtotime(date('Y-m-d H' . ':00:00', $start_time));
|
||||
if ($arr[0] <= 0) {
|
||||
$cycle_time = 60 * $arr[1];
|
||||
$i = $time - $start_time;
|
||||
$more = $i % $cycle_time;
|
||||
if ($more == 0) {
|
||||
$cycle_time = $time;
|
||||
} else {
|
||||
$cycle_time = $time - $more + $cycle_time;
|
||||
}
|
||||
} else {
|
||||
$h = ($todaystart - $start_time) / 3600;
|
||||
$h = floor($h);
|
||||
$more = $h % $arr[0];
|
||||
if ($more == 0) {
|
||||
$cycle_time = 60 * $arr[1];
|
||||
$cycle_time1 = $todaystart + $cycle_time;
|
||||
if ($cycle_time1 < $time) {
|
||||
$cycle_time = 60 * 60 * $arr[0] + 60 * $arr[1];
|
||||
}
|
||||
} else {
|
||||
$sh = $arr[0] - $more;
|
||||
$cycle_time = 60 * 60 * $sh + 60 * $arr[1];
|
||||
}
|
||||
$cycle_time = $todaystart + $cycle_time;
|
||||
}
|
||||
|
||||
break;
|
||||
case 3: //每小时
|
||||
$cycle_time = strtotime(date('Y-m-d ' . 'H:' . $cycle . ':00', $time));
|
||||
break;
|
||||
case 4: //每天
|
||||
$arr = explode('/', $cycle);
|
||||
$cycle_time = strtotime(date('Y-m-d ' . $arr[0] . ':' . $arr[1] . ':00', $time));
|
||||
break;
|
||||
case 5: //N天
|
||||
$arr = explode('/', $cycle);
|
||||
$todaystart = strtotime(date('Y-m-d ' . '00:00:00', $time));
|
||||
$start_time = strtotime(date('Y-m-d ' . '00:00:00', $start_time));
|
||||
$d = ($todaystart - $start_time) / 86400;
|
||||
$d = floor($d);
|
||||
$more = $d % $arr[0];
|
||||
if ($more == 0) {
|
||||
$cycle_time = 60 * 60 * $arr[1] + 60 * $arr[2];
|
||||
$cycle_time1 = $todaystart + $cycle_time;
|
||||
if ($cycle_time1 < $time) {
|
||||
$cycle_time = 60 * 60 * 24 * $more + 60 * 60 * $arr[1] + 60 * $arr[2];
|
||||
}
|
||||
} else {
|
||||
$sd = $arr[0] - $more;
|
||||
$cycle_time = 60 * 60 * 24 * $sd + 60 * 60 * $arr[1] + 60 * $arr[2];
|
||||
}
|
||||
$cycle_time = $todaystart + $cycle_time;
|
||||
break;
|
||||
case 6: //每星期
|
||||
$arr = explode('/', $cycle);
|
||||
$todaystart = strtotime(date('Y-m-d ' . '00:00:00', $time));
|
||||
$w = date("w");
|
||||
if ($w > $arr[0]) {
|
||||
$d = 7 - $w + $arr[0];
|
||||
$cycle_time = $todaystart + 60 * 60 * 24 * $d + 60 * 60 * $arr[1] + 60 * $arr[2];
|
||||
} else if ($w == $arr[0]) {
|
||||
$to_time = 60 * 60 * $arr[1] + 60 * $arr[2];
|
||||
$to_time = $todaystart + $to_time;
|
||||
if ($time > $to_time) {
|
||||
$d = 7 - $w + $arr[0];
|
||||
$cycle_time = $todaystart + 60 * 60 * 24 * $d + 60 * 60 * $arr[1] + 60 * $arr[2];
|
||||
} else {
|
||||
$cycle_time = $to_time;
|
||||
}
|
||||
} else {
|
||||
$d = $arr[0] - $w;
|
||||
$cycle_time = $todaystart + 60 * 60 * 24 * $d + 60 * 60 * $arr[1] + 60 * $arr[2];
|
||||
}
|
||||
break;
|
||||
case 7: //每月
|
||||
$arr = explode('/', $cycle);
|
||||
$current_d = date("d");
|
||||
$firstDate = date('Y-m-01', $time);
|
||||
$max_d = date('d', strtotime("$firstDate + 1 month -1 day"));
|
||||
$todaystart = strtotime(date('Y-m-d ' . '00:00:00', $time));
|
||||
if ($current_d > $arr[0]) {
|
||||
$d = $max_d - $current_d + $arr[0];
|
||||
$cycle_time = $todaystart + 60 * 60 * 24 * $d + 60 * 60 * $arr[1] + 60 * $arr[2];
|
||||
} elseif ($current_d == $arr[0]) {
|
||||
$to_time = 60 * 60 * $arr[1] + 60 * $arr[2];
|
||||
$to_time = $todaystart + $to_time;
|
||||
if ($time > $to_time) {
|
||||
$d = $max_d - $current_d + $arr[0];
|
||||
$cycle_time = $todaystart + 60 * 60 * 24 * $d + 60 * 60 * $arr[1] + 60 * $arr[2];
|
||||
} else {
|
||||
$cycle_time = $to_time;
|
||||
}
|
||||
} else {
|
||||
$d = $arr[0] - $current_d;
|
||||
$cycle_time = $todaystart + 60 * 60 * 24 * $d + 60 * 60 * $arr[1] + 60 * $arr[2];
|
||||
}
|
||||
break;
|
||||
case 8: //每年
|
||||
$arr = explode('/', $cycle);
|
||||
$cycle_time = strtotime(date('Y-' . $arr[0] . '-' . $arr[1] . ' ' . $arr[2] . ':' . $arr[3] . ':00', $time));
|
||||
break;
|
||||
default:
|
||||
$cycle_time = 0;
|
||||
break;
|
||||
}
|
||||
return ['cycle_time' => $cycle_time];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user