diff --git a/app/api/controller/StoreKeeper.php b/app/api/controller/StoreKeeper.php index ce257ac9..6903219e 100644 --- a/app/api/controller/StoreKeeper.php +++ b/app/api/controller/StoreKeeper.php @@ -30,6 +30,7 @@ use app\store\model\Order as OrderModel; use app\store\model\OrderRefund as OrderRefundModel; use app\store\model\dealer\Order as DealerOrderModel; use app\store\model\Article as ArticleModel; +use app\store\model\goods\GoodsPrice as GoodsPriceModel; /** * 店主管理 @@ -500,4 +501,46 @@ class StoreKeeper extends Controller } + //会员、分销价格配置 + + /** + * 配置列表 + * @return Json + * @throws \think\db\exception\DbException + */ + public function priceList(): Json + { + $model = new GoodsPriceModel; + $list = $model->getAll($this->request->param()); + return $this->renderSuccess(compact('list')); + } + + public function addPrice(): Json + { + $model = new GoodsPriceModel; + if (!$model->add($this->request->param())) { + return $this->renderError($model->getError() ?: '添加失败'); + } + return $this->renderSuccess('添加成功'); + } + + public function editPrice(): Json + { + $model = new GoodsPriceModel; + if (!$model->edit($this->request->param())) { + return $this->renderError($model->getError() ?: '编辑失败'); + } + return $this->renderSuccess('编辑成功'); + } + + public function delPrice(): Json + { + $model = new GoodsPriceModel; + if (!$model->del($this->request->param())) { + return $this->renderError($model->getError() ?: '删除失败'); + } + return $this->renderSuccess('删除成功'); + } + + } \ No newline at end of file diff --git a/app/api/model/Goods.php b/app/api/model/Goods.php index 28f452c3..b548ffa3 100644 --- a/app/api/model/Goods.php +++ b/app/api/model/Goods.php @@ -26,6 +26,7 @@ use cores\exception\BaseException; use think\db\exception\DataNotFoundException; use think\db\exception\DbException; use think\db\exception\ModelNotFoundException; +use app\store\model\goods\GoodsPrice as GoodsPriceModel; /** * 商品模型 @@ -350,9 +351,78 @@ class Goods extends GoodsModel return $this->setGoodsData($goodsInfo, function ($goods) { // 计算并设置商品会员价 $this->getEnableGradeMoney() && $this->setGoodsGradeMoney($goods); + //计算plus 分销价格 + $this->setGoodsMoney($goods); }); } + /** + * 设置商品plus 分销价格 + * @param Goods $goods + * @throws BaseException + */ + private function setGoodsMoney(self $goods) + { + // 判断是否登录 + if (!UserService::isLogin()) { + return; + } + $catService = new \app\store\model\GoodsCategoryRel(); + $catIds = $catService->where(['goods_id' => $goods->goods_id])->column('category_id'); + //读取分类集 + $price_list_plus = $price_list_dealer = []; + foreach ($catIds as $k => $v) { + $price_list_plus[] = GoodsPriceModel::getDiscountPrice($v, 1, $goods['goods_price_min']); + $price_list_dealer[] = GoodsPriceModel::getDiscountPrice($v, 2, $goods['goods_price_min']); + } + //价格判断 + if (UserService::isstore()) { + $goods['goods_price_min_plus'] = min($price_list_plus); + $goods['goods_price_min_dealer'] = min($price_list_dealer); + } elseif (UserService::isPlusMember()) { + $goods['goods_price_min_plus'] = min($price_list_plus); + } elseif (UserService::isDealerMember()) { + $goods['goods_price_min_dealer'] = min($price_list_dealer); + } + // 会员折扣价: 商品sku列表 + if ($goods->getRelation('skuList')) { + foreach ($goods['skuList'] as &$skuItem) { + $temp_price_plus = $temp_price_dealer = []; + foreach ($catIds as $k => $v) { + $temp_price_plus[] = GoodsPriceModel::getDiscountPrice($v, 1, $skuItem['goods_price']); + $temp_price_dealer[] = GoodsPriceModel::getDiscountPrice($v, 2, $skuItem['goods_price']); + } + //价格判断 + if (UserService::isstore()) { + $skuItem['goods_price_plus'] = min($temp_price_plus); + $skuItem['goods_price_dealer'] = min($temp_price_dealer); + } elseif (UserService::isPlusMember()) { + $skuItem['goods_price_plus'] = min($temp_price_plus); + } elseif (UserService::isDealerMember()) { + $skuItem['goods_price_dealer'] = min($temp_price_dealer); + } + + } + } + // 折扣价: 已选择的商品sku(用于购物车) + if ($goods->getAttr('skuInfo')) { + if (UserService::isPlusMember()) { + $sku_price_plus = []; + foreach ($catIds as $k => $v) { + $sku_price_plus[] = GoodsPriceModel::getDiscountPrice($v, 1, $goods['skuInfo']['goods_price']); + } + $goods['skuInfo']['goods_price'] = min($sku_price_plus); + } elseif (UserService::isDealerMember()) { + $sku_price_dealer = []; + foreach ($catIds as $k => $v) { + $sku_price_dealer[] = GoodsPriceModel::getDiscountPrice($v, 2, $goods['skuInfo']['goods_price']); + } + $goods['skuInfo']['goods_price'] = min($sku_price_dealer); + } + + } + } + /** * 设置商品的会员价 * @param Goods $goods diff --git a/app/api/service/Goods.php b/app/api/service/Goods.php index bffafc63..0eca5075 100644 --- a/app/api/service/Goods.php +++ b/app/api/service/Goods.php @@ -16,6 +16,7 @@ use app\api\model\Goods as GoodsModel; use app\api\model\Setting as SettingModel; use app\api\model\GoodsSku as GoodsSkuModel; use app\api\model\Category as CategoryModel; +use app\api\service\User as UserService; use app\common\model\store\Shop as ShopModel; use app\api\service\sharp\Active as ActiveService; use app\common\enum\Setting as SettingEnum; @@ -23,6 +24,7 @@ use app\common\service\Goods as GoodsService; use app\api\model\sharp\Active as SharpActiveModel; use app\api\model\sharp\ActiveTime as ActiveTimeModel; use app\api\controller\sharp\Goods as miaosha; +use app\store\model\goods\GoodsPrice as GoodsPriceModel; /** * 商品服务类 @@ -52,19 +54,19 @@ class Goods extends GoodsService switch (request()->get('type')) { case 1: - $data['imgurl']= 'https://www.saas.njrenzhou.com/uploads/10001/20240131/bdc5f17f3ff8c53ce0853177bc4f1917.png'; + $data['imgurl'] = 'https://www.saas.njrenzhou.com/uploads/10001/20240131/bdc5f17f3ff8c53ce0853177bc4f1917.png'; return $data; break; case 2: - $data['imgurl']= 'https://www.saas.njrenzhou.com/uploads/10001/20240131/e8e10653875e779bc72dbee65b8072c0.png'; + $data['imgurl'] = 'https://www.saas.njrenzhou.com/uploads/10001/20240131/e8e10653875e779bc72dbee65b8072c0.png'; return $data; break; case 3: - $data['imgurl']= 'https://www.saas.njrenzhou.com/uploads/10001/20240131/5c4ec6ffeb23223936295e290dc3d1f9.png'; + $data['imgurl'] = 'https://www.saas.njrenzhou.com/uploads/10001/20240131/5c4ec6ffeb23223936295e290dc3d1f9.png'; return $data; break; case 4: - $data['imgurl']= [ + $data['imgurl'] = [ 'https://www.saas.njrenzhou.com/uploads/10001/20240131/5c4ec6ffeb23223936295e290dc3d1f9.png', ]; return $data; @@ -278,7 +280,7 @@ class Goods extends GoodsService { $data = []; foreach ($goodsList as $goods) { - $data[] = [ + $temp = [ 'goods_id' => $goods['goods_id'], 'goods_name' => $goods['goods_name'], 'selling_point' => $goods['selling_point'], @@ -290,6 +292,25 @@ class Goods extends GoodsService 'goods_sales' => $goods['goods_sales'], 'remaizhishu' => $goods['remaizhishu'], ]; + if (UserService::isLogin()) { + $catService = new \app\store\model\GoodsCategoryRel(); + $catIds = $catService->where(['goods_id' => $goods['goods_id']])->column('category_id'); + $price_list_plus = $price_list_dealer = []; + foreach ($catIds as $k => $v) { + $price_list_plus[] = GoodsPriceModel::getDiscountPrice($v, 1, $goods['goods_price_min']); + $price_list_dealer[] = GoodsPriceModel::getDiscountPrice($v, 2, $goods['goods_price_min']); + } + //价格判断 + if (UserService::isstore()) { + $temp['goods_price_min_plus'] = min($price_list_plus); + $temp['goods_price_min_dealer'] = min($price_list_dealer); + } elseif (UserService::isPlusMember()) { + $temp['goods_price_min_plus'] = min($price_list_plus); + } elseif (UserService::isDealerMember()) { + $temp['goods_price_min_dealer'] = min($price_list_dealer); + } + } + $data[] = $temp; } return $data; } diff --git a/app/command/test.php b/app/command/test.php new file mode 100644 index 00000000..9406e9d4 --- /dev/null +++ b/app/command/test.php @@ -0,0 +1,28 @@ +setName('test') + ->setDescription('测试demo'); + } + + protected function execute(Input $input, Output $output) + { + echo date('Y-m-d H:i:s') . '完成'; + } + + +} diff --git a/app/common/model/Category.php b/app/common/model/Category.php index dc09acaf..861d47fa 100644 --- a/app/common/model/Category.php +++ b/app/common/model/Category.php @@ -14,6 +14,7 @@ namespace app\common\model; use cores\BaseModel; use think\model\relation\HasOne; +use think\model\relation\HasMany; /** * 商品分类模型 @@ -37,6 +38,11 @@ class Category extends BaseModel return $this->hasOne('UploadFile', 'file_id', 'image_id'); } + public function price(): HasMany + { + $model = "app\\common\\model\\goods\\GoodsPrice"; + return $this->HasMany($model, 'cat_id', 'category_id'); + } /** * 分类详情 * @param int|array $where diff --git a/app/common/model/Goods.php b/app/common/model/Goods.php index 77689a0c..5afd7112 100644 --- a/app/common/model/Goods.php +++ b/app/common/model/Goods.php @@ -13,18 +13,18 @@ declare (strict_types=1); namespace app\common\model; +use app\common\enum\goods\Status as GoodsStatusEnum; +use app\common\enum\order\DeliveryType as DeliveryTypeEnum; +use app\common\library\helper; +use app\store\model\GoodsCategoryRel as GoodsCategoryRelModel; use cores\BaseModel; use think\db\BaseQuery; use think\db\exception\DbException; +use think\model\Collection; use think\model\relation\BelongsTo; use think\model\relation\HasMany; -use think\Paginator; -use think\model\Collection; use think\model\relation\HasOne; -use app\store\model\GoodsCategoryRel as GoodsCategoryRelModel; -use app\common\library\helper; -use app\common\enum\goods\Status as GoodsStatusEnum; -use app\common\enum\order\DeliveryType as DeliveryTypeEnum; +use think\Paginator; /** * 商品模型 @@ -359,11 +359,23 @@ class Goods extends BaseModel $goodsInfo['goods_image'] = current($goodsInfo['goods_images'])['preview_url']; // 商品销量(实际显示=初始虚拟销量+实际销量) $goodsInfo['goods_sales'] = $goodsInfo['sales_initial'] + $goodsInfo['sales_actual']; +// //商品价格判断 +// if (UserService::isLogin()) { +// if (UserService::isStore()) {//店主 +// $goodsInfo['goods_price_min_plus'] = 0; +// $goodsInfo['goods_price_min_dealer'] = 0; +// } elseif (UserService::isDealerMember()) { //分销商 +// $goodsInfo['goods_price_min_dealer'] = 0; +// } elseif (UserService::isPlusMember()) {//升级会员 +// $goodsInfo['goods_price_min_plus'] = 0; +// } +// } // 回调函数 is_callable($callback) && call_user_func($callback, $goodsInfo); return $goodsInfo; } + /** * 根据商品id集获取商品列表 * @param array $goodsIds diff --git a/app/common/model/UploadFile.php b/app/common/model/UploadFile.php index 940c3ea0..7a2f1be5 100644 --- a/app/common/model/UploadFile.php +++ b/app/common/model/UploadFile.php @@ -12,10 +12,10 @@ declare (strict_types=1); namespace app\common\model; +use app\common\enum\file\FileType as FileTypeEnum; +use app\common\enum\file\Storage as StorageEnum; use cores\BaseModel; use think\model\relation\BelongsTo; -use app\common\enum\file\Storage as StorageEnum; -use app\common\enum\file\FileType as FileTypeEnum; /** * 文件库模型 @@ -73,6 +73,8 @@ class UploadFile extends BaseModel // 存储方式本地:拼接当前域名 if ($data['storage'] === StorageEnum::LOCAL) { $data['domain'] = rtrim(uploads_url(), '/'); + } elseif ($data['storage'] === StorageEnum::EXTERNAL) { + return "{$data['file_path']}"; } return "{$data['domain']}/{$data['file_path']}"; } diff --git a/app/common/model/goods/GoodsPrice.php b/app/common/model/goods/GoodsPrice.php new file mode 100644 index 00000000..8ea60710 --- /dev/null +++ b/app/common/model/goods/GoodsPrice.php @@ -0,0 +1,48 @@ + +// +---------------------------------------------------------------------- +declare (strict_types=1); + +namespace app\common\model\goods; + +use cores\BaseModel; +use think\model\relation\HasOne; + +/** + * 商品服务与承诺模型 + * Class Service + */ +class GoodsPrice extends BaseModel +{ + // 定义表名 + protected $name = 'goods_price'; + + // 定义主键 + protected $pk = 'id'; + + /** + * 帮助详情 + * @param int $helpId + * @return static|array|null + */ + public static function detail(int $helpId) + { + return self::get($helpId); + } + /** + * 分类图片 + * @return HasOne + */ + public function cat(): HasOne + { + $model = "app\\common\\model\\Category"; + return $this->hasOne($model, 'category_id', 'cat_id'); + } +} diff --git a/app/store/controller/Server.php b/app/store/controller/Server.php index 066d3b4e..57a477fe 100644 --- a/app/store/controller/Server.php +++ b/app/store/controller/Server.php @@ -212,7 +212,7 @@ class Server extends Controller $order_status = intval($this->request->post('order_status')); $where = []; if (!empty($server_name)) { - $where[] = ['a.server_name', 'like', `%$server_name%`]; + $where[] = ['a.server_name', 'like', "%$server_name%"]; } if (!empty($order_no)) { $where[] = ['a.order_no', '=', $order_no]; @@ -229,7 +229,9 @@ class Server extends Controller $where[] = ['b.nick_name', 'like', "%$server_name%"]; } $list = $model->getList($where); - return $this->renderSuccess(compact('list')); + $data['list'] = $list->items(); + $data['total'] = $list->total(); + return $this->renderSuccess($data); } /** diff --git a/app/store/model/goods/GoodsPrice.php b/app/store/model/goods/GoodsPrice.php new file mode 100644 index 00000000..910ac2bf --- /dev/null +++ b/app/store/model/goods/GoodsPrice.php @@ -0,0 +1,172 @@ + +// +---------------------------------------------------------------------- +declare (strict_types=1); + +namespace app\store\model\goods; + +use app\common\library\helper; +use think\Paginator; +use think\Collection; +use app\common\model\goods\GoodsPrice as GoodsPriceModel; +use app\common\model\Category as CategoryModel; + +/** + * 商品价格配比 + * Class Service + */ +class GoodsPrice extends GoodsPriceModel +{ + /** + * 获取全部记录 + * @param array $param + * @return array|Collection + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getAll($params) + { + $catFids = CategoryModel::where(['parent_id' => 0])->column('category_id'); + $catList = CategoryModel::with(['price'])->whereIn('parent_id', $catFids)->select()->toArray(); + $all = []; + foreach ($catList as $k => $v) { + $temp = []; + if (!empty($v['price'])) { + foreach ($v['price'] as $pk => $pv) { + if (!empty($params['type'])) { + if ($pv['type'] == $params['type']) { + $temp[] = $pv; + } + } else { + if ($pv['type'] == 1) { + $temp[] = $pv; + } + } + } + } + $all[] = [ + 'category_id' => $v['category_id'], + 'name' => $v['name'], + 'price' => $temp + ]; + } + return $all; + } + + + /** + * 新增记录 + * @param array $data + * @return bool|false + */ + public function add(array $data): bool + { + if (empty($data['type']) || empty($data['max_price']) || empty($data['cat_id']) || empty($data['markup_rate'])) { + $this->error = "请补全信息"; + return false; + } + //校验是否有冲突的区间 + $catList = $this->where(['cat_id' => $data['cat_id'], 'type' => $data['type']])->select(); + if (!empty($catList)) { + + foreach ($catList as $k => $v) { + if ($data['min_price'] >= $v->min_price && $data['min_price'] <= $v->max_price) { + $this->error = "该分类价格区间冲突,请重新设置价格"; + return false; + } + if ($data['max_price'] <= $v->max_price && $data['max_price'] >= $v->min_price) { + $this->error = "该分类价格区间冲突,请重新设置价格"; + return false; + } + } + } + $data['profit_min'] = round($data['min_price'] * $data['markup_rate'] / 100, 2); + $data['profit_max'] = round($data['max_price'] * $data['markup_rate'] / 100, 2); + $data['store_id'] = self::$storeId; + return $this->save($data); + } + + /** + * 更新记录 + * @param array $data + * @return bool + */ + public function edit(array $data): bool + { + if (empty($data['type']) || empty($data['max_price']) || empty($data['cat_id']) || empty($data['markup_rate']) || empty($data['id'])) { + $this->error = "请补全信息"; + return false; + } + $detail = $this->where('id', '=', $data['id'])->find(); + if ($detail->isEmpty()) { + $this->error = "异常数据"; + return false; + } + //校验是否有冲突的区间 + $catList = $this->where(['cat_id' => $data['cat_id'], 'type' => $data['type']])->where('id', '<>', $data['id'])->select(); + if (!empty($catList)) { + foreach ($catList as $k => $v) { + if ($data['min_price'] >= $v->min_price && $data['min_price'] <= $v->max_price) { + $this->error = "该分类价格区间冲突,请重新设置价格"; + return false; + } + if ($data['max_price'] <= $v->max_price && $data['max_price'] >= $v->min_price) { + $this->error = "该分类价格区间冲突,请重新设置价格"; + return false; + } + } + } + $data['profit_min'] = round($data['min_price'] * $data['markup_rate'] / 100, 2); + $data['profit_max'] = round($data['max_price'] * $data['markup_rate'] / 100, 2); + return $detail->save($data) !== false; + } + + /** + * 删除记录(软删除) + * @return bool + * @throws \Exception + */ + public function del($data): bool + { + // 判断该服务是否被商品引用 + $detail = $this->where('id', '=', $data['id'])->find(); + if ($detail->isEmpty()) { + $this->error = "异常数据"; + return false; + } + return $detail->delete() !== false; + } + + + /** + * 获取和计算折扣后的价格 + * @param $catId + * @param $type + * @param $originalPrice + * @return string + */ + public static function getDiscountPrice($catId, $type = 1, $originalPrice): string + { + $info = self::where(['cat_id' => $catId, 'type' => $type]) + ->where('min_price', '<=', $originalPrice) + ->order('min_price desc') + ->find(); + //没有配置返回原价 + if (!$info) { + return $originalPrice; + } + // 使用高精度方法计算等级折扣; + $discountPrice = helper::bcmul($originalPrice, $info->markup_rate / 100, 2); + //取优惠后的价格 + $lastPrice = bcsub($originalPrice, $discountPrice, 2); + return helper::number2($lastPrice, true); + } +} diff --git a/config/console.php b/config/console.php index f6008bfe..dbaa6db4 100644 --- a/config/console.php +++ b/config/console.php @@ -7,5 +7,7 @@ return [ 'commands' => [ // 定时任务 'timer' => \app\timer\command\Timer::class, + //test脚本 + 'test' => 'app\command\test', ], ];