chore: 添加静态资源文件和版本配置文件

添加大量图片、字体、音频等静态资源文件,包括用户界面图片、模板文件和安装界面素材
添加系统版本配置文件(.version)和常量定义文件(.constant)
更新供应商依赖文件,包括Symfony VarDumper组件和相关许可证文件
添加验证码配置文件(captcha.php)和.gitignore规则
This commit is contained in:
2026-03-06 20:14:23 +08:00
commit c9a98f342c
4485 changed files with 490986 additions and 0 deletions

View File

@@ -0,0 +1,85 @@
<?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\other;
use app\dao\other\AgreementDao;
use app\services\BaseServices;
use think\annotation\Inject;
use think\exception\ValidateException;
/**
* Class AgreementServices
* @package app\services\other
* @mixin AgreementDao
*/
class AgreementServices extends BaseServices
{
/**
* @var AgreementDao
*/
#[Inject]
protected AgreementDao $dao;
/**
* 获取会员协议
* @param $type
* @return array
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function getAgreementBytype($type)
{
if (!$type) return [];
return $this->dao->cacheTag()->remember(md5('agreement_' . $type), function () use ($type) {
$data = $this->dao->getOne(['type' => $type]);
if ($data) {
return $data->toArray();
} else {
return [];
}
});
}
/**
* 修改协议内容
* @param array $data
* @param $id
* @return bool|\crmeb\basic\BaseModel
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function saveAgreement(array $data, $id = 0)
{
if (!$data) return false;
if (!isset($data['type']) || !$data['type'] || $data['type'] == 0) throw new ValidateException('协议类型缺失');
if (!isset($data['title']) || !$data['title']) throw new ValidateException('请填写协议名称');
if (!isset($data['content']) || !$data['content']) throw new ValidateException('请填写协议内容');
if (!$id) {
$getOne = $this->getAgreementBytype($data['type']);
if ($getOne) throw new ValidateException('该类型协议已经存在');
}
$data['add_time'] = time();
if ($id) {
$res = $this->dao->update($id,$data);
} else {
$res = $this->dao->save($data);
}
$this->dao->cacheTag()->clear();
return !!$res;
}
}

View File

@@ -0,0 +1,104 @@
<?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\other;
use app\dao\other\CacheDao;
use app\services\BaseServices;
use think\annotation\Inject;
/**
* Class CacheServices
* @package app\services\other
* @mixin CacheDao
*/
class CacheServices extends BaseServices
{
/**
* @var CacheDao
*/
#[Inject]
protected CacheDao $dao;
/**
* 获取数据缓存
* @param string $key
* @param string|callable|int|array $default 默认值不存在则写入
* @param int $expire
* @return mixed|null
*/
public function getDbCache(string $key, $default, int $expire = 0)
{
$this->dao->delectDeOverdueDbCache();
$result = $this->dao->value(['key' => $key], 'result');
if ($result) {
return json_decode($result, true);
} else {
if ($default instanceof \Closure) {
// 获取缓存数据
$value = $default();
if ($value) {
$this->setDbCache($key, $value, $expire);
return $value;
}
} else {
$this->setDbCache($key, $default, $expire);
return $default;
}
return null;
}
}
/**
* 设置数据缓存存在则更新,没有则写入
* @param string $key
* @param $result
* @param $expire
* @return \crmeb\basic\BaseModel|mixed|\think\Model
* @throws \Exception
*/
public function setDbCache(string $key, $result, $expire = 0)
{
$this->dao->delectDeOverdueDbCache();
$addTime = $expire ? time() + $expire : 0;
if ($this->dao->count(['key' => $key])) {
return $this->dao->update($key, [
'result' => json_encode($result),
'expire_time' => $addTime,
'add_time' => time()
], 'key');
} else {
return $this->dao->save([
'key' => $key,
'result' => json_encode($result),
'expire_time' => $addTime,
'add_time' => time()
]);
}
}
/**
* 删除某个缓存
* @param string $key
*/
public function delectDbCache(string $key = '')
{
if ($key)
return $this->dao->delete($key, 'key');
else
return false;
}
}

View File

@@ -0,0 +1,62 @@
<?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\other;
use app\dao\other\CategoryDao;
use app\services\BaseServices;
use think\annotation\Inject;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
/**
* Class CategoryServices
* @package app\services\other
* @mixin CategoryDao
*/
class CategoryServices extends BaseServices
{
//积分分类
public const INTEGRAL_CATEGORY_GROUP = 5;
/**
* @var string
*/
protected string $cacheName = 'crmeb_cate';
/**
* @var CategoryDao
*/
#[Inject]
protected CategoryDao $dao;
/**
* 获取分类列表
* @param array $where
* @param array $field
* @return array
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
*/
public function getCateList(array $where = [], array $field = ['*'])
{
[$page, $limit] = $this->getPageValue();
$data = $this->dao->getCateList($where, $page, $limit, $field);
$count = $this->dao->count($where);
return compact('data', 'count');
}
}

View File

@@ -0,0 +1,199 @@
<?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\other;
use app\dao\other\CityAreaDao;
use app\services\BaseServices;
use crmeb\exceptions\AdminException;
use crmeb\services\CacheService;
use crmeb\services\FormBuilder as Form;
use think\annotation\Inject;
/**
* 城市数据(街道)
* Class CityAreaServices
* @package app\services\other
* @mixin CityAreaDao
*/
class CityAreaServices extends BaseServices
{
/**
* 城市类型
* @var string[]
*/
public array $type = [
'1' => 'province',
'2' => 'city',
'3' => 'area',
'4' => 'street'
];
/**
* @var CityAreaDao
*/
#[Inject]
protected CityAreaDao $dao;
/**
* 获取某一个城市id相关上级所有ids
* @param int $id
* @return array|int[]
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function getRelationCityIds(int $id)
{
$cityInfo = $this->dao->get($id);
$ids = [];
if ($cityInfo) {
$ids = explode('/', trim($cityInfo['path'], '/'));
}
return array_merge([$id], $ids);
}
/**
* @param int $id
* @param int $expire
* @return bool|mixed|null
*/
public function getRelationCityIdsCache(int $id, int $expire = 1800)
{
return CacheService::redisHandler('apiCity')->remember('city_ids_' . $id, function () use ($id) {
$cityInfo = $this->dao->get($id);
$ids = [];
if ($cityInfo) {
$ids = explode('/', trim($cityInfo['path'], '/'));
}
return array_merge([$id], $ids);
}, $expire);
}
/**
* 获取城市数据
* @param int $pid
* @return false|mixed|string|null
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function getCityTreeList(int $pid = 0)
{
$cityList = $this->dao->cacheStrRemember('pid_' . $pid, function () use ($pid) {
$parent_name = '中国';
if ($pid) {
$city = $this->dao->get($pid);
$parent_name = $city ? $city['name'] : '';
}
$cityList = $this->dao->getCityList(['parent_id' => $pid], 'id as value,id,name as label,parent_id as pid,level', ['children']);
foreach ($cityList as &$item) {
$item['parent_name'] = $parent_name;
if (isset($item['children']) && $item['children']) {
$item['children'] = [];
$item['loading'] = false;
$item['_loading'] = false;
} else {
unset($item['children']);
}
}
return $cityList;
});
return $cityList;
}
/**
* 添加城市数据表单
* @param int $parentId
* @return array
* @throws \FormBuilder\Exception\FormBuilderException
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function createCityForm(int $parentId)
{
$info = [];
if ($parentId) {
$info = $this->dao->get($parentId);
}
$field[] = Form::hidden('level', $info['level'] ?? 0);
$field[] = Form::hidden('parent_id', $info['id'] ?? 0);
$field[] = Form::input('parent_name', '父类名称:', $info['name'] ?? '中国')->disabled(true);
$field[] = Form::input('name', '名称:')->required('请填写城市名称');
return create_form('添加城市', $field, $this->url('/setting/city/save'));
}
/**
* 添加城市数据创建
* @param int $id
* @return array
* @throws \FormBuilder\Exception\FormBuilderException
*/
public function updateCityForm(int $id)
{
$info = $this->dao->get($id);
if (!$info) {
throw new AdminException('需改的数据不存在');
}
if ($info['parent_id']) {
$city = $this->dao->get($info['parent_id']);
$info['parent_name'] = $city['name'];
}
$info = $info->toArray();
$field[] = Form::hidden('id', $info['id']);
$field[] = Form::hidden('level', $info['level']);
$field[] = Form::hidden('parent_id', $info['parent_id']);
$field[] = Form::input('parent_name', '父类名称:', $info['parent_name'] ?? '中国')->disabled(true);
$field[] = Form::input('name', '名称:', $info['name'])->required('请填写城市名称');
return create_form('修改城市', $field, $this->url('/setting/city/save'));
}
/**
* 根据省市区名称获取对应 id
* @param $province
* @param $city
* @param $area
* @return int[]
* @throws \ReflectionException
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
* User: liusl
* DateTime: 2024/12/18 下午3:42
*/
public function getCityId($province, $city, $area)
{
$result = [
'province' => 0,
'city' => 0,
'area' => 0
];
$address = "{$province}/{$city}/$area";
$info = $this->dao->search(['address' => $address])->find();
if (!$info) {
return $result;
}
$path = explode('/', $info['path']);
return [
'province' => $path[1],
'city' => $path[2],
'area' => $info['id']
];
}
}

View File

@@ -0,0 +1,307 @@
<?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\other;
use app\dao\other\ExpressDao;
use app\services\BaseServices;
use app\services\serve\ServeServices;
use crmeb\exceptions\AdminException;
use crmeb\services\CacheService;
use crmeb\services\ExpressService;
use crmeb\services\FormBuilder as Form;
use think\annotation\Inject;
/**
* 物流数据
* Class ExpressServices
* @package app\services\other
* @mixin ExpressDao
*/
class ExpressServices extends BaseServices
{
public string $_cacheKey = "plat_express_list";
//物流查询物流公司code
public array $express_code = [
'yunda' => 'yunda',
'yundakuaiyun' => 'yunda56',
'ems' => 'EMS',
'youzhengguonei' => 'chinapost',
'huitongkuaidi' => 'HTKY',
'baishiwuliu' => 'BSKY',
'shentong' => 'STO',
'jd' => 'JD',
'zhongtong' => 'ZTO',
'zhongtongkuaiyun' => 'ZTO56',
];
/**
* @var ExpressDao
*/
#[Inject]
protected ExpressDao $dao;
/**
* 获取物流信息
* @param array $where
* @return array
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function getExpressList(array $where)
{
[$page, $limit] = $this->getPageValue();
$list = $this->dao->getExpressList($where, '*', $page, $limit);
$count = $this->dao->count($where);
return compact('list', 'count');
}
/**
* 获取API用快递列表
* @return array
*/
public function apiExpressList()
{
return $this->dao->getExpressList([], '*', 0, 0);
}
/**
* 物流表单
* @param array $formData
* @return mixed
* @throws \FormBuilder\Exception\FormBuilderException
*/
public function createExpressForm(array $formData = [])
{
if (isset($formData['partner_id']) && $formData['partner_id'] == 1) $field[] = Form::input('account', '月结账号:', $formData['account'] ?? '');
if (isset($formData['partner_key']) && $formData['partner_key'] == 1) $field[] = Form::input('key', '月结密码:', $formData['key'] ?? '');
if (isset($formData['net']) && $formData['net'] == 1) $field[] = Form::input('net_name', '取件网点:', $formData['net_name'] ?? '');
if (isset($formData['check_man']) && $formData['check_man'] == 1) $field[] = Form::input('courier_name', '承载快递员名:', $formData['courier_name'] ?? '')->required();
if (isset($formData['partner_name']) && $formData['partner_name'] == 1) $field[] = Form::input('customer_name', '客户账户名称:', $formData['customer_name'] ?? '')->required();
if (isset($formData['is_code']) && $formData['is_code'] == 1) $field[] = Form::input('code_name', '电子面单承载编号:', $formData['code_name'] ?? '')->required();
$field[] = Form::number('sort', '排序:', (int)($formData['sort'] ?? 0))->min(0);
$field[] = Form::radio('is_show', '是否启用:', $formData['is_show'] ?? 1)->options([['value' => 0, 'label' => '隐藏'], ['value' => 1, 'label' => '启用']]);
return $field;
}
/**
* 创建物流信息表单获取
* @return array
* @throws \FormBuilder\Exception\FormBuilderException
*/
public function createForm()
{
return create_form('添加物流公司', $this->createExpressForm(), $this->url('/freight/express'));
}
/**
* 修改物流信息表单获取
* @param int $id
* @return array
* @throws \FormBuilder\Exception\FormBuilderException
*/
public function updateForm(int $id)
{
$express = $this->dao->get($id);
if (!$express) {
throw new AdminException('查询数据失败,无法修改');
}
return create_form('编辑物流公司', $this->createExpressForm($express->toArray()), $this->url('/freight/express/' . $id), 'PUT');
}
/**
* 平台获取快递
* @return array|mixed
*/
public function getPlatExpress()
{
/** @var ServeServices $expressService */
$expressService = app()->make(ServeServices::class);
/** @var CacheService $cacheService */
$cacheService = app()->make(CacheService::class);
$data = [];
if ($list = $cacheService::get($this->_cacheKey)) {
$data = json_decode($list, true);
} else {
$list = $expressService->express()->express(0, 0, 1000);
if (isset($list['data'])) {
$cacheService->set($this->_cacheKey, json_encode($list['data']), 3600);
$data = $list['data'];
}
}
return $data;
}
/**
* 获取物流信息组合成新的数组返回
* @param array $where
* @return array
*/
public function express(array $where = [], string $k = 'id')
{
$list = $this->expressList($where);
$data = [];
if ($list) {
foreach ($list as $k => $v) {
$data[$k]['id'] = $v['id'];
$data[$k]['value'] = $v['name'];
$data[$k]['code'] = $v['code'];
}
}
return $data;
}
/**
* 获取物流信息组合成新的数组返回
* @param array $where
* @return array
*/
public function expressSelectForm(array $where = [])
{
$list = $this->expressList();
//$list = $this->dao->getExpress($where, 'name', 'id');
$data = [];
foreach ($list as $key => $value) {
$data[] = ['label' => $value['name'], 'value' => $value['id']];
}
return $data;
}
/**
* 获取快递列表(带缓存)
* @param array $where 查询条件
* @return array
*/
public function expressList($where = [])
{
if (empty($where)) $where = ['is_show' => 1];
return $this->dao->getExpressList($where, 'id,name,code,partner_id,partner_key,net,account,key,net_name', 0, 0);
}
/**
* 物流公司查询
* @param string $cacheName
* @param string $expressNum
* @return array|bool|mixed
*/
public function query(string $cacheName, string $expressNum)
{
$resultData = CacheService::get($cacheName, null);
if ($resultData === null || !is_array($resultData)) {
$data = [];
$cacheTime = 0;
try {
switch ((int)sys_config('logistics_type')) {
case 1://一号通
/** @var ServeServices $services */
$services = app()->make(ServeServices::class);
$result = $services->express()->query($expressNum);
if (isset($result['ischeck']) && $result['ischeck'] == 1) {
$cacheTime = 0;
} else {
$cacheTime = 1800;
}
foreach (isset($result['content']) ? $result['content'] : [] as $item) {
$data[] = ['time' => $item['time'], 'status' => $item['status']];
}
break;
case 2://阿里云
$result = ExpressService::query($expressNum);
if (is_array($result) &&
isset($result['result']) &&
isset($result['result']['deliverystatus']) &&
$result['result']['deliverystatus'] >= 3)
$cacheTime = 0;
else
$cacheTime = 1800;
$data = $result['result']['list'] ?? [];
break;
}
CacheService::set($cacheName, $data, $cacheTime);
} catch (\Throwable $e) {
}
return $data;
}
return $resultData;
}
/**
* 同步物流公司
* @return bool
*/
public function syncExpress()
{
if (CacheService::get('sync_express')) {
return true;
}
$expressList = $this->getPlatExpress();
$data = $data_all = [];
$selfExpress = $this->dao->getExpress([], 'id,code,status,account,key,net_name,courier_name,customer_name,code_name', 'id');
$codes = [];
if ($selfExpress) {
$codes = array_column($selfExpress, 'code');
$selfExpress = array_combine($codes, $selfExpress);
}
foreach ($expressList as $express) {
$data = [];
$data['partner_id'] = $express['partner_id'] ?? 0;
$data['partner_key'] = $express['partner_key'] ?? 0;
$data['net'] = $express['net'] ?? 0;
$data['check_man'] = $express['check_man'] ?? 0;
$data['partner_name'] = $express['partner_name'] ?? 0;
$data['is_code'] = $express['is_code'] ?? 0;
if (!in_array($express['code'], $codes)) {
$data['name'] = $express['name'] ?? '';
$data['code'] = $express['code'] ?? '';
$data['is_show'] = 0;
$data['status'] = 0;
if ($express['partner_id'] == 0 && $express['partner_key'] == 0 && $express['net'] == 0) {
$data['status'] = 1;
}
$data_all[] = $data;
} else {
if (isset($selfExpress[$express['code']]['id']) && $selfExpress[$express['code']]['id']) {
if (($express['partner_id'] == 1 && !$selfExpress[$express['code']]['account']) || ($express['partner_key'] == 1 && !$selfExpress[$express['code']]['key']) || ($express['net'] == 1 && !$selfExpress[$express['code']]['net_name']) || ($express['check_man'] == 1 && !$selfExpress[$express['code']]['courier_name']) || ($express['partner_name'] == 1 && !$selfExpress[$express['code']]['customer_name']) || ($express['is_code'] == 1 && !$selfExpress[$express['code']]['code_name'])) {
$data['status'] = 0;
} else {
$data['status'] = 1;
}
$this->dao->update($selfExpress[$express['code']]['id'], $data, 'id');
}
}
}
if ($data_all) {
$this->dao->saveAll($data_all);
}
CacheService::set('sync_express', 1, 3600);
return true;
}
/**
* 查询单个快递公司
* @param array $where
* @return array|\think\Model|null
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function getOneByWhere(array $where)
{
return $this->dao->getOne($where);
}
}

View File

@@ -0,0 +1,112 @@
<?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\other;
use app\services\activity\discounts\StoreDiscountsServices;
use app\services\activity\integral\StoreIntegralServices;
use app\services\activity\bargain\StoreBargainServices;
use app\services\activity\combination\StoreCombinationServices;
use app\services\activity\seckill\StoreSeckillServices;
use app\services\BaseServices;
use app\services\product\sku\StoreProductAttrValueServices;
use crmeb\services\CacheService;
/**
* Class HotDataServices
* @package app\services\product\product
*/
class HotDataServices extends BaseServices
{
/**
* 活动商品缓存库存预热
* @param int $type 商品类型 0-普通商品 1-秒杀 2-砍价 3-拼团 4-积分 5-套餐
* @return void
*/
public function hot(int $type = 0)
{
/** @var StoreProductAttrValueServices $productAttrValueServices */
$productAttrValueServices = app()->make(StoreProductAttrValueServices::class);
switch ($type) {
case 0://普通商品
break;
case 1://秒杀商品
/** @var StoreSeckillServices $seckillServices */
$seckillServices = app()->make(StoreSeckillServices::class);
$products = $seckillServices->getListByTime(0);
if ($products) {
$products = array_column($products, 'id');
$attrValue = $productAttrValueServices->getSkuArray([['product_id', 'IN', $products], ['type', '=', 1], ['quota', '>', 0]], 'unique,quota,quota_show');
if ($attrValue) {
foreach ($attrValue as $item) {
CacheService::setStock($item['unique'], (int)$item['quota'], 1);
}
}
}
break;
case 2://砍价商品
/** @var StoreBargainServices $bargainServices */
$bargainServices = app()->make(StoreBargainServices::class);
$products = $bargainServices->bargainList();
if ($products) {
$products = array_column($products, 'id');
$attrValue = $productAttrValueServices->getSkuArray([['product_id', 'IN', $products], ['type', '=', 2], ['quota', '>', 0]], 'unique,quota,quota_show');
if ($attrValue) {
foreach ($attrValue as $item) {
CacheService::setStock($item['unique'], (int)$item['quota'], 2);
}
}
}
break;
case 3://拼团商品
/** @var StoreCombinationServices $combinationServices */
$combinationServices = app()->make(StoreCombinationServices::class);
$products = $combinationServices->combinationList(['is_del' => 0, 'is_show' => 1, 'pinkIngTime' => true, 'storeProductId' => true]);
if ($products) {
$products = array_column($products, 'id');
$attrValue = $productAttrValueServices->getSkuArray([['product_id', 'IN', $products], ['type', '=', 3], ['quota', '>', 0]], 'unique,quota,quota_show');
if ($attrValue) {
foreach ($attrValue as $item) {
CacheService::setStock($item['unique'], (int)$item['quota'], 3);
}
}
}
break;
case 4://积分商品
/** @var StoreIntegralServices $integralServices */
$integralServices = app()->make(StoreIntegralServices::class);
$products = $integralServices->getColumn(['is_del' => 0], 'id');
if ($products) {
$attrValue = $productAttrValueServices->getSkuArray([['product_id', 'IN', $products], ['type', '=', 4], ['quota', '>', 0]], 'unique,quota,quota_show');
if ($attrValue) {
foreach ($attrValue as $item) {
CacheService::setStock($item['unique'], (int)$item['quota'], 4);
}
}
}
break;
case 5://套餐
/** @var StoreDiscountsServices $discountsServices */
$discountsServices = app()->make(StoreDiscountsServices::class);
$products = $discountsServices->getColumn([['is_del', '=', 0], ['is_limit', '>', 0]], 'id,limit_num');
if ($products) {
foreach ($products as $item) {
CacheService::setStock(md5($item['id']), (int)$item['limit_num'], 5);
}
}
break;
}
}
}

View File

@@ -0,0 +1,62 @@
<?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\other\Import;
use app\dao\other\Import\ImportRecordErrorDao;
use app\services\BaseServices;
use think\annotation\Inject;
/**
* 导入
* Class ImportRecordErrorServices
* @package app\services\other\import
* @mixin ImportRecordErrorDao
*/
class ImportRecordErrorServices extends BaseServices
{
/**
* @var ImportRecordErrorDao
*/
#[Inject]
protected ImportRecordErrorDao $dao;
/**
* 列表
* @param $where
* @param bool $is_limit
* @return array
* @throws \ReflectionException
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
* User: liusl
* DateTime: 2024/12/19 下午5:08
*/
public function getErrorList($where, bool $is_limit = false)
{
$page = $limit = 0;
if ($is_limit) {
[$page, $limit] = $this->getPageValue();
}
$query = $this->dao->search($where);
$count = $query->count();
$list = $query->when($page, function ($query) use ($page, $limit) {
$query->page($page, $limit);
})->select()->toArray();
foreach ($list as &$item) {
$item['original_data'] = json_decode($item['original_data'], true);
}
return compact('list', 'count');
}
}

View File

@@ -0,0 +1,522 @@
<?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\other\Import;
use app\dao\other\Import\ImportRecordDao;
use app\jobs\user\UserImportJob;
use app\jobs\user\UserSpreadJob;
use app\services\BaseServices;
use app\services\kefu\UserServices;
use app\services\other\CityAreaServices;
use app\services\user\group\UserGroupServices;
use app\services\user\label\UserLabelRelationServices;
use app\services\user\label\UserLabelServices;
use app\services\user\level\SystemUserLevelServices;
use app\services\wechat\WechatUserServices;
use think\annotation\Inject;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
use think\exception\ValidateException;
/**
* 导入
* Class ImportRecordServices
* @package app\services\other\import
* @mixin ImportRecordDao
*/
class ImportRecordServices extends BaseServices
{
const MAX_IMPORT_NUM = 10000;
const MAX_SINGLE_NUM = 50;
/**
* @var ImportRecordDao
*/
#[Inject]
protected ImportRecordDao $dao;
/**
* 列表
* @param $where
* @return array
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
* @throws \ReflectionException
* User: liusl
* DateTime: 2024/12/19 下午4:54
*/
public function getImportList(array $where)
{
[$page, $limit] = $this->getPageValue();
$query = $this->dao->search($where);
$count = $query->count();
$list = $query->page($page, $limit)->order('add_time DESC')->select()->toArray();
foreach ($list as &$item) {
$item['add_time'] = date('Y-m-d H:i:s', $item['add_time']);
}
return compact('count', 'list');
}
/**
* 删除
* @param int $id
* @return true
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
* User: liusl
* DateTime: 2024/12/19 下午4:57
*/
public function deleteImport(int $id)
{
$info = $this->dao->get($id);
if (!$info) {
throw new ValidateException('删除失败');
}
$info->is_del = 1;
$info->save();
app()->make(ImportRecordErrorServices::class)->delete(['record_id' => $id]);
return true;
}
/**
* 批量
* @param $data
* User: liusl
* DateTime: 2024/12/9 下午4:09
*/
public function batchUserImport($data, $real_name = '', $type = 'user')
{
$res = $this->dao->save([
'name' => $real_name ? substr($real_name, 0, strpos($real_name, '.')) : '导入用户数据',
'type' => $type,
'total_count' => count($data),
'add_time' => time()]);
$id = $res->id;
$errorCount = 0;
if (count($data) > self::MAX_SINGLE_NUM) {
$chunkedArray = array_chunk($data, self::MAX_SINGLE_NUM);
foreach ($chunkedArray as $key => $chunk) {
$end = !array_key_last($chunkedArray) == $key;
UserImportJob::dispatch([$id, $chunk, $end]);
}
} else {
$errorCount = $this->userSingleImport($data, $id, true);
}
return compact('errorCount', 'id');
}
/**
* 0:openid 1:unioId 2:uid 3:手机号 4:用户昵称 5:客户姓名 6:性别 7:生日 8:用户等级 9:经验值 10:付费会员有效期
* 11:客户积分 12:客户余额 13:客户标签 14:用户分组 15:用户来源 16:省 17:市 18:区 19:地址
* 单次
* User: liusl
* DateTime: 2024/12/9 下午4:10
*/
public function userSingleImport($data, $id, $end = false)
{
$userLabel = app()->make(UserLabelServices::class);
$labelCateId = $userLabel->search(['type' => 0, 'label_cate' => 0])->where('label_name', '外部导入')->value('id');
if (!$labelCateId) {
$labelCateId = $userLabel->search([])->save(['label_name' => '外部导入', 'type' => 0, 'label_cate' => 0])->id;
}
// 数据处理
list($errorData, $handleData, $labelData, $groupData) = $this->checkUser($data);
// 唯一化并过滤标签和分组数据
$_labelValues = array_unique(array_filter($labelData));
$_groupValues = array_unique(array_filter($groupData));
$res = $this->transaction(function () use ($labelCateId, $_labelValues, $_groupValues, $errorData, $id, $handleData, $end) {
// 获取标签和分组数据
$labelValues = $this->getOrCreateLabels($_labelValues, $labelCateId);
$groupValues = $this->getOrCreateGroups($_groupValues);
// 错误数据
$saveErrorData = $this->prepareErrorData($errorData, $id);
// 处理用户数据
list($labelRelationData, $wechatUserData) = $this->processHandleData($handleData, $labelValues, $groupValues);
// 批量插入其他数据
$this->bulkSave($labelRelationData, $wechatUserData, $saveErrorData, $id);
//是否最后一批数据
if ($end) {
$this->dao->update($id, ['status' => 1]);
}
return true;
});
if (!$res) {
throw new ValidateException('导入失败');
}
return count($errorData);
}
/**
* 获取或创建标签
* @param $_labelValues
* @param $labelCateId
* @return array
* @throws \ReflectionException
* User: liusl
* DateTime: 2024/12/18 下午5:51
*/
/**
* 获取或创建用户标签
* @param array $_labelValues 标签名称数组
* @param int $labelCateId 标签分类ID
* @return array
* @throws \ReflectionException
*/
private function getOrCreateLabels($_labelValues, $labelCateId)
{
$userLabel = app()->make(UserLabelServices::class);
$labelValues = $userLabel->search([])->whereIn('label_name', $_labelValues)->column('label_name', 'id');
$diffLabels = array_diff($_labelValues, $labelValues);
if ($diffLabels) {
foreach ($diffLabels as $diffLabel) {
$_id = $userLabel->search([])->insert([
'label_cate' => $labelCateId,
'label_name' => $diffLabel,
], true);
$labelValues[$_id] = $diffLabel;
}
}
return array_combine(
array_map('md5', $labelValues),
array_keys($labelValues)
);
}
/**
* 获取或创建分组
* @param $_groupValues
* @return array
* @throws \ReflectionException
* User: liusl
* DateTime: 2024/12/18 下午5:51
*/
private function getOrCreateGroups($_groupValues)
{
$userGroupServices = app()->make(UserGroupServices::class);
$groupValues = $userGroupServices->search([])->whereIn('group_name', $_groupValues)->column('group_name', 'id');
$diffGroups = array_diff($_groupValues, $groupValues);
if ($diffGroups) {
foreach ($diffGroups as $diffGroup) {
$_id = $userGroupServices->search([])->insert(['group_name' => $diffGroup], true);
$groupValues[$_id] = $diffGroup;
}
}
return array_combine(
array_map('md5', $groupValues),
array_keys($groupValues)
);
}
/**
* 错误记录
* @param $errorData
* @param $id
* @return array
* User: liusl
* DateTime: 2024/12/18 下午5:51
*/
private function prepareErrorData($errorData, $id)
{
$saveErrorData = [];
foreach ($errorData as $error) {
$fail_msg = $error['fail_msg'] ?? '';
unset($error['fail_msg']);
$saveErrorData[] = [
'record_id' => $id,
'original_data' => json_encode($error),
'fail_msg' => $fail_msg,
];
}
return $saveErrorData;
}
/**
* 处理用户数据
* @param $handleData
* @param $labelValues
* @param $groupValues
* @return array[]
* User: liusl
* DateTime: 2024/12/18 下午5:50
*/
private function processHandleData($handleData, $labelValues, $groupValues)
{
$userServices = app()->make(UserServices::class);
$labelRelationData = [];
$wechatUserData = [];
foreach ($handleData as $handle) {
$uid = $handle['uid'];
$openid = $handle['openid'];
$unionid = $handle['unionid'];
$label = $handle['label'];
unset($handle['label'], $handle['uid'], $handle['openid'], $handle['unionid']);
if ($uid) {
$handle['uid'] = $uid;
}
$handle['group'] = $handle['group'] ? $groupValues[md5($handle['group'])] ?? 0 : 0;
$handle['account'] = $handle['phone'] ?: 'wx' . rand(1, 9999) . time();
$handle['pwd'] = md5('123456');
$handle['avatar'] = sys_config('h5_avatar');
$handle['user_type'] = $handle['login_type'];
$handle['add_time'] = time();
$uid = $userServices->save($handle)->uid;
// 处理标签关系
if ($label) {
foreach ($label as $l) {
$labelRelationData[] = [
'uid' => $uid,
'label_id' => $labelValues[md5($l)] ?? 0,
];
}
}
// 处理微信用户
if (($openid || $unionid) && in_array($handle['login_type'], ['routine', 'app', 'wechat'])) {
$wechatUserData[] = [
'uid' => $uid,
'openid' => $openid,
'unionid' => $unionid,
'nickname' => $handle['nickname'],
'sex' => $handle['sex'],
'user_type' => $handle['login_type']
];
}
event('user.register', [$userServices->get($uid), true, 0]);
}
return [$labelRelationData, $wechatUserData];
}
/**
* 批量保存数据
* @param $labelRelationData
* @param $wechatUserData
* @param $saveErrorData
* @param $id
* @return void
* @throws DbException
* @throws \ReflectionException
* User: liusl
* DateTime: 2024/12/18 下午5:50
*/
private function bulkSave($labelRelationData, $wechatUserData, $saveErrorData, $id)
{
if (count($labelRelationData) > 0) {
app()->make(UserLabelRelationServices::class)->saveAll($labelRelationData);
}
if (count($wechatUserData) > 0) {
app()->make(WechatUserServices::class)->saveAll($wechatUserData);
}
if (count($saveErrorData) > 0) {
app()->make(ImportRecordErrorServices::class)->saveAll($saveErrorData);
$this->dao->search([])->where('id', $id)->setInc('fail_count', count($saveErrorData));
}
}
/**
* 检查用户数据并处理
* @param $data
* @return array
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
* @throws \ReflectionException
* User: liusl
* DateTime: 2024/12/18 下午4:10
*/
public function checkUser($data)
{
$userServices = app()->make(UserServices::class);
$wechatUserServices = app()->make(WechatUserServices::class);
$cityAreaServices = app()->make(CityAreaServices::class);
// 初始化错误数据、处理后的数据、标签数据和分组数据数组
$errorData = [];
$handleData = [];
$labelData = [];
$groupData = [];
// 获取微信用户的openid和unionid信息
$openIds = $wechatUserServices->search([])->whereIn('openid', array_filter(array_column($data, 'openid')))->column('uid', 'openid');
$unionIds = $wechatUserServices->search([])->whereIn('unionid', array_filter(array_column($data, 'unionid')))->column('uid', 'unionid');
// 获取用户的uid和手机号信息
$userIds = $userServices->search([])->withTrashed()->whereIn('uid', array_filter(array_column($data, 'uid')))->column('uid', 'uid');
$phoneIds = $userServices->search([])->whereIn('phone', array_filter(array_column($data, 'phone')))->column('uid', 'phone');
//等级
$levels = app()->make(SystemUserLevelServices::class)->getColumn(['is_del' => 0, 'is_show' => 1], 'exp_num,grade', 'id');
// 遍历输入的数据数组
foreach ($data as $handle) {
// 检查是否所有关键用户信息都未提供如果未提供,则标记为错误
if (!$handle['unionid'] && !$handle['uid'] && !$handle['phone'] && !$handle['openid']) {
$handle['fail_msg'] = 'openid, unionid, uid, 手机号请填写至少一个用户信息';
$errorData[] = $handle;
continue;
}
if ($handle['openid'] && isset($openIds[$handle['openid']])) {
$handle['fail_msg'] = 'openid: ' . $handle['openid'] . ' 已存在';
$errorData[] = $handle;
continue;
}
if ($handle['unionid'] && isset($unionIds[$handle['unionid']])) {
$handle['fail_msg'] = 'unionid: ' . $handle['unionid'] . ' 已存在';
$errorData[] = $handle;
continue;
}
if ($handle['uid'] && isset($userIds[$handle['uid']])) {
$handle['fail_msg'] = 'uid: ' . $handle['uid'] . ' 已存在';
$errorData[] = $handle;
continue;
}
if ($handle['phone']) {
if (!preg_match('/^1[3-9]\d{9}$/', $handle['phone'])) {
$handle['fail_msg'] = '手机号格式错误';
$errorData[] = $handle;
continue;
}
if (isset($phoneIds[$handle['phone']])) {
$handle['fail_msg'] = '手机号: ' . $handle['phone'] . ' 已存在';
$errorData[] = $handle;
continue;
}
}
//真实姓名
if ($handle['real_name'] && mb_strlen($handle['real_name'], 'UTF-8') > 25) {
$handle['fail_msg'] = '真实姓名不能超过25个字符';
$errorData[] = $handle;
continue;
}
// 根据性别名称转换为对应的数字代码
$handle['sex'] = match ($handle['sex']) {
'男' => 1,
'女' => 2,
default => 0,
};
if ($handle['birthday']) {
// $handle['birthday'] = $this->excelDate($handle['birthday']);
// $handle['birthday'] = strtotime($handle['birthday']);
}
if ($handle['overdue_time']) {
$handle['overdue_time'] = $this->excelDate($handle['overdue_time']);
$handle['overdue_time'] = strtotime($handle['overdue_time']);
$handle['is_money_level'] = 1;
}
if ($handle['label']) {
$handle['label'] = array_unique(array_filter(explode(',', $handle['label'])));
$labelData = array_merge($labelData, $handle['label']);
}
if ($handle['group']) {
$groupData[] = $handle['group'];
}
//经验
if ($handle['level'] || $handle['exp']) {
$level = in_array($handle['level'], array_column($levels, 'grade')) ? $handle['level'] : 0;
$level_num = 0;
foreach ($levels as $var) {
if ($handle['exp'] >= $var['exp_num']) {
$level_num = $var['grade'];
}
}
foreach ($levels as $key => $var) {
if ($level > $level_num && $var['grade'] == $level) {
$handle['exp'] = $var['exp_num'];
$handle['level'] = $key;
break;
}
if ($level <= $level_num && $var['grade'] == $level_num) {
$handle['level'] = $key;
break;
}else{
$handle['level'] = $handle['exp'] = 0;
}
}
}
if ($handle['province'] && $handle['city'] && $handle['area']) {
$handle['provincials'] ="{$handle['province']}/{$handle['city']}/{$handle['area']}";
$province = $cityAreaServices->getCityId($handle['province'], $handle['city'], $handle['area']);
$handle['province'] = $province['province'];
$handle['city'] = $province['city'];
$handle['area'] = $province['area'];
} else {
$handle['province'] = 0;
$handle['city'] = 0;
$handle['area'] = 0;
}
$handle['login_type'] = match ($handle['login_type']) {
'微信小程序' => 'routine',
'公众号' => 'wechat',
'H5' => 'h5',
'PC' => 'pc',
'APP' => 'app',
default => 'import',
};
$handleData[] = $handle;
}
return [$errorData, $handleData, $labelData, $groupData];
}
/**
* 将Excel日期序列号转换为标准日期格式
* @param int $date Excel日期序列号
* @return string Y-m-d格式日期
*/
public function excelDate($date)
{
//Excel 1900日期系统起始日期
$excelStartDate = strtotime('1900-01-01');
// 因为 Excel 错误地包含了 1900-02-29,日期序列号应该减去 1
$date = $date - 2;
$unixTimestamp = strtotime("+$date days", $excelStartDate);
return date('Y-m-d', $unixTimestamp);
}
}

View File

@@ -0,0 +1,397 @@
<?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\other;
use app\services\BaseServices;
use app\dao\other\QrcodeDao;
use app\services\product\product\CopyTaobaoServices;
use app\services\system\attachment\SystemAttachmentServices;
use crmeb\exceptions\AdminException;
use crmeb\services\UploadService;
use crmeb\services\UtilService;
use crmeb\services\wechat\MiniProgram;
use crmeb\services\wechat\OfficialAccount;
use GuzzleHttp\Psr7\Utils;
use think\annotation\Inject;
use think\exception\ValidateException;
/**
*
* Class QrcodeServices
* @package app\services\other
* @mixin QrcodeDao
*/
class QrcodeServices extends BaseServices
{
/**
* @var QrcodeDao
*/
#[Inject]
protected QrcodeDao $dao;
/**
* 获取临时二维码
* @param $type
* @param $id
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function getTemporaryQrcode($type, $id)
{
$where['third_id'] = $id;
$where['third_type'] = $type;
$res = $this->dao->getOne($where);
if (!$res) {
$this->createTemporaryQrcode($id, $type);
$res = $this->getTemporaryQrcode($type, $id);
} else if (empty($res['expire_seconds']) || $res['expire_seconds'] < time()) {
$this->createTemporaryQrcode($id, $type, $res['id']);
$res = $this->getTemporaryQrcode($type, $id);
}
if (!$res['ticket']) throw new AdminException('临时二维码获取错误');
return $res;
}
/**
* 临时二维码生成
* @param $id
* @param $type
* @param string $qrcode_id
*/
public function createTemporaryQrcode($id, $type, $qrcode_id = '')
{
$qrcode = OfficialAccount::instance()->qrCode();
$data = $qrcode->temporary($id, 30 * 24 * 3600);
$data['qrcode_url'] = $data['url'];
$data['expire_seconds'] = $data['expire_seconds'] + time();
$data['url'] = $qrcode->url($data['ticket']);
$data['status'] = 1;
$data['third_id'] = $id;
$data['third_type'] = $type;
if ($data['url']) {
$siteUrl = sys_config('site_url');
$uploadValue = app()->make(CopyTaobaoServices::class)->downloadImage($data['url'], $data['ticket'] . '.jpg');
if (is_array($uploadValue)) {
$data['url'] = $uploadValue['image_type'] == 1 ? $siteUrl . $uploadValue['path'] : $uploadValue['path'];
}
}
if ($qrcode_id) {
$this->dao->update($qrcode_id, $data);
} else {
$data['add_time'] = time();
$this->dao->save($data);
}
}
/**
* 获取永久二维码
* @param $type
* @param $id
* @return array|mixed|\think\Model
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function getForeverQrcode($type, $id)
{
$where['third_id'] = $id;
$where['third_type'] = $type;
$res = $this->dao->getOne($where);
if (!$res) {
$this->createForeverQrcode($id, $type);
$res = $this->getForeverQrcode($type, $id);
}
if (!$res['ticket']) throw new AdminException('永久二维码获取错误');
return $res;
}
/**
* 永久二维码生成
* @param $id
* @param $type
*/
public function createForeverQrcode($id, $type)
{
$qrcode = OfficialAccount::instance()->qrCode();
$data = $qrcode->forever($id);
if (isset($data['errcode']) && $data['errcode'] == 40001) {
OfficialAccount::instance()->application()->getAccessToken()->refresh();
$qrcode = OfficialAccount::instance()->qrCode();
$data = $qrcode->forever($id);
}
$data['qrcode_url'] = $data['url'];
$data['url'] = $qrcode->url($data['ticket']);
if ($data['url']) {
$siteUrl = sys_config('site_url');
$uploadValue = app()->make(CopyTaobaoServices::class)->downloadImage($data['url'], $data['ticket'] . '.jpg');
if (is_array($uploadValue)) {
$data['url'] = $uploadValue['image_type'] == 1 ? $siteUrl . $uploadValue['path'] : $uploadValue['path'];
}
}
$data['expire_seconds'] = 0;
$data['status'] = 1;
$data['third_id'] = $id;
$data['third_type'] = $type;
$data['add_time'] = time();
$this->dao->save($data);
}
/**
* 获取二维码完整路径,不存在则自动生成
* @param string $name
* @param string $link
* @param bool $force
* @return bool|mixed|string
*/
public function getWechatQrcodePath(string $name, string $link, bool $force = false, bool $isSaveAttach = true)
{
/** @var SystemAttachmentServices $systemAttachmentService */
$systemAttachmentService = app()->make(SystemAttachmentServices::class);
try {
if (!$isSaveAttach) {
$imageInfo = "";
} else {
$imageInfo = $systemAttachmentService->getOne(['name' => $name]);
}
$siteUrl = sys_config('site_url');
if (!$imageInfo) {
$codeUrl = UtilService::setHttpType($siteUrl . $link, request()->isSsl() ? 0 : 1);//二维码链接
$imageInfo = UtilService::getQRCodePath($codeUrl, $name);
if (is_string($imageInfo) && $force)
return false;
if (is_array($imageInfo)) {
if ($isSaveAttach) {
$systemAttachmentService->save([
'name' => $imageInfo['name'],
'att_dir' => $imageInfo['dir'],
'satt_dir' => $imageInfo['thumb_path'],
'att_size' => $imageInfo['size'],
'att_type' => $imageInfo['type'],
'image_type' => $imageInfo['image_type'],
'module_type' => 2,
'time' => time(),
'pid' => 1,
'type' => 1
]);
}
$url = $imageInfo['dir'];
} else {
$url = '';
$imageInfo = ['image_type' => 0];
}
} else $url = $imageInfo['att_dir'];
if ($imageInfo['image_type'] == 1 && $url) $url = $siteUrl . $url;
return $url;
} catch (\Throwable $e) {
if ($force)
return false;
else
return '';
}
}
/**
* 获取短链
* @param int $id
* @param string $uid
* @param int $type
* @return false|mixed|string
* User: liusl
* DateTime: 2024/11/23 下午3:10
*/
public function getRoutineShortLink(int $id = 0, string $uid = '', int $type = 0)
{
try {
$query = http_build_query(['id' => $id, 'spid' => $uid]);
$page = match ($type) {
-1 => '/pages/index/index',
0 => '/pages/goods_details/index',
default => '',
};
$res = MiniProgram::generateUrlLink($page, $query);
return $res['url_link'] ?? '';
} catch (\Throwable $e) {
return false;
}
}
/**
* 获取小程序分享二维码
* @param int $id
* @param int $uid
* @param int $type
* @param string $namePath
* @param bool $isSaveAttach
* @param string $savePath
* @return false|mixed|string
*/
public function getRoutineQrcodePath(int $id, int $uid, int $type = 0, string $namePath = '', bool $isSaveAttach = true, string $savePath = 'qrcode/routine')
{
$data = 'id=' . $id . '&spid=' . $uid;
$page = match ($type) {
-1 => 'pages/index/index',
0 => 'pages/goods_details/index',//普通商品
1, 3, 4, 6, 7 => 'pages/activity/goods_details/index',//1秒杀3拼团4积分7新人专享
2 => 'pages/activity/goods_bargain_details/index',//砍价
31 => 'pages/activity/goods_combination_status/index',//拼团状态
90, 91 => 'pages/admin/order_cancellation/index',//核销页面
99 => 'pages/index/index',//首页
103 => 'pages/annex/offline_pay/index',//线下支付
104 => 'pages/annex/vip_active/index',//兑换激活svip
105 => 'pages/annex/vip_paid/index',//付费会员中心
106 => 'pages/annex/special/index',//专题页面
107 => 'pages/goods/order_pay/index',//
110 => 'pages/users/user_spread_user/index',
111 => 'pages/goods/receive_gift/index',//领取赠品
default => '',
};
if (in_array($type, [1, 3, 4, 6, 7])) {
$data .= '&type=' . $type;
}
if (in_array($type, [90, 91])) {
$data = 'auth=3&code=' . $id;
}
if (!$page || !$namePath) {
return false;
}
try {
/** @var SystemAttachmentServices $systemAttachmentService */
$systemAttachmentService = app()->make(SystemAttachmentServices::class);
if (!$isSaveAttach) {
$imageInfo = "";
} else {
$imageInfo = $systemAttachmentService->getOne(['name' => $savePath . '/' . $namePath]);
//检测远程文件是否存在
if (isset($imageInfo['att_dir']) && strstr($imageInfo['att_dir'], 'http') !== false && curl_file_exist($imageInfo['att_dir']) === false) {
$imageInfo = '';
$systemAttachmentService->delete(['name' => $savePath . '/' . $namePath]);
}
}
$siteUrl = sys_config('site_url');
$imageInfo = '';
if (!$imageInfo) {
$res = MiniProgram::appCodeUnlimit($data, $page, 280);
if (!$res) return false;
$uploadType = (int)sys_config('upload_type', 1);
$upload = UploadService::init($uploadType);
$res = (string)Utils::streamFor($res);
$res = $upload->to($savePath)->validate()->stream($res, $namePath);
if ($res === false) {
return false;
}
$imageInfo = $upload->getUploadInfo();
$imageInfo['image_type'] = $uploadType;
if ($imageInfo['image_type'] == 1) $remoteImage = UtilService::remoteImage($siteUrl . $imageInfo['dir']);
else $remoteImage = UtilService::remoteImage($imageInfo['dir']);
if (!$remoteImage['status']) return false;
if ($isSaveAttach) {
$systemAttachmentService->save([
'name' => $imageInfo['name'],
'att_dir' => $imageInfo['dir'],
'satt_dir' => $imageInfo['thumb_path'],
'att_size' => $imageInfo['size'],
'att_type' => $imageInfo['type'],
'image_type' => $imageInfo['image_type'],
'module_type' => 2,
'time' => time(),
'pid' => 1,
'type' => 2
]);
}
$url = $imageInfo['dir'];
} else $url = $imageInfo['att_dir'];
if ($imageInfo['image_type'] == 1) $url = $siteUrl . $url;
return $url;
} catch (\Throwable $e) {
return false;
}
}
/**
* 添加二维码 存在直接获取
* @param $thirdId
* @param $thirdType
* @param $page
* @param $qrCodeLink
* @return array|object|\think\Model
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function qrCodeForever($thirdId = 0, $thirdType = 'spread', $page = '', $qrCodeLink = '')
{
$qrcode = $this->dao->getOne(['third_id' => $thirdId, 'third_type' => $thirdType]);
if ($qrcode) {
return $qrcode;
}
return $this->setQrcodeForever($thirdId, $thirdType, $page, $qrCodeLink);
}
/**
* 检测是否存在
* @param int $thirdId
* @param string $thirdType
* @return int
*/
public function qrCodeExist($thirdId = 0, $thirdType = 'spread')
{
return !!$this->dao->getCount(['third_id' => $thirdId, 'third_type' => $thirdType]);
}
/**
* 添加二维码记录
* @param int $thirdId
* @param string $thirdType
* @param string $page
* @param string $qrCodeLink
* @return object
*/
public function setQrcodeForever($thirdId = 0, $thirdType = 'spread', $page = '', $qrCodeLink = '')
{
$data['third_type'] = $thirdType;
$data['third_id'] = $thirdId;
$data['status'] = 1;
$data['add_time'] = time();
$data['page'] = $page;
$data['url_time'] = '';
$data['qrcode_url'] = $qrCodeLink;
if (!$re = $this->dao->save($data)) {
throw new ValidateException('生成失败');
}
return $re;
}
/**
* 修改二维码地址
* @param int $id
* @param array $data
* @return bool
*/
public function setQrcodeFind($id = 0, $data = array())
{
if (!$id) return false;
if (!$this->dao->get((int)$id)) {
throw new ValidateException('数据不存在');
}
if (!$re = $this->dao->update($id, $data, 'id')) {
throw new ValidateException('修改数据失败');
}
return $re;
}
}

View File

@@ -0,0 +1,148 @@
<?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\other;
use app\dao\other\SystemCityDao;
use app\services\BaseServices;
use crmeb\exceptions\AdminException;
use crmeb\services\CacheService;
use crmeb\services\FormBuilder as Form;
use think\annotation\Inject;
/**
* 城市数据
* Class SystemCityServices
* @package app\services\other
* @mixin SystemCityDao
*/
class SystemCityServices extends BaseServices
{
/**
* 城市数据
* @var string
*/
public string $tree_city_key = 'tree_city_list';
/**
* @var SystemCityDao
*/
#[Inject]
protected SystemCityDao $dao;
/**
* 获取城市数据
* @param array $where
* @return array
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function getCityList(array $where)
{
return CacheService::get($this->tree_city_key, function () {
return $this->getSonCityList();
}, 86400);
}
/**
* tree形城市列表
* @param int $pid
* @param string $parent_name
* @return array
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function getSonCityList($pid = 0, $parent_name = '中国')
{
$list = $this->dao->getCityList(['parent_id' => $pid], 'id,city_id,level,name');
$arr = [];
if ($list) {
foreach ($list as $item) {
$item['parent_id'] = $parent_name;
$item['children'] = $this->getSonCityList($item['city_id'], $item['name']);
$arr [] = $item;
}
}
return $arr;
}
/**
* 添加城市数据表单
* @param int $parentId
* @return array
* @throws \FormBuilder\Exception\FormBuilderException
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function createCityForm(int $parentId)
{
if ($parentId) {
$info = $this->dao->getOne(['city_id' => $parentId], 'level,city_id,name');
} else {
$info = ["level" => 0, "city_id" => 0, "name" => '中国'];
}
$field[] = Form::hidden('level', $info['level']);
$field[] = Form::hidden('parent_id', $info['city_id']);
$field[] = Form::input('parent_name', '上级名称', $info['name'])->readonly(true);
$field[] = Form::input('name', '名称')->required('请填写城市名称');
return create_form('添加城市', $field, $this->url('/setting/city/save'));
}
/**
* 添加城市数据创建
* @param int $id
* @return array
* @throws \FormBuilder\Exception\FormBuilderException
*/
public function updateCityForm(int $id)
{
$info = $this->dao->get($id);
if (!$info) {
throw new AdminException('需改的数据不存在');
}
$info = $info->toArray();
$info['parent_name'] = $this->dao->value(['city_id' => $info['parent_id']], 'name') ?: '中国';
$field[] = Form::hidden('id', $info['id']);
$field[] = Form::hidden('level', $info['level']);
$field[] = Form::hidden('parent_id', $info['parent_id']);
$field[] = Form::input('parent_name', '上级名称', $info['parent_name'])->readonly(true);
$field[] = Form::input('name', '名称', $info['name'])->required('请填写城市名称');
$field[] = Form::input('merger_name', '合并名称', $info['merger_name'])->placeholder('格式:陕西,西安,雁塔')->required('请填写合并名称');
return create_form('修改城市', $field, $this->url('/setting/city/save'));
}
/**
* 获取城市数据
* @return mixed
*/
public function cityList()
{
return CacheService::get('CITY_LIST', function () {
$allCity = $this->dao->getCityList([], 'city_id as v,name as n,parent_id');
return sort_city_tier($allCity, 0);
}, 0);
}
/**
* @return bool|mixed|null
*/
public function getCityTreeList()
{
return CacheService::get('CITY_TREE_LIST', function () {
return get_tree_children($this->dao->getCityList(['is_show' => 1], 'city_id as value,name as label,parent_id as pid'), 'children', 'value');
});
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,224 @@
<?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\other\queue;
use app\dao\other\queue\QueueAuxiliaryDao;
use app\services\BaseServices;
use app\services\order\StoreOrderServices;
use think\annotation\Inject;
use think\exception\ValidateException;
/**
* 队列辅助
* Class QueueAuxiliaryServices
* @package app\services\other\queue
* @mixin QueueAuxiliaryDao
*/
class QueueAuxiliaryServices extends BaseServices
{
public static array $_status = [
0 => "未执行",
1 => "成功",
2 => "失败",
3 => '删除'
];
/**
* @var QueueAuxiliaryDao
*/
#[Inject]
protected QueueAuxiliaryDao $dao;
/**
* 添加队列数据
* @param $queueId
* @param $ids
* @param $data
* @param $type
* @param $rediskey
* @return bool
*/
public function saveQueueOrderData($queueId, $ids, $data, $type, $rediskey)
{
if (!$ids) {
throw new ValidateException('缺少数据');
}
$data_all = [];
$save = ['binding_id' => $queueId, 'type' => $rediskey, 'status' => 0, 'add_time' => time()];
if ($type == 7) {//批量发货读取数据表格
foreach ($data as $k => $v) {
if ($v[0] && $v[1] && $v[2] && $v[3] && $v[4] && in_array($v[0], $ids)) {
$save['relation_id'] = $v[0];
$save['other'] = json_encode(['id' => $v[0], 'order_id' => $v[1], 'delivery_name' => $v[2], 'delivery_code' => $v[3], 'delivery_id' => $v[4], 'delivery_status' => 0, 'wx_message' => 0, 'phone_message' => 0, 'error_info' => ""]);
$data_all[] = $save;
}
}
} else {
foreach ($ids as $k => $v) {
$save['relation_id'] = $v;
$save['other'] = json_encode(['id' => $v, 'delivery_status' => 0, 'wx_message' => 0, 'phone_message' => 0, 'error_info' => ""]);
$data_all[] = $save;
}
}
if ($data_all) {
if (!$this->dao->saveAll($data_all)) {
throw new ValidateException('添加队列数据失败');
}
}
return true;
}
/**
* 获取发货缓存数据列表
* @param array $where
* @return array
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function getOrderExpreList(array $where, int $limit = 0)
{
if (!$where) throw new ValidateException("获取发货缓存数据条件缺失");
if ($limit) {
[$page] = $this->getPageValue();
} else {
[$page, $limit] = $this->getPageValue();
}
return $this->dao->getOrderExpreList($where, $page, $limit);
}
/**
* 修改订单缓存数据
* @param array $where
* @param array $data
* @return mixed
*/
public function updateOrderStatus(array $where, array $data)
{
if (!$where) throw new ValidateException("数据条件缺失");
return $this->dao->update($where, $data);
}
/**
* 根据条件统计缓存数据
* @param array $where
* @return int
*/
public function getCountOrder(array $where)
{
return $this->dao->count($where);
}
/**
* 查看订单缓存数据的各种状态
* @param $orderId
* @param $queueId
* @return bool|mixed
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function getOrderOtherSataus($orderId, $queueId, $cacheType)
{
if (!$orderId || !$queueId) return false;
$where['relation_id'] = $orderId;
$where['binding_id'] = $queueId;
$where['type'] = $cacheType;
$where['status'] = 1;
$getOne = $this->dao->getOrderCacheOne($where);
if ($getOne) return true;
return false;
}
/**
* 获取发货记录
* @param array $where
* @return array
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function deliveryLogList(array $where = [])
{
[$page, $limit] = $this->getPageValue();
$list = $this->dao->deliveryLogList($where, $page, $limit);
$list = $this->doBatchDeliveryData($list);
$count = $this->dao->count($where);
return compact('list', 'count');
}
/**
* 下载发货记录
* @param array $where
* @return array
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function getExportData(array $where, int $limit = 0)
{
if (!$where) throw new ValidateException("数据条件缺失");
$list = $this->getOrderExpreList($where, $limit);
$list = $this->doBatchDeliveryData($list);
return $list;
}
/**
* 批量发货记录数据
* @param $list
* @return mixed
*/
public function doBatchDeliveryData($list)
{
if ($list) {
/** @var StoreOrderServices $storeOrderService */
$storeOrderService = app()->make(StoreOrderServices::class);
/** @var QueueServices $queueService */
$queueService = app()->make(QueueServices::class);
$type = array_flip($queueService->queue_redis_key);
foreach ($list as &$v) {
$v['add_time'] = date('Y-m-d H:i:s', $v['add_time']);
$v['status_cn'] = self::$_status[$v['status']];
$v['error'] = $v['status'] == 1 ? '无' : '队列异常';
$orderInfo = $storeOrderService->getOne(['id' => $v['relation_id']]);
if (!$orderInfo) {
continue;
}
$v['order_id'] = $orderInfo['order_id'];
if (in_array($type[$v['type']], [7, 8, 9])) {
$v['delivery_name'] = $orderInfo ? ($orderInfo['delivery_type'] == 'fictitious' ? '虚拟发货' : $orderInfo['delivery_name']) : "";
$v['delivery_id'] = $orderInfo ? ($orderInfo['delivery_type'] == 'fictitious' ? '无' : $orderInfo['delivery_id']) : "";
}
if ($type[$v['type']] == 10) {
$v['fictitious_content'] = $orderInfo ? $orderInfo['fictitious_content'] : "";
}
}
}
return $list;
}
/**
* 获取某个队列的数据缓存
* @param $bindingId
* @param $type
* @return array
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function getCacheOidList($bindingId, $type)
{
return $this->dao->getCacheOidList($bindingId, $type);
}
}

View File

@@ -0,0 +1,970 @@
<?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\other\queue;
use app\controller\admin\v1\system\SystemClearData;
use app\dao\other\queue\QueueDao;
use app\jobs\BatchHandleJob;
use app\services\BaseServices;
use app\services\activity\coupon\StoreCouponIssueServices;
use app\services\order\StoreCartServices;
use app\services\order\StoreOrderDeliveryServices;
use app\services\order\StoreOrderServices;
use app\services\product\category\StoreProductCategoryServices;
use app\services\product\product\StoreProductRelationServices;
use app\services\product\product\StoreProductServices;
use app\services\product\sku\StoreProductRuleServices;
use app\services\system\SystemClearServices;
use app\services\user\group\UserGroupServices;
use app\services\user\label\UserLabelRelationServices;
use app\services\user\label\UserLabelServices;
use app\services\user\UserServices;
use crmeb\exceptions\AdminException;
use crmeb\services\CacheService;
use think\annotation\Inject;
use think\exception\ValidateException;
use think\facade\Log;
/**
* 队列
* Class QueueServices
* @package app\services\other\queue
* @mixin QueueDao
*/
class QueueServices extends BaseServices
{
/**
* 任务类型名称
* @var string[]
*/
public array $queue_type_name = [
1 => "批量发放用户优惠券",
2 => "批量设置用户分组",
3 => "批量设置用户标签",
4 => "批量下架商品",
5 => "批量删除商品规格",
6 => "批量删除订单",
7 => "批量手动发货",
8 => "批量打印电子面单",
9 => "批量配送",
10 => "批量虚拟发货",
11 => "批量加入回收站",
12 => "批量删除商品",
];
/**
* 任务redis缓存key
* @var string[]
*/
public array $queue_redis_key = [
1 => "DrivingSendCoupon-ADMIN",
2 => "DrivingUserGroup-ADMIN",
3 => "DrivingUserLabel-ADMIN",
4 => "DrivingProductUnshow-ADMIN",
5 => "DrivingProductRule-ADMIN",
6 => "DrivingOrderDel-ADMIN",
7 => 3,
8 => 4,
9 => 5,
10 => 6,
11 => "ProductRecycle-ADMIN",
12 => "ProductDeleteBatch-ADMIN",
];
/**
* 状态
* @var string[]
*/
protected array $status_name = [
0 => '未处理',
1 => '正在处理',
2 => '完成',
3 => '失败'
];
/**
* @var QueueDao
*/
#[Inject]
protected QueueDao $dao;
/**
* 获取任务列表
* @param array $where
*/
public function getList(array $where = [])
{
[$page, $limit] = $this->getPageValue();
$list = $this->dao->getList($where, $page, $limit);
if ($list) {
foreach ($list as &$v) {
$v['finish_time'] = $v['finish_time'] ? date('Y-m-d H:i:s', $v['finish_time']) : "";
$v['first_time'] = $v['first_time'] ? date('Y-m-d H:i:s', $v['first_time']) : "";
$v['again_time'] = $v['again_time'] ? date('Y-m-d H:i:s', $v['again_time']) : "";
$v['status_cn'] = $this->status_name[$v['status']] ?? '';
$v['is_show_log'] = false;
if (in_array($v['type'], [7, 8, 9, 10])) {
$v['is_show_log'] = true;
$v['is_error_button'] = $v['status'] == 2;
}
$v['type_cn'] = $this->queue_type_name[$v['type']] ?? '';
$v['cache_type'] = $this->queue_redis_key[$v['type']] ?? 0;
$v['success_num'] = bcsub($v['total_num'], $v['surplus_num'], 0);
//是否显示停止按钮
$v['is_stop_button'] = $v['status'] == 1;
$v['add_time'] = date('Y-m-d H:i:s', $v['add_time']);
}
}
$count = $this->dao->count($where);
return compact('list', 'count');
}
/**
* 将要执行的任务数据存入表中
* @param array $where
* @param string $field
* @param array $data
* @param int $type
* @return mixed
*/
public function setQueueData(array $where = [], $field = "*", array $data = [], int $type = 1, $other = false)
{
if (!$type) throw new ValidateException('缺少执行任务类型');
$queue_redis_keys = $this->queue_redis_key;
$redisKey = $queue_redis_keys[$type] ?? '';
$queue_type_name = $this->queue_type_name;
$queueName = $queue_type_name[$type] ?? '';
if (!$redisKey || !$queueName) {
throw new ValidateException('缺少队列缓存KEY,或者不存在此类型队列');
}
//检查同类型其他任务
$this->checkTypeQueue($redisKey);
$source = 'admin';
if (in_array($type, [1, 2, 3, 4, 5, 6, 11, 12])) {
$queueDataNum = $this->setRedisData($redisKey, $type, $data, $where, $field);
if (!$queueDataNum) {
throw new ValidateException('需要执行的批量数据为空');
}
if (!$id = $this->dao->addQueueList($queueName, $queueDataNum, $type, $redisKey, $source)) {
throw new ValidateException('添加队列失败');
}
} else {
if ($type == 7) {
$ids = array_column($data, 0);
} else {
$ids = $data;
}
/** @var StoreOrderServices $orderService */
$orderService = app()->make(StoreOrderServices::class);
$oids = $orderService->getOrderDumpData($where, $ids, $field);
$order_ids = [];
if ($oids) {
//过滤拼团未完成订单
foreach ($oids as $order) {
if (isset($order['pinkStatus']) && $order['pinkStatus'] != 2) {
continue;
}
$order_ids[] = $order['id'];
}
}
if (!$order_ids) {
throw new ValidateException('暂无需要发货订单');
}
if (!$id = $this->dao->addQueueList($queueName, count($ids), $type, $redisKey, $source)) {
throw new ValidateException('添加队列失败');
}
/** @var QueueAuxiliaryServices $auxiliaryService */
$auxiliaryService = app()->make(QueueAuxiliaryServices::class);
$auxiliaryService->saveQueueOrderData($id, $order_ids, $data, $type, $redisKey);
}
return $id;
}
/**
* 队列数据放入redis集合
* @param $redisKey
* @param $type
* @param array $dataIds
* @param array $where
* @param string $filed
* @return int
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function setRedisData($redisKey, $type, array $dataIds, array $where, $filed = "*")
{
if (!$redisKey || !$type) return 0;
/** @var CacheService $redis */
$redis = app()->make(CacheService::class);
if ($dataIds) {
foreach ($dataIds as $v) {
$redis->sAdd($redisKey, $v);
}
} else {
if ($where) {
foreach ($where as $k => $v) {
if (!$v) unset($where[$k]);
}
}
switch ($type) {
case 1://批量发放优惠券
case 2://批量设置用户分组
case 3://批量设置用户标签
/** @var UserServices $userService */
$userService = app()->make(UserServices::class);
$dataInfo = $userService->getUserInfoList($where, $filed);
if ($dataInfo) {
foreach ($dataInfo as $k => $v) {
$redis->sAdd($redisKey, $v['uid']);
}
}
break;
case 4://批量上下架商品
case 11:
case 12:
$cateIds = [];
if (isset($where['cate_id']) && $where['cate_id']) {
/** @var StoreProductCategoryServices $storeCategory */
$storeCategory = app()->make(StoreProductCategoryServices::class);
$cateIds = $storeCategory->getColumn(['pid' => $where['cate_id']], 'id');
}
if ($cateIds) {
$cateIds[] = $where['cate_id'];
$where['cate_id'] = $cateIds;
}
/** @var StoreProductServices $productService */
$productService = app()->make(StoreProductServices::class);
$dataInfo = $productService->getProductListByWhere($where, $filed);
if ($dataInfo) {
foreach ($dataInfo as $k => $v) {
$redis->sAdd($redisKey, $v['id']);
}
}
break;
case 5://批量删除商品规格
/** @var StoreProductRuleServices $productRuleService */
$productRuleService = app()->make(StoreProductRuleServices::class);
$dataInfo = $productRuleService->getProductRuleList($where, $filed);
if ($dataInfo) {
foreach ($dataInfo as $k => $v) {
$redis->sAdd($redisKey, $v['id']);
}
}
break;
case 6://批量删除用户已删除订单
/** @var StoreOrderServices $orderService */
$orderService = app()->make(StoreOrderServices::class);
$dataInfo = $orderService->getOrderListByWhere($where, $filed);
if ($dataInfo) {
foreach ($dataInfo as $k => $v) {
$redis->sAdd($redisKey, $v['id']);
}
}
break;
default:
return 0;
break;
}
}
return $redis->sCard($redisKey);
}
/**
* 获取队列redis中存的数据集合
* @param string $redisKey
* @param array $queueInfo
* @return array
*/
public function getQueueRedisdata($queueInfo, string $redisKey = '')
{
if (!$queueInfo) return [$redisKey, []];
if (!$redisKey) {
$redisKey = $queueInfo['execute_key'] ?? '';
}
if (!$redisKey) {
return [$redisKey, []];
}
/** @var CacheService $redis */
$redis = app()->make(CacheService::class);
return [$redisKey, $redis->sMembers($redisKey)];
}
/**
* 批量发送优惠券
* @param $coupon
* @param $type
* @return bool
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function sendCoupon($coupon, $type)
{
if (!$type || !$coupon) return false;
$queueInfo = $this->dao->getQueueOne(['type' => $type, 'status' => 0]);
if (!$queueInfo) {
return false;
}
//把队列需要执行的入参数据存起来,以便队列执行失败后接着执行,同时队列状态改为正在执行状态。
$this->dao->setQueueDoing($coupon, $queueInfo['id']);
[$redisKey, $uids] = $this->getQueueRedisdata($queueInfo);
if ($uids) {
$chunkUids = array_chunk($uids, 100, true);
/** @var StoreCouponIssueServices $issueService */
$issueService = app()->make(StoreCouponIssueServices::class);
foreach ($chunkUids as $v) {
$issueService->setCoupon($coupon, $v, $redisKey, $queueInfo);
}
}
//发完后将队列置为完成
$this->setQueueSuccess($queueInfo['id'], $queueInfo['type']);
return true;
}
/**
* 批量设置用户分组
* @param $groupId
* @param $type
* @return bool
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function setUserGroup($groupId, $type)
{
if (!$groupId || !$type) return false;
$queueInfo = $this->dao->getQueueOne(['type' => $type, 'status' => 0]);
if (!$queueInfo) {
return false;
}
/** @var UserGroupServices $userGroup */
$userGroup = app()->make(UserGroupServices::class);
if (!$userGroup->getGroup($groupId)) {
return false;
}
//把队列需要执行的入参数据存起来,以便队列执行失败后接着执行,同时队列状态改为正在执行状态。
$this->dao->setQueueDoing($groupId, $queueInfo['id']);
[$redisKey, $uids] = $this->getQueueRedisdata($queueInfo);
if ($uids) {
$chunkUids = array_chunk($uids, 1000, true);
/** @var UserServices $userServices */
$userServices = app()->make(UserServices::class);
foreach ($chunkUids as $v) {
//执行分组
if (!$userServices->setUserGroup($v, $groupId)) {
$this->setQueueFail($queueInfo['id'], $redisKey);
} else {
$this->doSuccessSremRedis($v, $redisKey, $type);
}
}
}
//发完后将队列置为完成
$this->setQueueSuccess($queueInfo['id'], $queueInfo['type']);
return true;
}
/**
* 批量设置用户标签
* @param $labelId
* @param $type
* @return bool
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function setUserLabel($labelId, $type, $other = [])
{
if (!$labelId || !$type) return false;
$queueInfo = $this->dao->getQueueOne(['type' => $type, 'status' => 0]);
if (!$queueInfo) {
return false;
}
/** @var UserLabelServices $userLabelServices */
$userLabelServices = app()->make(UserLabelServices::class);
$count = $userLabelServices->getCount([['id', 'IN', $labelId]]);
if ($count != count($labelId)) {
return false;
}
//把队列需要执行的入参数据存起来,以便队列执行失败后接着执行,同时队列状态改为正在执行状态。
$this->dao->setQueueDoing($labelId, $queueInfo['id']);
[$redisKey, $uids] = $this->getQueueRedisdata($queueInfo);
if ($uids) {
$chunkUids = array_chunk($uids, 1000, true);
/** @var UserLabelRelationServices $services */
$services = app()->make(UserLabelRelationServices::class);
$store_id = $other['store_id'] ?? 0;
foreach ($chunkUids as $v) {
if (!$services->setUserLable($v, $labelId, $store_id ? 1 : 0, $store_id)) {
$this->setQueueFail($queueInfo['id'], $redisKey);
} else {
$this->doSuccessSremRedis($v, $redisKey, $type);
}
}
}
//发完后将队列置为完成
$this->setQueueSuccess($queueInfo['id'], $queueInfo['type']);
return true;
}
/**
* 商品批量上下架
* @param string $upORdown
* @param $type
* @return bool
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function setProductShow($upORdown = "up", $type = 1)
{
if (!$type) return false;
$queueInfo = $this->dao->getQueueOne(['type' => $type, 'status' => 0]);
if (!$queueInfo) {
return false;
}
//把队列需要执行的入参数据存起来,以便队列执行失败后接着执行,同时队列状态改为正在执行状态。
$this->dao->setQueueDoing($upORdown, $queueInfo['id']);
[$redisKey, $pids] = $this->getQueueRedisdata($queueInfo);
if ($pids) {
$chunkPids = array_chunk($pids, 1000, true);
$isShow = 0;
if ($upORdown == 'up') $isShow = 1;
/** @var StoreProductServices $storeproductServices */
$storeproductServices = app()->make(StoreProductServices::class);
/** @var StoreProductRelationServices $storeProductRelationServices */
$storeProductRelationServices = app()->make(StoreProductRelationServices::class);
/** @var StoreCartServices $cartService */
$cartService = app()->make(StoreCartServices::class);
$update = ['is_show' => $isShow];
if ($isShow) {//手动上架 清空定时下架状态
$update['auto_off_time'] = 0;
}
foreach ($chunkPids as $v) {
//商品
$res = $storeproductServices->batchUpdate($v, $update);
//门店商品
$storeproductServices->batchUpdateAppendWhere($v, $update, ['type' => 1], 'pid');
if ($isShow == 0) {
$storeProductRelationServices->setShow($v, (int)$isShow);
//购物车
$cartService->batchUpdate($v, ['status' => 1], 'product_id');
}
//下架检测是否有参与活动商品
try {
// $is_activity = $storeproductServices->checkActivity($v);
} catch (\Throwable $e) {
$is_activity = false;
}
if ($isShow == 0 || $is_activity) {
//改变购物车中状态
$storeProductRelationServices->setShow($v, (int)$isShow);
}
if (!$res) {
$this->setQueueFail($queueInfo['id'], $redisKey);
} else {
$this->doSuccessSremRedis($v, $redisKey, $type);
}
}
}
//发完后将队列置为完成
$this->setQueueSuccess($queueInfo['id'], $queueInfo['type']);
return true;
}
/**
* 批量队列删除商品规格
* @param $type
* @return bool
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function delProductRule($type)
{
if (!$type) return false;
$queueInfo = $this->dao->getQueueOne(['type' => $type, 'status' => 0]);
if (!$queueInfo) {
return false;
}
//把队列需要执行的入参数据存起来,以便队列执行失败后接着执行,同时队列状态改为正在执行状态。
$this->dao->setQueueDoing('', $queueInfo['id']);
[$redisKey, $pids] = $this->getQueueRedisdata($queueInfo);
if ($pids) {
$chunkPids = array_chunk($pids, 1000, true);
/** @var StoreProductRuleServices $storeProductRuleservices */
$storeProductRuleservices = app()->make(StoreProductRuleServices::class);
foreach ($chunkPids as $v) {
$res = $storeProductRuleservices->del(implode(',', $v));
if ($res) {
$this->doSuccessSremRedis($v, $redisKey, $queueInfo['type']);
} else {
$this->addQueueFail($queueInfo['id'], $redisKey);
}
}
}
//发完后将队列置为完成
$this->setQueueSuccess($queueInfo['id'], $queueInfo['type']);
return true;
}
/**
* 批量加入回收站
* @return void
* User: liusl
* DateTime: 2025/5/22 11:37
*/
public function productRecycle($type)
{
if (!$type) return false;
$queueInfo = $this->dao->getQueueOne(['type' => $type, 'status' => 0]);
if (!$queueInfo) {
return false;
}
//把队列需要执行的入参数据存起来,以便队列执行失败后接着执行,同时队列状态改为正在执行状态。
$this->dao->setQueueDoing('', $queueInfo['id']);
[$redisKey, $pids] = $this->getQueueRedisdata($queueInfo);
if ($pids) {
$chunkPids = array_chunk($pids, 1000, true);
$res = app()->make(StoreProductServices::class)->delAll($pids);
foreach ($chunkPids as $v) {
if ($res) {
$this->doSuccessSremRedis($v, $redisKey, $type);
} else {
$this->setQueueFail($queueInfo['id'], $redisKey);
}
}
}
//发完后将队列置为完成
$this->setQueueSuccess($queueInfo['id'], $queueInfo['type']);
return true;
}
/**
* 彻底删除商品
* @param $type
* @return bool
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
* User: liusl
* DateTime: 2025/5/23 10:22
*/
public function productDeleteBatch($type)
{
if (!$type) return false;
$queueInfo = $this->dao->getQueueOne(['type' => $type, 'status' => 0]);
if (!$queueInfo) {
return false;
}
//把队列需要执行的入参数据存起来,以便队列执行失败后接着执行,同时队列状态改为正在执行状态。
$this->dao->setQueueDoing('', $queueInfo['id']);
[$redisKey, $pids] = $this->getQueueRedisdata($queueInfo);
if ($pids) {
$chunkPids = array_chunk($pids, 1000, true);
$res = app()->make(SystemClearServices::class)->recycleProduct($pids);
foreach ($chunkPids as $v) {
if ($res) {
$this->doSuccessSremRedis($v, $redisKey, $type);
} else {
$this->setQueueFail($queueInfo['id'], $redisKey);
}
}
}
//发完后将队列置为完成
$this->setQueueSuccess($queueInfo['id'], $queueInfo['type']);
return true;
}
/**
* 批量队列删除订单
* @param $type
* @return bool
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function delOrder($type)
{
if (!$type) return false;
$queueInfo = $this->dao->getQueueOne(['type' => $type, 'status' => 0]);
if (!$queueInfo) {
return false;
}
//把队列需要执行的入参数据存起来,以便队列执行失败后接着执行,同时队列状态改为正在执行状态。
$this->dao->setQueueDoing('', $queueInfo['id']);
[$redisKey, $pids] = $this->getQueueRedisdata($queueInfo);
if ($pids) {
$chunkPids = array_chunk($pids, 1000, true);
/** @var StoreOrderServices $storeOrderServices */
$storeOrderServices = app()->make(StoreOrderServices::class);
foreach ($chunkPids as $v) {
$res = $storeOrderServices->batchUpdateOrder($v, ['is_system_del' => 1]);
if ($res) {
$this->doSuccessSremRedis($v, $redisKey, $type);
} else {
$this->setQueueFail($queueInfo['id'], $redisKey);
}
}
}
//发完后将队列置为完成
$this->setQueueSuccess($queueInfo['id'], $queueInfo['type']);
return true;
}
/**
* 队列批量发货
* @param $oid
* @param array $deliveryData
* @return bool
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function orderDelivery($oid, array $deliveryData)
{
if (!$oid) return false;
if (!isset($deliveryData['queueType'])) {
return false;
}
/** @var QueueAuxiliaryServices $auxiliaryService */
$auxiliaryService = app()->make(QueueAuxiliaryServices::class);
//看是否能查到任务数据
$auxiliaryInfo = $auxiliaryService->getOrderCacheOne(['binding_id' => $deliveryData['queueId'], 'relation_id' => $oid, 'type' => $deliveryData['cacheType']]);
if (!$auxiliaryInfo || !$auxiliaryInfo['other']) {
return false;
}
$deliveryInfo = json_decode($auxiliaryInfo['other'], true);
if ($deliveryData['queueType'] == 7) {
if (!$deliveryInfo['delivery_name'] || !$deliveryInfo['delivery_code'] || !$deliveryInfo['delivery_id']) {
return false;
}
$deliveryData['express_record_type'] = 1;
$deliveryData['delivery_name'] = $deliveryInfo['delivery_name'];
$deliveryData['delivery_id'] = $deliveryInfo['delivery_id'];
$deliveryData['delivery_code'] = $deliveryInfo['delivery_code'];
}
try {
/** @var StoreOrderDeliveryServices $storeOrderDelivery */
$storeOrderDelivery = app()->make(StoreOrderDeliveryServices::class);
//发货
$storeOrderDelivery->delivery($oid, $deliveryData);
} catch (\Throwable $e) {
Log::error('队列发货失败发货,order_id:' . $oid . ',原因:' . $e->getMessage());
}
//更改队列子集数据
$this->doSuccessSremRedis(['order_id' => $oid], $deliveryData['queueId'], $deliveryData['queueType'], ['phone_message' => 1, 'status' => 1]);
//队列置为完成
return $this->setQueueSuccess($deliveryData['queueId'], $deliveryData['queueType']);
}
/**
* 添加任务前校验同类型任务状态
* @param $type
* @param array $queueInfo
* @param false $is_again
* @return bool
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function checkTypeQueue($type, array $queueInfo = [], bool $is_again = false)
{
if (!$type) return false;
if (!$queueInfo) {
$queueInfo = $this->dao->getQueueOne(['type' => $type, 'status' => [0, 1]]);
}
if (!$queueInfo) {
return false;
}
$num = 0;
if (in_array($type, [7, 8, 9, 10])) {
/** @var QueueAuxiliaryServices $auxiliaryService */
$auxiliaryService = app()->make(QueueAuxiliaryServices::class);
$num = $auxiliaryService->count(['binding_id' => $queueInfo['id'], 'status' => 0]);
} else {
if ($queueInfo['execute_key']) {
/** @var CacheService $redis */
$redis = app()->make(CacheService::class);
$num = $redis->sCard($queueInfo['execute_key']);
}
}
if ($num) {
if (!$is_again) {
if ($queueInfo['status'] == 0) {
throw new AdminException('上次批量任务尚未执行,请前往任务列表手动执行');
}
if ($queueInfo['status'] == 1) {
throw new AdminException('有正在执行中的任务,请耐心等待,若长时间无反应,前往任务列表修复异常数据,再手动执行');
}
}
} else {
$this->delWrongQueue(0, $type);
return false;
}
return true;
}
/**
* 修复异常任务
* @param $queueInfo
* @return bool|mixed
*/
public function repairWrongQueue($queueInfo)
{
if (!$queueInfo) throw new AdminException('任务不存在');
try {
switch ($queueInfo['type']) {
case 1://批量发放优惠券
case 2://批量设置用户分组
case 3://批量设置用户标签
case 4://批量上下架商品
case 5://批量删除商品规格
case 6://批量删除用户已删除订单
if (!$queueInfo['execute_key']) {
throw new AdminException('缓存key缺失,请清除数据');
}
/** @var CacheService $redis */
$redis = app()->make(CacheService::class);
$cacheNum = $redis->sCard($queueInfo['execute_key']);
if ($cacheNum != $queueInfo['surplus_num']) {
return $this->dao->update(['id' => $queueInfo['id']], ['surplus_num' => $cacheNum]);
}
break;
case 7://手动发货
case 8://电子面单发货
case 9://批量配送
case 10://批量虚拟发货
/** @var QueueAuxiliaryServices $auxiliaryService */
$auxiliaryService = app()->make(QueueAuxiliaryServices::class);
$cacheType = $this->queue_redis_key[$queueInfo['type']] ?? '';
$cacheFailAndNoNum = $auxiliaryService->getCountOrder(['binding_id' => $queueInfo['id'], 'type' => $cacheType, 'status' => [0, 2]]);
$cacheTotalNum = $auxiliaryService->getCountOrder(['binding_id' => $queueInfo['id'], 'type' => $cacheType, 'status' => [0, 1, 2]]);
//如果任务已经执行完毕,但是记录却存在未执行数据,要进行修复,让其重新执行
if ($cacheFailAndNoNum && $queueInfo['status'] == 2) return $this->dao->update(['id' => $queueInfo['id']], ['status' => 3, 'surplus_num' => $cacheFailAndNoNum, 'total_num' => $cacheTotalNum]);
//如果执行失败,记录全部执行成功,那么进行修复
if (!$cacheFailAndNoNum && $queueInfo['status'] != 2) return $this->dao->update(['id' => $queueInfo['id']], ['status' => 2, 'surplus_num' => 0, 'total_num' => $cacheTotalNum]);
}
return true;
} catch (\Exception $e) {
throw new AdminException($e->getMessage());
}
}
/**
* 队列再次执行
* @param $queueId
* @param $type
* @return bool
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function againDoQueue($queueId, $type)
{
$queueInfo = $this->getQueueOne(['id' => $queueId, 'type' => $type]);
if (!$queueInfo) {
throw new AdminException('队列任务不存在');
}
if (!$queueInfo['queue_in_value']) {
throw new AdminException('队列关键数据缺失,请清除此任务及异常数据');
}
if ($queueInfo['status'] == 2) {
throw new AdminException('队列已完成');
}
if ($queueInfo['status'] == 3) {
throw new AdminException('队列异常,请清除队列重新加入');
}
if ($queueInfo['status'] == 4) {
throw new AdminException('队列已删除');
}
//检测当前队列
if (!$this->checkTypeQueue($type, $queueInfo, true)) {
throw new AdminException('任务已清除,无需再次执行');
}
//先进行数据修复
$this->repairWrongQueue($queueInfo);
if (in_array($type, [7, 8, 9, 10])) {
$queueInValue = json_decode($queueInfo['queue_in_value'], true);
/** @var StoreOrderServices $storeOrderService */
$storeOrderService = app()->make(StoreOrderServices::class);
$storeOrderService->adminQueueOrderDo($queueInValue, true);
} else {
$queueInValue = $queueInfo['queue_in_value'];
if ($type == 1) {
$queueInValue = json_decode($queueInfo['queue_in_value'], true);
}
//加入队列
BatchHandleJob::dispatch([$queueInValue, $type]);
}
return true;
}
/**
* 任务执行失败,修改队列状态
* @param $queueId
* @param string $redisKey
* @return mixed
*/
public function setQueueFail($queueId, $redisKey = '')
{
if ($redisKey) {
/** @var CacheService $cacheService */
$cacheService = app()->make(CacheService::class);
$surplusNum = $cacheService->sCard($redisKey);
} else {
/** @var QueueAuxiliaryServices $auxiliaryService */
$auxiliaryService = app()->make(QueueAuxiliaryServices::class);
$surplusNum = $auxiliaryService->count(['binding_id' => $queueId, 'status' => 0]);
}
return $this->dao->update(['id' => $queueId], ['status' => 3, 'surplus_num' => $surplusNum]);
}
/**
* 将执行成功数据移除redis集合
* @param array $data
* @param $redisKey
* @return bool
*/
public function doSuccessSremRedis(array $data, $redisKey, $type, array $otherData = [])
{
if (!$data || !$redisKey || !$type) return true;
if (in_array($type, [7, 8, 9, 10])) {
$where['relation_id'] = $data['order_id'];
$where['binding_id'] = $redisKey;
/** @var QueueAuxiliaryServices $auxiliaryService */
$auxiliaryService = app()->make(QueueAuxiliaryServices::class);
$getOne = $auxiliaryService->getOrderCacheOne($where);
if (!$getOne) return false;
$other = json_decode($getOne['other'], true);
if (isset($otherData['delivery_status'])) $other['delivery_status'] = $otherData['delivery_status'];
if (isset($otherData['wx_message'])) $other['wx_message'] = $otherData['wx_message'];
if (isset($otherData['phone_message'])) $other['phone_message'] = $otherData['phone_message'];
if (isset($otherData['error_info'])) $other['error_info'] = $otherData['error_info'];
$updateData['status'] = isset($otherData['status']) ? $otherData['status'] : 0;
$updateData['other'] = json_encode($other);
$updateData['update_time'] = time();
$auxiliaryService->updateOrderStatus($where, $updateData);
} else {//在redis缓存集合的从集合删除
/** @var CacheService $redis */
$redis = app()->make(CacheService::class);
foreach ($data as $k => $v) {
$redis->sRem($redisKey, $v);
}
}
return true;
}
/**
* 任务执行成功
* @param $queueId
* @param $type
* @return bool|mixed
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function setQueueSuccess($queueId, $type)
{
if (!$queueId || !$type) return false;
$queueInfo = $this->dao->get($queueId);
if (!$queueInfo) return false;
$res = true;
if (in_array($type, [7, 8, 9, 10])) {
$res = false;
if ($queueInfo['surplus_num'] > 0) {
$this->dao->bcDec($queueId, 'surplus_num', 1);
}
//看是否全部执行成功
$queueInfo = $this->dao->get($queueId);
if ($queueInfo['surplus_num'] == 0) {
$res = true;
}
}
if ($res) {
$update = [
'status' => 2,
'finish_time' => time(),
'surplus_num' => 0
];
return $this->dao->update(['id' => $queueId], $update);
}
return true;
}
/**
* 清除异常队列
* @param $queueId
* @param $type
* @return bool
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function delWrongQueue($queueId, $type, $is_del = true)
{
if (!$type) return false;
if ($queueId) {
$queueInfo = $this->dao->getQueueOne(['id' => $queueId, 'type' => $type]);
} else {
$queueInfo = $this->dao->getQueueOne(['type' => $type]);
}
if (!$queueInfo) {
return true;
}
try {
$data = ['status' => 3];
if ($is_del) {
if (in_array($type, [7, 8, 9, 10])) {
/** @var QueueAuxiliaryServices $auxiliaryService */
$auxiliaryService = app()->make(QueueAuxiliaryServices::class);
$auxiliaryService->batchUpdate(['binding_id' => $queueInfo['id']], ['status' => 3]);
} else {
if ($queueInfo['execute_key']) {
/** @var CacheService $redis */
$redis = app()->make(CacheService::class);
$redis->del($queueInfo['execute_key']);
}
}
$data = ['is_del' => 1, 'status' => 4];
}
$this->dao->update(['id' => $queueInfo['id']], $data);
} catch (\Throwable $e) {
Log::error('清除异常队列失败,原因' . $e->getMessage());
}
return true;
}
}