SystemNoticeConfigRepository.php 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
  4. // +----------------------------------------------------------------------
  5. // | Copyright (c) 2016~2024 https://www.crmeb.com All rights reserved.
  6. // +----------------------------------------------------------------------
  7. // | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
  8. // +----------------------------------------------------------------------
  9. // | Author: CRMEB Team <admin@crmeb.com>
  10. // +----------------------------------------------------------------------
  11. namespace app\common\repositories\system\notice;
  12. use app\common\dao\system\notice\SystemNoticeConfigDao;
  13. use app\common\repositories\BaseRepository;
  14. use crmeb\exceptions\WechatException;
  15. use crmeb\services\MiniProgramService;
  16. use crmeb\services\WechatService;
  17. use FormBuilder\Factory\Elm;
  18. use think\exception\ValidateException;
  19. use think\facade\Route;
  20. /**
  21. * 通知管理
  22. */
  23. class SystemNoticeConfigRepository extends BaseRepository
  24. {
  25. public function __construct(SystemNoticeConfigDao $dao)
  26. {
  27. $this->dao = $dao;
  28. }
  29. /**
  30. * 根据条件获取列表数据
  31. *
  32. * 本函数用于根据给定的条件数组和分页信息,从数据库中检索满足条件的数据列表。
  33. * 它首先构造一个查询,然后计算满足条件的数据总数,最后根据分页信息和排序条件获取具体的数据。
  34. *
  35. * @param array $where 查询条件数组,包含一个或多个条件键值对。
  36. * @param int $page 当前页码,用于分页查询。
  37. * @param int $limit 每页的数据条数,用于分页查询。
  38. * @return array 返回一个包含 'count' 和 'list' 两个元素的数组,'count' 为满足条件的数据总数,'list' 为当前页码的数据列表。
  39. */
  40. public function getList(array $where, $page, $limit)
  41. {
  42. // 根据条件数组构造查询
  43. $query = $this->dao->getSearch($where);
  44. // 计算满足条件的数据总数
  45. $count = $query->count();
  46. // 根据当前页码和每页数据条数进行分页查询,并按创建时间升序排序
  47. $list = $query->page($page, $limit)->order('create_time ASC')->select();
  48. // 返回包含数据总数和数据列表的数组
  49. return compact('count', 'list');
  50. }
  51. /**
  52. * 创建或编辑通知配置的表单
  53. *
  54. * 该方法用于生成一个包含通知配置信息的表单,根据$id$的存在与否决定是创建新的通知配置还是编辑已有的通知配置。
  55. * 表单中包括了各种通知方式(站内消息、公众号模板消息、小程序订阅消息、短信消息)的开关控制,以及通知的标题、说明、关键字等信息的输入字段。
  56. * 通知类型(用户或商户)的选择也被包含在表单中,此外,针对短信、公众号模板和小程序订阅消息,提供了内容输入的文本区域。
  57. *
  58. * @param int|null $id 通知配置的ID,如果为NULL,则表示创建新的通知配置;否则,表示编辑已有的通知配置。
  59. * @return \think\form\Form 返回一个包含通知配置表单的实例。
  60. * @throws ValidateException 如果根据$id$查询不到已有的通知配置,则抛出验证异常。
  61. */
  62. public function form(?int $id)
  63. {
  64. // 初始化表单数据数组
  65. $formData = [];
  66. // 如果$id$存在
  67. if ($id) {
  68. // 通过$id$查询通知配置数据
  69. $data = $this->dao->get($id);
  70. // 如果查询不到数据,抛出异常
  71. if (!$data) throw new ValidateException('数据不存在');
  72. // 将查询到的数据转换为数组,并赋值给formData
  73. $formData = $data->toArray();
  74. // 创建编辑通知配置的表单,提交地址为更新通知配置的路由URL
  75. $form = Elm::createForm(Route::buildUrl('systemNoticeConfigUpdate', ['id' => $id])->build());
  76. } else {
  77. // 创建新建通知配置的表单,提交地址为创建通知配置的路由URL
  78. $form = Elm::createForm(Route::buildUrl('systemNoticeConfigCreate')->build());
  79. }
  80. // 设置表单的验证规则,包括各种输入字段及其验证要求
  81. $form->setRule([
  82. // 通知标题输入框
  83. Elm::input('notice_title', '通知名称:')->placeholder('请输入通知名称')->required(),
  84. // 通知说明输入框
  85. Elm::input('notice_info', '通知说明:')->placeholder('请输入通知说明')->required(),
  86. // 通知关键字输入框
  87. Elm::input('notice_key', '通知KEY:')->placeholder('请输入通知KEY')->required(),
  88. // 站内消息开关选择器
  89. Elm::radio('notice_sys', '站内消息:', -1)->options([
  90. ['value' => 0, 'label' => '关闭'],
  91. ['value' => 1, 'label' => '开启'],
  92. ['value' => -1, 'label' => '无'],
  93. ])->requiredNum(),
  94. // 公众号模板消息开关选择器
  95. Elm::radio('notice_wechat', '公众号模板消息:', -1)->options([
  96. ['value' => 0, 'label' => '关闭'],
  97. ['value' => 1, 'label' => '开启'],
  98. ['value' => -1, 'label' => '无'],
  99. ])->requiredNum(),
  100. // 小程序订阅消息开关选择器
  101. Elm::radio('notice_routine', '小程序订阅消息:', -1)->options([
  102. ['value' => 0, 'label' => '关闭'],
  103. ['value' => 1, 'label' => '开启'],
  104. ['value' => -1, 'label' => '无'],
  105. ])->requiredNum(),
  106. // 短信消息开关选择器
  107. Elm::radio('notice_sms', '短信消息:', -1)->options([
  108. ['value' => 0, 'label' => '关闭'],
  109. ['value' => 1, 'label' => '开启'],
  110. ['value' => -1, 'label' => '无'],
  111. ])->requiredNum(),
  112. // 通知类型选择器
  113. Elm::radio('type', '通知类型:', 0)->options([
  114. ['value' => 0, 'label' => '用户'],
  115. ['value' => 1, 'label' => '商户'],
  116. ])->requiredNum(),
  117. // 短信内容输入框
  118. Elm::textarea('sms_content','短信内容:')->placeholder('请输入短信内容'),
  119. // 公众号模板内容输入框
  120. Elm::textarea('wechat_content','公众号模板内容:')->placeholder('请输入公众号模板内容'),
  121. // 小程序订阅消息内容输入框
  122. Elm::textarea('routine_content','小程序订阅消息内容:')->placeholder('请输入小程序订阅消息内容'),
  123. ]);
  124. // 设置表单标题,根据$id$的存在与否决定是"添加通知"还是"编辑通知"
  125. // 并将之前准备的formData赋值给表单,用于预填充已有的通知配置数据
  126. return $form->setTitle(is_null($id) ? '添加通知' : '编辑通知')->formData($formData);
  127. }
  128. /**
  129. * 切换实体的状态。
  130. *
  131. * 该方法用于根据给定的ID和字段名,改变特定字段的状态。主要应用于需要动态更新数据状态的场景,
  132. * 比如启用或禁用某个功能、标记某个项为已读或未读等。
  133. *
  134. * @param int $id 主键ID,用于定位特定的实体。
  135. * @param string $filed 需要改变状态的字段名。
  136. * @param int $status 新的状态值。通常是一个表示状态的整数,比如0表示禁用,1表示启用。
  137. * @throws ValidateException 如果字段值为-1,则抛出异常,表示该消息无此通知类型。
  138. */
  139. public function swithStatus($id, $filed, $status)
  140. {
  141. // 通过主键ID获取实体数据。
  142. $data = $this->dao->get($id);
  143. // 检查字段值,如果为-1,则抛出异常,表示该消息无此通知类型。
  144. if ($data[$filed] == -1) throw new ValidateException('该消息无此通知类型');
  145. // 更新字段状态为新的状态值。
  146. $data->$filed = $status;
  147. // 保存更新后的数据。
  148. $data->save();
  149. }
  150. /**
  151. * 根据键获取系统通知的状态
  152. *
  153. * 本函数通过与数据库交互,检索特定键对应的系统通知状态。
  154. * 它被设计为类的一部分,旨在提供关于系统通知状态的信息。
  155. *
  156. * @param string $key 键值,用于唯一标识通知状态。
  157. * @return mixed 返回与键关联的系统通知状态。具体数据类型取决于数据库返回的结果。
  158. */
  159. public function getNoticeSys($key)
  160. {
  161. // 通过调用DAO层的方法,查询数据库中键为$key的系统通知状态
  162. return $this->dao->getNoticeStatusByKey($key, 'notice_sys');
  163. }
  164. /**
  165. * 根据键获取通知短信的状态
  166. *
  167. * 本函数通过与数据访问对象(DAO)交互,来获取特定键所对应的通知短信状态。
  168. * 主要用于查询系统中配置的通知方式(如短信、邮件等)是否启用。
  169. *
  170. * @param string $key 键值,用于唯一标识特定的通知配置项。
  171. * @return bool 返回通知短信的状态,启用为true,禁用为false。
  172. */
  173. public function getNoticeSms($key)
  174. {
  175. // 通过DAO层方法查询并返回指定键对应的短信通知状态
  176. return $this->dao->getNoticeStatusByKey($key, 'notice_sms');
  177. }
  178. /**
  179. * 根据键值获取微信通知状态
  180. *
  181. * 本函数通过调用DAO层的方法,来获取特定键值对应的通知状态,特别针对微信通知。
  182. * 这里的键值可能是用户ID、订单ID等,用于唯一标识通知的接收方或相关对象。
  183. * 返回的通知状态可以是开启或关闭,具体取决于数据库中的设置。
  184. *
  185. * @param string $key 键值,用于查找通知状态
  186. * @return bool|null 返回对应键值的微信通知状态,true表示开启,false表示关闭,null表示查询失败或无数据
  187. */
  188. public function getNoticeWechat($key)
  189. {
  190. // 调用DAO方法,查询并返回键值为$key的微信通知状态
  191. return $this->dao->getNoticeStatusByKey($key, 'notice_wechat');
  192. }
  193. /**
  194. * 根据键值获取推送通知的常规状态
  195. *
  196. * 本函数旨在通过指定的键值查询数据库,以获取特定通知的常规状态。
  197. * 这里的“常规状态”可能指的是通知的可见性、有效性或其他与通知常规属性相关的状态。
  198. *
  199. * @param string $key 键值,用于在数据库中唯一标识通知记录。
  200. * @return mixed 返回查询结果,可能是通知的状态值,具体取决于数据库查询的结果。
  201. */
  202. public function getNoticeRoutine($key)
  203. {
  204. // 通过键值和类型查询通知状态,这里的类型固定为'notice_routine'
  205. return $this->dao->getNoticeStatusByKey($key, 'notice_routine');
  206. }
  207. /**
  208. * 根据键获取短信模板ID。
  209. *
  210. * 本函数用于根据给定的键值查询短信模板。如果模板存在且启用了短信通知,
  211. * 则根据系统配置的短信使用类型返回相应的模板ID:如果使用阿里云短信服务,
  212. * 则返回阿里云短信模板ID;否则返回默认短信模板ID。
  213. *
  214. * @param string $key 模板的唯一标识键。
  215. * @return string 返回查询到的短信模板ID,如果未找到或未启用短信通知,则返回空字符串。
  216. */
  217. public function getSmsTemplate(string $key)
  218. {
  219. // 根据键值查询模板信息
  220. $temp = $this->dao->getWhere(['const_key' => $key]);
  221. // 检查模板是否存在且启用了短信通知
  222. if ($temp && $temp['notice_sms'] == 1) {
  223. // 根据系统配置的短信使用类型返回相应的模板ID
  224. return systemConfig('sms_use_type') == 2 ? $temp['sms_ali_tempid'] : $temp['sms_tempid'];
  225. }
  226. // 如果模板不存在或未启用短信通知,返回空字符串
  227. return '';
  228. }
  229. /**
  230. * 编辑消息模板ID
  231. * @param $id
  232. * @return \FormBuilder\Form
  233. * @author Qinii
  234. * @day 6/9/22
  235. */
  236. public function changeForm($id)
  237. {
  238. $formData = $this->dao->get($id);
  239. if (!$formData) throw new ValidateException('数据不存在');
  240. $form = Elm::createForm(Route::buildUrl('systemNoticeConfigSetChangeTempId', ['id' => $id])->build());
  241. $children = [];
  242. $value = '';
  243. if ($formData->notice_sms != -1) {
  244. $value = 'sms';
  245. if (systemConfig('sms_use_type') == 2) {
  246. $sms = [
  247. 'type' => 'el-tab-pane',
  248. 'props' => [
  249. 'label' => '阿里云短信',
  250. 'name' => 'sms'
  251. ],
  252. 'children' =>[
  253. Elm::input('title','通知类型:', $formData->notice_title)->placeholder('请输入通知类型')->disabled(true),
  254. Elm::input('info','场景说明:', $formData->notice_info)->disabled(true)->placeholder('请输入场景说明'),
  255. Elm::input('sms_ali_tempid','短信模板ID:')->placeholder('请输入短信模板ID'),
  256. Elm::input('notice_info','短信说明:')->disabled(true)->placeholder('请输入短信说明'),
  257. Elm::textarea('sms_content','短信内容:')->disabled(true),
  258. Elm::switches('notice_sms', '是否开启:', 1)->activeValue(1)->inactiveValue(0)->inactiveText('关')->activeText('开'),
  259. ]
  260. ];
  261. } else {
  262. $sms = [
  263. 'type' => 'el-tab-pane',
  264. 'props' => [
  265. 'label' => '一号通短信',
  266. 'name' => 'sms'
  267. ],
  268. 'children' =>[
  269. Elm::input('title','通知类型:', $formData->notice_title)->disabled(true),
  270. Elm::input('info','场景说明:', $formData->notice_info)->disabled(true),
  271. Elm::input('sms_tempid','短信模板ID:'),
  272. Elm::input('notice_info','短信说明:')->disabled(true),
  273. Elm::textarea('sms_content','短信内容:')->disabled(true),
  274. Elm::switches('notice_sms', '是否开启:', 1)->activeValue(1)->inactiveValue(0)->inactiveText('关')->activeText('开'),
  275. ]
  276. ];
  277. }
  278. $children[] = $sms;
  279. }
  280. if ($formData->notice_wechat != -1 ) {
  281. if (!$value) $value = 'wechat';
  282. $children[] = [
  283. 'type' => 'el-tab-pane',
  284. 'props' => [
  285. 'label' => '模板消息',
  286. 'name' => 'wechat'
  287. ],
  288. 'children' =>[
  289. Elm::input('title1','通知类型:', $formData->notice_title)->disabled(true),
  290. Elm::input('info1','场景说明:', $formData->notice_info)->disabled(true),
  291. Elm::input('wechat_tempkey','模板消息编号:', $formData->wechat_tempkey)->disabled(true),
  292. Elm::input('wechat_tempid','模板消息ID:', $formData->wechat_tempid),
  293. Elm::textarea('wechat_content','模板消息内容:', $formData->wechat_content)->disabled(true),
  294. Elm::switches('notice_wechat', '是否开启:', 1)->activeValue(1)->inactiveValue(0)->inactiveText('关')->activeText('开'),
  295. ]
  296. ];
  297. }
  298. if ($formData->notice_routine != -1) {
  299. if (!$value) $value = 'routine';
  300. $children[] = [
  301. 'type' => 'el-tab-pane',
  302. 'props' => [
  303. 'label' => '订阅消息',
  304. 'name' => 'routine'
  305. ],
  306. 'children' =>[
  307. Elm::input('title2','通知类型:', $formData->notice_title)->disabled(true),
  308. Elm::input('info2','场景说明:', $formData->notice_info)->disabled(true),
  309. Elm::input('routine_tempkey','订阅消息编号:', $formData->routine_tempkey)->disabled(true),
  310. Elm::input('routine_tempid','订阅消息ID:', $formData->routine_tempid),
  311. Elm::textarea('routine_content','订阅消息内容:', $formData->routine_content)->disabled(true),
  312. Elm::switches('notice_routine', '是否开启:', $formData->notice_routine)->activeValue(1)->inactiveValue(0)->inactiveText('关')->activeText('开'),
  313. ]
  314. ];
  315. }
  316. $form->setRule([
  317. [
  318. 'type' => 'el-tabs',
  319. 'native' => true,
  320. 'props' => [
  321. 'value' => $value
  322. ],
  323. 'children' => $children
  324. ]
  325. ]);
  326. return $form->setTitle( '编辑消息模板')->formData($formData->toArray());
  327. }
  328. /**
  329. * 获取模板列表
  330. * 根据$type的值决定查询微信模板还是小程序模板的信息
  331. *
  332. * @param int $type 模板类型,1代表微信模板,0代表小程序模板
  333. * @return array 返回包含模板列表和总数的数组
  334. */
  335. public function getTemplateList($type)
  336. {
  337. // 根据$type的值,确定查询微信模板还是小程序模板,并设置相应的查询条件
  338. if ($type) {
  339. $where['is_wechat'] = 1;
  340. $field = 'notice_title,notice_config_id,notice_wechat,wechat_tempkey tempkey,wechat_content content,wechat_tempid tempid,type,kid';
  341. } else {
  342. $where['is_routine'] = 1;
  343. $field = 'notice_title,notice_config_id,notice_routine,routine_tempkey tempkey,routine_content content,routine_tempid tempid,type,kid';
  344. }
  345. // 执行查询操作
  346. $query = $this->dao->search($where);
  347. // 统计查询结果的总数
  348. $count = $query->count();
  349. // 设置查询字段并执行查询,获取模板列表
  350. $list = $query->setOption('field',[])->field($field)->field($field)->select();
  351. // 对查询结果中的每个模板内容进行处理,如果存在内容,则按换行符分割
  352. foreach ($list as &$item) {
  353. if ($item['content']) {
  354. $item['content'] = (strpos($item['content'], "\\n") !== false) ? explode("\\n", $item['content']) : explode("\n", $item['content']);
  355. }
  356. }
  357. // 返回包含模板列表和总数的数组
  358. return compact('list', 'count');
  359. }
  360. }