AttachmentService.php 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479
  1. <?php
  2. namespace services\common;
  3. use common\enums\AddonsEnum;
  4. use Yii;
  5. use yii\data\Pagination;
  6. use yii\web\NotFoundHttpException;
  7. use common\models\common\Attachment;
  8. use common\components\Service;
  9. use common\enums\RabbitMqEnum;
  10. use common\helpers\ArrayHelper;
  11. use common\helpers\UploadHelper;
  12. use common\models\common\AttachmentGroup;
  13. use common\models\common\PlatformSetting;
  14. use common\models\common\MallSetting;
  15. use Exception;
  16. /**
  17. *
  18. * Class AttachmentService
  19. * @package services\common
  20. */
  21. class AttachmentService extends Service
  22. {
  23. /**
  24. * 系统图标 全部商城都要显示
  25. *
  26. * @var array
  27. */
  28. public $systemIconGroup = [
  29. [
  30. 'id' => 999990,
  31. 'name' => '系统图标',
  32. 'parent_id' => 0,
  33. ],
  34. [
  35. 'id' => 99991,
  36. 'name' => '商业模式',
  37. 'parent_id' => 999990,
  38. ],
  39. [
  40. 'id' => 99992,
  41. 'name' => '拓客营销',
  42. 'parent_id' => 999990,
  43. ],
  44. [
  45. 'id' => 99993,
  46. 'name' => '我的订单',
  47. 'parent_id' => 999990,
  48. ],
  49. [
  50. 'id' => 99994,
  51. 'name' => '行业运营',
  52. 'parent_id' => 999990,
  53. ],
  54. // <hst-start>增加商品分类默认图标,禅道ID1152,类型:优化
  55. // 注意事项:三级分类的id位数为二级分类的位数,三级分类的第三位开始二一级分类的最后一位,依次递增。
  56. [
  57. 'id' => 99995,
  58. 'name' => '商品分类',
  59. 'parent_id' => 999990,
  60. ],
  61. ['id' => 95001, 'name' => '电脑办公', 'parent_id' => 99995,],
  62. ['id' => 95002, 'name' => '个护清洁', 'parent_id' => 99995,],
  63. ['id' => 95003, 'name' => '家用电器', 'parent_id' => 99995,],
  64. ['id' => 95004, 'name' => '美妆护肤', 'parent_id' => 99995,],
  65. ['id' => 95005, 'name' => '生鲜', 'parent_id' => 99995,],
  66. ['id' => 95006, 'name' => '食品酒饮', 'parent_id' => 99995,],
  67. ['id' => 95007, 'name' => '医疗保健', 'parent_id' => 99995,],
  68. // <hst-end>
  69. ];
  70. /**
  71. * 修改分组
  72. *
  73. * @param array $post
  74. * @return boolean
  75. * @throws Exception
  76. */
  77. public function saveGroup(array $post)
  78. {
  79. if ($this->isSystemGroup($post['parent_id'])) {
  80. throw new Exception('系统图标无法更改');
  81. }
  82. return AttachmentGroup::saveGroup($post);
  83. }
  84. /**
  85. * 删除分组
  86. *
  87. * @param array $ids
  88. * @param integer $mall_id
  89. * @param integer $mch_id
  90. * @return boolean
  91. * @throws Exception
  92. */
  93. public function deleteGroup(array $ids, int $mall_id, int $mch_id = 0)
  94. {
  95. if ($this->isSystemGroup($ids)) {
  96. throw new Exception('系统图标无法删除');
  97. }
  98. return AttachmentGroup::deleteGroup($ids, $mall_id, $mch_id);
  99. }
  100. /**
  101. * 获取分组
  102. *
  103. * @param integer $mall_id
  104. * @param integer $type 1 or 0
  105. * @param integer $is_recycle
  106. * @return array
  107. */
  108. public function getGroupByTypeAndMallId(int $mall_id, int $type = 0, int $is_recycle = 0)
  109. {
  110. $query = AttachmentGroup::find()->where([
  111. 'mall_id' => $mall_id,
  112. 'is_delete' => 0,
  113. // 'mch_id' => 0
  114. ]);
  115. $query->andWhere(['type' => $type]);
  116. $is_recycle && $query->andWhere(['is_recycle' => $is_recycle]);
  117. $list = $query->asArray()->all();
  118. return ArrayHelper::merge($list, $this->systemIconGroup);
  119. }
  120. /**
  121. * 删除文件
  122. *
  123. * @param array $ids
  124. * @param integer $mall_id
  125. * @return boolean
  126. * @throws Exception
  127. */
  128. public function delFile(array $ids, int $mall_id)
  129. {
  130. // 删除前查询删除内容是否包含系统图标
  131. if (
  132. Attachment::isSystemFile($ids, $this->getSystemIconGroupIds())
  133. ) {
  134. throw new Exception('删除内容包含系统图标无法操作');
  135. }
  136. // 更改
  137. Attachment::updateAll(['is_delete' => Attachment::IS_DELETE_TEMP], [
  138. 'id' => $ids,
  139. 'mall_id' => $mall_id,
  140. ]);
  141. // 删除文件
  142. Yii::$app->services->rabbitMq->push(
  143. RabbitMqEnum::EXCHANGE_TASK,
  144. RabbitMqEnum::TASK_QUEUE,
  145. $ids,
  146. get_class(Yii::$app->services->attachment),
  147. 'delete'
  148. );
  149. return true;
  150. }
  151. /**
  152. * 挪动文件到某个分组
  153. *
  154. * @param array|int $ids
  155. * @param integer $mall_id
  156. * @param integer $group_id
  157. * @return boolean
  158. */
  159. public function moveFileToGroupId($ids, int $mall_id, int $group_id)
  160. {
  161. // 移动前查询删除内容是否包含系统图标
  162. if (
  163. Attachment::isSystemFile($ids, $this->getSystemIconGroupIds())
  164. ) {
  165. throw new Exception('移动内容包含系统图标无法操作');
  166. }
  167. if ($this->isSystemGroup($group_id)) {
  168. throw new Exception('系统图标文件夹不允许操作');
  169. }
  170. $attachmentGroup = AttachmentGroup::getGroupById($mall_id, $group_id);
  171. // 分组不存在
  172. if (empty($attachmentGroup)) throw new Exception('分组不存在');
  173. Attachment::updateAll(['group_id' => $group_id], [
  174. 'id' => $ids,
  175. 'mall_id' => $mall_id,
  176. ]);
  177. return true;
  178. }
  179. /**
  180. * @param $data
  181. * @return int
  182. * @throws NotFoundHttpException
  183. */
  184. public function create($data)
  185. {
  186. $model = new Attachment();
  187. $model->attributes = $data;
  188. if (!$model->save()) {
  189. $firstErrors = $model->getFirstErrors() ?: ['未捕获到错误信息'];
  190. throw new NotFoundHttpException(array_values($firstErrors)[0]);
  191. }
  192. return $model->id;
  193. }
  194. /**
  195. * 获取系统图标组的IDS
  196. *
  197. * @return array
  198. */
  199. public function getSystemIconGroupIds()
  200. {
  201. return ArrayHelper::getColumn($this->systemIconGroup, 'id');
  202. }
  203. /**
  204. * 是否是系统图标组
  205. *
  206. * @param integer|array $group_id
  207. * @return boolean
  208. */
  209. public function isSystemGroup($group_id): bool
  210. {
  211. if (is_array($group_id)) {
  212. foreach ($group_id as $item) {
  213. if (in_array($item, $this->getSystemIconGroupIds())) {
  214. return true;
  215. }
  216. }
  217. return false;
  218. } else {
  219. return in_array($group_id, $this->getSystemIconGroupIds());
  220. }
  221. }
  222. /**
  223. * @param int $mall_id
  224. * @param string $uploadType
  225. * @param int $group_id
  226. * @param string $drive
  227. * @param string $keyword
  228. * @return array
  229. */
  230. public function getListPage($mall_id, $uploadType = '', $group_id = 0,$drive = '', $keyword = '', $store_id = 0, $mch_id = 0, $addons_name = '')
  231. {
  232. // 这些插件上传的图片不显示出来
  233. $excludeAddons = [
  234. AddonsEnum::ADDONS_NAME_CLOUD_PRESCRIPTION
  235. ];
  236. $where = [
  237. ['=', 'is_delete', 0],
  238. ['=', 'mall_id', $mall_id],
  239. ['NOT IN', 'addons_name', $excludeAddons],
  240. ];
  241. // 查询系统图标时 mall_id 修改为0
  242. if ($this->isSystemGroup($group_id)) {
  243. $where = [
  244. ['=', 'is_delete', 0],
  245. ['=', 'mall_id', 0],
  246. ];
  247. }
  248. if ($uploadType) {
  249. $where[] = ['=', 'upload_type', $uploadType];
  250. }
  251. if ($group_id) {
  252. $where[] = ['=', 'group_id', $group_id];
  253. }
  254. if ($drive) {
  255. $where[] = ['=', 'drive', $drive];
  256. }
  257. if ($keyword) {
  258. $where[] = ['like', 'old_name', $keyword];
  259. }
  260. // 如果是门店则只能看到自己门店和平台的
  261. if ($store_id) {
  262. $where[] = ['in', 'store_id', [0, $store_id]];
  263. }
  264. if (!empty($addons_name)) {
  265. $where[] = ['=', 'addons_name', $addons_name];
  266. }
  267. // 如果是多商户则只能看到自己多商户和平台的
  268. if ($mch_id) {
  269. $where[] = ['in', 'mch_id', [0, $mch_id]];
  270. }
  271. $select = ['id', 'url', 'thumb_url', 'upload_type', 'drive', 'name', 'old_name', 'size', 'created_at'];
  272. $result = Attachment::getPageList(20, function ($query) use ($where, $select) {
  273. array_unshift($where, 'and');
  274. $query->andWhere($where)->select($select);
  275. });
  276. $static_url = Yii::$app->services->setting->get('system.static_url') ?? '';
  277. if ($result && $static_url) {
  278. foreach ($result['list'] as &$item) {
  279. if ($item['drive'] == 'local' && strpos($item['url'], 'http') === false) {
  280. $item['url'] = $static_url . $item['url'];
  281. }
  282. }
  283. }
  284. return $result;
  285. }
  286. /**
  287. * 删除文件
  288. * @param array $ids
  289. * @throws
  290. * @return bool
  291. */
  292. public function delete($ids)
  293. {
  294. try{
  295. foreach($ids as $id){
  296. $attachment = Attachment::findOne(['id' => $id]);
  297. if ($this->isSystemGroup($attachment->group_id)) {
  298. continue;
  299. }
  300. if(!$attachment){
  301. continue;
  302. }
  303. if($attachment->drive == Attachment::DRIVE_LOCAL){
  304. $config = ['drive' => Attachment::DRIVE_LOCAL];
  305. }else{
  306. //获取对应配置
  307. $config = $this->getStorageConfig($attachment->mall_id,$attachment->drive);
  308. }
  309. $upload = new UploadHelper($config, $attachment->upload_type);
  310. $res = $upload->delete($attachment->path);
  311. if($res){
  312. $attachment->is_delete = Attachment::IS_DELETE_COMPLETE;
  313. $attachment->save();
  314. }
  315. }
  316. return true;
  317. }catch(\Exception $e){
  318. Yii::error('delete file error:'.$e->getMessage());
  319. return false;
  320. }
  321. }
  322. /**
  323. * 获取商城的设置
  324. * @param $mall_id
  325. * @param string $driver
  326. * @return array|mixed
  327. */
  328. public function getStorageConfigMall($mall_id,$driver = '')
  329. {
  330. $setting = [];
  331. $mall_driver = $driver ?: Yii::$app->services->setting->mall->get($mall_id, 'storage.driver');
  332. if($mall_driver !== Attachment::DRIVE_LOCAL) {
  333. $mall_setting = !empty($mall_driver) ? Yii::$app->services->setting->mall->get($mall_id, 'storage_driver.' . $mall_driver) : [];
  334. if($mall_setting){
  335. $has_storage = true;// 判断配置是否为空
  336. $setting = json_decode($mall_setting, true);
  337. // 因为后台添加ram 配置, 但是之前客户是没有填写ram或者不需要填写的。所以这里过滤下
  338. foreach ($setting as $key => $value) {
  339. if (empty($value) && $key != 'arn') {
  340. $has_storage = false;
  341. break;
  342. }
  343. }
  344. if ($has_storage === false) {
  345. $setting = [];// 不填配置则直接放回空配置
  346. } else {
  347. $setting['drive'] = $mall_driver;
  348. }
  349. }
  350. }
  351. return $setting;
  352. }
  353. /**
  354. * 获取文件上传配置
  355. * @param $mall_id
  356. * @param string $driver
  357. * @return array
  358. */
  359. public function getStorageConfig($mall_id,$driver = '')
  360. {
  361. if($mall_id > 0 ){
  362. $setting = $this->getStorageConfigMall($mall_id,$driver);
  363. if($setting) return $setting;
  364. }
  365. //获取商城配置
  366. $setting = ['drive' => Attachment::DRIVE_LOCAL]; //默认配置:本地存储
  367. $mall_driver = $driver ?: Yii::$app->services->setting->get('storage.driver');
  368. if($mall_driver !== Attachment::DRIVE_LOCAL) {
  369. $setting = !empty($mall_driver) ? Yii::$app->services->setting->get('storage_driver.' . $mall_driver) : [];
  370. if ($setting) {
  371. $setting = json_decode($setting, true);
  372. $setting['drive'] = $mall_driver;
  373. } else {
  374. $setting = $this->getPlatformStorageConfig($driver);
  375. }
  376. }
  377. return $setting;
  378. }
  379. /**
  380. * 获取平台的文件上传配置
  381. * @param $driver
  382. * @return array|mixed|void
  383. */
  384. public function getPlatformStorageConfig($driver = '')
  385. {
  386. $driver = $driver ?: PlatformSetting::conf('storage.driver');
  387. $setting = !empty($driver) ? PlatformSetting::conf('storage_driver.'.$driver) : [];
  388. $setting = !empty($setting) ? json_decode($setting,true) : [];
  389. $setting['drive'] = $driver;
  390. return $setting;
  391. }
  392. public function setLongVideoData($mall_id, $post)
  393. {
  394. try {
  395. //获取商城存储配置
  396. $config = \Yii::$app->services->attachment->getStorageConfig($mall_id);
  397. // $post['url'] = 'https://qimallos-1300393541.cos.ap-guangzhou.myqcloud.com/videos/5/2025/08/21/video_1755763652_otl4M422.mp4';
  398. $path_info = pathinfo($post['url']);
  399. // $stats = stat($url);
  400. $headers_data = get_headers($post['url'], true);
  401. $size = $headers_data['Content-Length'];
  402. $data = [
  403. 'mall_id' => $mall_id,
  404. 'drive' => $config['drive'],
  405. 'upload_type' => $post['upload_type'] ?? 'long_video',
  406. 'url' => $post['url'],
  407. 'path' => $post['url'],
  408. 'name' => $path_info['filename'],
  409. 'old_name' => $post['old_name'] ?? '',
  410. 'size' => $size,
  411. 'extension' => $path_info['extension'],
  412. 'mch_id' => $post['mch_id'] ?? 0,
  413. 'store_id' => $post['store_id'] ?? 0,
  414. 'group_id' => $post['attachment_group_id'] ?? 0,
  415. ];
  416. $res = $this->create($data);
  417. return true;
  418. // print_r();exit;
  419. } catch (\Exception $e) {
  420. throw new Exception($e->getMessage());
  421. }
  422. }
  423. }