308 lines
7.3 KiB
PHP
308 lines
7.3 KiB
PHP
<?php
|
|
|
|
namespace App\Cache\Redis\Api;
|
|
|
|
use App\Cache\Redis\RedisCache;
|
|
use App\Constants\Common\GoodCode;
|
|
use App\Extend\DateUtil;
|
|
use App\Model\Sku;
|
|
use App\Model\Spu;
|
|
use App\Service\ServiceTrait\Common\OssTrait;
|
|
use Hyperf\Di\Annotation\Inject;
|
|
use Psr\Container\ContainerExceptionInterface;
|
|
use Psr\Container\NotFoundExceptionInterface;
|
|
|
|
class GoodCache
|
|
{
|
|
use OssTrait;
|
|
|
|
/**
|
|
* @var RedisCache $redis
|
|
*/
|
|
#[Inject]
|
|
protected RedisCache $redis;
|
|
|
|
/**
|
|
* @var Spu $spuModel
|
|
*/
|
|
#[Inject]
|
|
protected Spu $spuModel;
|
|
|
|
/**
|
|
* @var Sku $skuModel
|
|
*/
|
|
#[Inject]
|
|
protected Sku $skuModel;
|
|
|
|
/**
|
|
* @var int $cycleId
|
|
*/
|
|
public int $cycleId;
|
|
|
|
/**
|
|
* @var int $kitchenId
|
|
*/
|
|
public int $kitchenId;
|
|
|
|
/**
|
|
* @var string
|
|
*/
|
|
protected string $optionalKey;
|
|
|
|
/**
|
|
* @var string
|
|
*/
|
|
protected string $mealKey;
|
|
|
|
/**
|
|
* @var array $stockArr
|
|
*/
|
|
private array $stockArr = [];
|
|
|
|
/**
|
|
* @var int
|
|
*/
|
|
private int $expireTime;
|
|
|
|
/**
|
|
* @return void
|
|
*/
|
|
public function __construct()
|
|
{
|
|
$this->expireTime = DateUtil::DAY;
|
|
}
|
|
|
|
/**
|
|
* @param int $id
|
|
* @return bool|float|int|\Redis
|
|
* @throws ContainerExceptionInterface
|
|
* @throws NotFoundExceptionInterface
|
|
*/
|
|
public function getStock(int $id): float|bool|int|\Redis
|
|
{
|
|
$stockKey = ApiRedisKey::goodStockKey($this->cycleId,$this->kitchenId);
|
|
return $this->redis->zScore($stockKey, $id) ?? 0;
|
|
}
|
|
|
|
/**
|
|
* @return void
|
|
* @throws ContainerExceptionInterface
|
|
* @throws NotFoundExceptionInterface
|
|
*/
|
|
private function initGoodCacheByCycleId(): void
|
|
{
|
|
$this->mealKey = ApiRedisKey::mealGoodListKey($this->cycleId,$this->kitchenId);
|
|
$this->optionalKey = ApiRedisKey::optionalGoodListKey($this->cycleId,$this->kitchenId);
|
|
|
|
if ($this->checkMealGoodCache() && $this->checkOptionalGoodCache()) return;
|
|
|
|
$this->setOptionalGoodCache();
|
|
|
|
$this->setMealGoodCache();
|
|
|
|
if (!empty($this->stockArr)) {
|
|
$stockKey = ApiRedisKey::goodStockKey($this->cycleId,$this->kitchenId);
|
|
foreach ($this->stockArr as $one) {
|
|
$this->redis->zAdd($stockKey,$one['stock'],$one['id']);
|
|
$this->redis->expire($stockKey,$this->expireTime);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @return void
|
|
* @throws ContainerExceptionInterface
|
|
* @throws NotFoundExceptionInterface
|
|
*/
|
|
private function setMealGoodCache(): void
|
|
{
|
|
$list = $this->spuModel->getListByCycleIdAndType($this->cycleId, $this->kitchenId,GoodCode::SPU_TYPE_MEAL);
|
|
|
|
if (empty($list)) return;
|
|
|
|
$list = $list->toArray();
|
|
|
|
$this->buildData($list);
|
|
|
|
$this->redis->set($this->mealKey, json_encode($list));
|
|
$this->redis->expire($this->mealKey,$this->expireTime);
|
|
}
|
|
|
|
/**
|
|
* @param $list
|
|
* @return mixed
|
|
*/
|
|
private function buildData(&$list): mixed
|
|
{
|
|
$spuIds = array_column($list, 'id');
|
|
|
|
$skuList = $this->skuModel->getListBySpuIds($spuIds);
|
|
|
|
if ($skuList->isEmpty()) return $list;
|
|
|
|
$skuList = $skuList->toArray();
|
|
|
|
$imageIdArr = array_column($skuList,'image_ids');
|
|
$imageList = $this->getOssObjects($imageIdArr);
|
|
|
|
$skuListArr = [];
|
|
$imageArr = [];
|
|
$stockArr = [];
|
|
foreach ($skuList as $sku) {
|
|
if (empty($skuListArr[$sku['spu_id']])) {
|
|
$skuListArr[$sku['spu_id']] = [];
|
|
}
|
|
|
|
$sku['url'] = $imageList[$sku['image_ids']]['url'] ?? '';
|
|
|
|
$skuListArr[$sku['spu_id']][] = $sku;
|
|
$imageArr[$sku['spu_id']] = array_merge($imageArr[$sku['spu_id']] ?? [],[$sku['url']]);
|
|
|
|
$stockArr[] = [
|
|
'id' => $sku['id'],
|
|
'stock' => $sku['surplus_stock']
|
|
];
|
|
}
|
|
|
|
if (!empty($stockArr)) {
|
|
$this->stockArr = $stockArr;
|
|
}
|
|
|
|
foreach ($list as &$item) {
|
|
$item['sku_list'] = $skuListArr[$item['id']] ?? [];
|
|
$item['image_list'] = $imageArr[$item['id']] ?? [];
|
|
}
|
|
|
|
return $list;
|
|
}
|
|
|
|
/**
|
|
* @return void
|
|
* @throws ContainerExceptionInterface
|
|
* @throws NotFoundExceptionInterface
|
|
*/
|
|
private function setOptionalGoodCache(): void
|
|
{
|
|
$list = $this->spuModel->getListByCycleIdAndType($this->cycleId, $this->kitchenId,GoodCode::SPU_TYPE_OPTIONAL);
|
|
|
|
if (empty($list)) return;
|
|
|
|
$list = $list->toArray();
|
|
|
|
$this->buildData($list);
|
|
|
|
$this->redis->set($this->optionalKey, json_encode($list));
|
|
$this->redis->expire($this->optionalKey,$this->expireTime);
|
|
}
|
|
|
|
/**
|
|
* @return bool
|
|
* @throws ContainerExceptionInterface
|
|
* @throws NotFoundExceptionInterface
|
|
*/
|
|
private function checkMealGoodCache(): bool
|
|
{
|
|
if ($this->redis->exists($this->mealKey)) return true;
|
|
|
|
$this->redis->delete($this->mealKey);
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* @return bool
|
|
* @throws ContainerExceptionInterface
|
|
* @throws NotFoundExceptionInterface
|
|
*/
|
|
private function checkOptionalGoodCache(): bool
|
|
{
|
|
if ($this->redis->exists($this->optionalKey)) return true;
|
|
|
|
$this->redis->delete($this->optionalKey);
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* @return array|mixed
|
|
* @throws ContainerExceptionInterface
|
|
* @throws NotFoundExceptionInterface
|
|
*/
|
|
public function getOptionalGoodList(): mixed
|
|
{
|
|
$this->initGoodCacheByCycleId();
|
|
|
|
$data = $this->redis->get($this->optionalKey);
|
|
|
|
if (empty($data)) return [];
|
|
|
|
$data = json_decode($data,true);
|
|
|
|
$this->buildStockData($data);
|
|
|
|
return $data;
|
|
}
|
|
|
|
/**
|
|
* @param $data
|
|
* @return mixed
|
|
* @throws ContainerExceptionInterface
|
|
* @throws NotFoundExceptionInterface
|
|
*/
|
|
private function buildStockData(&$data): mixed
|
|
{
|
|
foreach ($data as &$spu) {
|
|
foreach ($spu['sku_list'] as &$sku) {
|
|
$sku['stock'] = $this->getStock($sku['id']);
|
|
}
|
|
}
|
|
|
|
return $data;
|
|
}
|
|
|
|
/**
|
|
* @return array|mixed
|
|
* @throws ContainerExceptionInterface
|
|
* @throws NotFoundExceptionInterface
|
|
*/
|
|
public function getMealGoodList(): mixed
|
|
{
|
|
$this->initGoodCacheByCycleId();
|
|
|
|
$data = $this->redis->get($this->mealKey);
|
|
|
|
if (empty($data)) return [];
|
|
|
|
$data = json_decode($data,true);
|
|
|
|
$this->buildStockData($data);
|
|
|
|
return $data;
|
|
}
|
|
|
|
/**
|
|
* @param int $kitchenId
|
|
* @param int $cycleId
|
|
* @return void
|
|
* @throws ContainerExceptionInterface
|
|
* @throws NotFoundExceptionInterface
|
|
*/
|
|
public function delCache(int $kitchenId,int $cycleId): void
|
|
{
|
|
$keyArr = [
|
|
ApiRedisKey::mealGoodListKey($cycleId,$kitchenId),
|
|
ApiRedisKey::optionalGoodListKey($cycleId,$kitchenId),
|
|
ApiRedisKey::goodStockKey($cycleId,$kitchenId)
|
|
];
|
|
|
|
$script = <<<LUA
|
|
local corpseCount = 0
|
|
for _, key in ipairs(KEYS) do
|
|
corpseCount = corpseCount + redis.call('DEL', key)
|
|
end
|
|
return corpseCount
|
|
LUA;
|
|
|
|
$this->redis->eval($script, $keyArr,count($keyArr));
|
|
}
|
|
} |