From 9de81664ba6e4e62231299b1e581af4eb4dcf487 Mon Sep 17 00:00:00 2001 From: Anyon Date: Tue, 8 Sep 2020 16:28:07 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=95=86=E5=93=81=E7=AE=A1?= =?UTF-8?q?=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/data/controller/ShopGoods.php | 191 ++++++++++++ app/data/service/GoodsService.php | 46 ++- app/data/view/shop_goods/form.html | 327 ++++++++++++++++++++- app/data/view/shop_goods/form_style.html | 94 ++++++ app/data/view/shop_goods/index.html | 149 +++++++++- app/data/view/shop_goods/index_search.html | 41 +++ app/data/view/shop_goods/select.html | 58 ++++ app/data/view/shop_goods/stock.html | 66 +++++ app/wechat/controller/api/Test.php | 12 +- 9 files changed, 958 insertions(+), 26 deletions(-) create mode 100644 app/data/view/shop_goods/form_style.html create mode 100644 app/data/view/shop_goods/index_search.html create mode 100644 app/data/view/shop_goods/select.html create mode 100644 app/data/view/shop_goods/stock.html diff --git a/app/data/controller/ShopGoods.php b/app/data/controller/ShopGoods.php index 7622c5396..d8b13c6ec 100644 --- a/app/data/controller/ShopGoods.php +++ b/app/data/controller/ShopGoods.php @@ -2,7 +2,10 @@ namespace app\data\controller; +use app\data\service\GoodsService; use think\admin\Controller; +use think\admin\extend\CodeExtend; +use think\admin\extend\DataExtend; /** * 商品数据管理 @@ -17,6 +20,194 @@ class ShopGoods extends Controller */ private $table = 'ShopGoods'; + /** + * 商品数据管理 + * @auth true + * @menu true + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function index() + { + $this->title = '商品数据管理'; + $query = $this->_query($this->table); + $query->like('name')->equal('status,cate'); + // 加载对应数据 + $this->type = $this->request->get('type', 'index'); + if ($this->type === 'index') $query->where(['deleted' => 0]); + elseif ($this->type === 'recycle') $query->where(['deleted' => 1]); + else $this->error("无法加载 {$this->type} 数据列表!"); + // 列表排序并显示 + $query->order('sort desc,id desc')->page(); + } + /** + * 商品选择器 + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function select() + { + $query = $this->_query($this->table)->equal('status,cate')->like('name'); + $query->where(['deleted' => '0'])->order('sort desc,id desc')->page(); + } + + /** + * 数据列表处理 + * @param array $data + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + protected function _page_filter(&$data) + { + $query = $this->app->db->name('ShopGoodsCate'); + $query->where(['deleted' => 0, 'status' => 1])->order('sort desc,id desc'); + $this->clist = DataExtend::arr2table($query->select()->toArray()); + foreach ($data as &$vo) { + [$vo['list'], $vo['cate']] = [[], []]; + foreach ($this->clist as $cate) if ($cate['id'] === $vo['cate_id']) $vo['cate'] = $cate; + } + } + + /** + * 商品库存入库 + * @auth true + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function stock() + { + if ($this->request->isGet()) { + $code = $this->request->get('code'); + $goods = $this->app->db->name('ShopGoods')->where(['code' => $code])->find(); + empty($goods) && $this->error('无效的商品信息,请稍候再试!'); + $map = ['goods_code' => $code, 'status' => 1]; + $goods['list'] = $this->app->db->name('ShopGoodsItem')->where($map)->select()->toArray(); + $this->fetch('', ['vo' => $goods]); + } else { + [$post, $data] = [$this->request->post(), []]; + if (isset($post['id']) && isset($post['goods_code']) && is_array($post['goods_code'])) { + foreach (array_keys($post['goods_id']) as $key) if ($post['goods_number'][$key] > 0) array_push($data, [ + 'goods_code' => $post['goods_code'][$key], + 'goods_spec' => $post['goods_spec'][$key], + 'stock_total' => $post['goods_number'][$key], + ]); + if (!empty($data)) { + $this->app->db->name('ShopGoodsStock')->insertAll($data); + GoodsService::instance()->syncStock($post['code']); + $this->success('商品信息入库成功!'); + } + } + $this->error('没有需要商品入库的数据!'); + } + } + + /** + * 添加商品信息 + * @auth true + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function add() + { + $this->title = '添加商品信息'; + $this->isAddMode = '1'; + $this->_form($this->table, 'form'); + } + + /** + * 编辑商品信息 + * @auth true + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function edit() + { + $this->title = '编辑商品信息'; + $this->isAddMode = '0'; + $this->_form($this->table, 'form'); + } + + /** + * 表单数据处理 + * @param array $data + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + protected function _form_filter(&$data) + { + if (empty($data['code'])) { + $data['code'] = CodeExtend::uniqidNumber(12, 'G'); + } + if ($this->request->isGet()) { + // 商品分类数据 + $this->cates = GoodsService::instance()->getCateList('arr2table'); + // 商品默认规格 + $fields = 'goods_sku,goods_code,goods_spec,price_selling,price_market,number_virtual,number_express express,status'; + $this->items = $this->app->db->name('ShopGoodsItem')->where(['goods_code' => $data['code']])->column($fields, 'goods_spec'); + } elseif ($this->request->isPost()) { + if (empty($data['cover'])) $this->error('商品图片不能为空!'); + if (empty($data['slider'])) $this->error('轮播图不能为空!'); + // 商品规格保存 + [$specs, $count] = [json_decode($data['lists'], true), 0]; + foreach ($specs as $item) { + $count += intval($item[0]['status']); + if (empty($data['price_market'])) $data['price_market'] = $item[0]['market']; + } + if (empty($count)) $this->error('无可用的商品规格!'); + $this->app->db->name('ShopGoodsItem')->where(['goods_code' => $data['code']])->update(['status' => '0']); + foreach ($specs as $item) data_save('ShopGoodsItem', [ + 'goods_sku' => $item[0]['sku'], + 'goods_code' => $item[0]['code'], + 'goods_spec' => $item[0]['spec'], + 'price_market' => $item[0]['market'], + 'price_selling' => $item[0]['selling'], + 'number_virtual' => $item[0]['virtual'], + 'number_express' => $item[0]['express'], + 'status' => $item[0]['status'] ? 1 : 0, + ], 'goods_spec', ['goods_id' => $data['id']]); + } + } + + /** + * 表单结果处理 + * @param boolean $result + */ + protected function _form_result($result) + { + if ($result && $this->request->isPost()) { + $this->success('商品编辑成功!', 'javascript:history.back()'); + } + } + + /** + * 上下架商品管理 + * @auth true + * @throws \think\db\exception\DbException + */ + public function state() + { + $this->_save($this->table, $this->_vali([ + 'status.in:0,1' => '状态值范围异常!', + 'status.require' => '状态值不能为空!', + ])); + } + + /** + * 删除商品信息 + * @auth true + * @throws \think\db\exception\DbException + */ + public function remove() + { + $this->_delete($this->table); + } } \ No newline at end of file diff --git a/app/data/service/GoodsService.php b/app/data/service/GoodsService.php index 978e61d88..01d0063a9 100644 --- a/app/data/service/GoodsService.php +++ b/app/data/service/GoodsService.php @@ -13,20 +13,62 @@ use think\admin\Service; class GoodsService extends Service { + /** + * 更新商品库存数据 + * @param string $code + * @return bool + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function syncStock($code) + { + // 商品入库统计 + $query = $this->app->db->name('ShopGoodsStock'); + $query->field('goods_code,goods_spec,ifnull(sum(number_stock),0) number_stock'); + $stockList = $query->where(['code' => $code])->group('goods_id,goods_spec')->select()->toArray(); + // 商品销量统计 + $query = $this->app->db->table('shop_order a')->field('b.goods_code,b.goods_spec,ifnull(sum(b.stock_sales),0) stock_sales'); + $query->leftJoin('shop_order_item b', 'a.order_no=b.order_no')->where([['b.code', '=', $code], ['a.status', 'in', [1, 2, 3, 4, 5]]]); + $salesList = $query->group('b.goods_id,b.goods_spec')->select()->toArray(); + // 组装更新数据 + $dataList = []; + foreach (array_merge($stockList, $salesList) as $vo) { + $key = "{$vo['goods_code']}@@{$vo['goods_spec']}"; + $dataList[$key] = isset($dataList[$key]) ? array_merge($dataList[$key], $vo) : $vo; + if (empty($dataList[$key]['stock_sales'])) $dataList[$key]['stock_sales'] = 0; + if (empty($dataList[$key]['stock_total'])) $dataList[$key]['stock_total'] = 0; + } + unset($salesList, $stockList); + // 更新商品规格销量及库存 + foreach ($dataList as $vo) { + $map = ['goods_code' => $code, 'goods_spec' => $vo['goods_spec']]; + $set = ['stock_total' => $vo['stock_total'], 'stock_sales' => $vo['stock_sales']]; + $this->app->db->name('ShopGoodsItem')->where($map)->update($set); + } + // 更新商品主体销量及库存 + $this->app->db->name('ShopGoods')->where(['code' => $code])->update([ + 'stock_total' => intval(array_sum(array_column($dataList, 'stock_total'))), + 'stock_sales' => intval(array_sum(array_column($dataList, 'stock_sales'))), + ]); + return true; + } + /** * 获取分类数据 + * @param string $type 数据类型 * @return array * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\DbException * @throws \think\db\exception\ModelNotFoundException */ - public function getCateList(): array + public function getCateList($type = 'arr2tree'): array { $map = ['deleted' => 0, 'status' => 1]; $query = $this->app->db->name('ShopGoodsCate'); $query->where($map)->order('sort desc,id desc'); $query->withoutField('sort,status,deleted,create_at'); - return DataExtend::arr2tree($query->select()->toArray()); + return DataExtend::$type($query->select()->toArray()); } /** diff --git a/app/data/view/shop_goods/form.html b/app/data/view/shop_goods/form.html index 566549bdf..22280f47e 100644 --- a/app/data/view/shop_goods/form.html +++ b/app/data/view/shop_goods/form.html @@ -1,10 +1,319 @@ - - - - - Title - - +{extend name="../../admin/view/main"} - - \ No newline at end of file +{block name="content"} + +{include file='shop_goods/form_style'} + +
+ +
+ + + + + +
+ 商品图片及轮播展示图片 + + + + + + + + + + + +
LOGO展示图片
+ + + + + +
+
+
+ +
+ 入会礼包配置 +
+ {foreach [0=>'非入会礼包,购买后不会影响等级',1=>'入会员礼包,购买后升级会员级别'] as $k=>$v} + {if (isset($vo.vip_mod) and $vo.vip_mod eq $k) or (empty($vo.vip_mod) and $k eq 0)} + + {else} + + {/if}{/foreach} +
+
+ +
+ 商品限购设置 + +
+
+ +
+ 商品规格及商品SKU绑定(规格填写后不允许再次修改) + + 增加分组 + + + + + + + + + + + + + + + + + + + + + + + +
商品SKU 市场价格 销售价格 虚拟销量 快递计件 销售状态
+ + + + + + + + + + + +
+

请注意商品SKU与商品条码尽量不要重复,也不能产生订单后再修改!

+ + +
+ +
+ 商品富文本内容 + +
+ +
+ {notempty name='vo.id'}{/notempty} + + +
+ +
+
+{/block} + +{block name='script'} + + + +{/block} \ No newline at end of file diff --git a/app/data/view/shop_goods/form_style.html b/app/data/view/shop_goods/form_style.html new file mode 100644 index 000000000..fde67f074 --- /dev/null +++ b/app/data/view/shop_goods/form_style.html @@ -0,0 +1,94 @@ + \ No newline at end of file diff --git a/app/data/view/shop_goods/index.html b/app/data/view/shop_goods/index.html index 566549bdf..5f122cb66 100644 --- a/app/data/view/shop_goods/index.html +++ b/app/data/view/shop_goods/index.html @@ -1,10 +1,141 @@ - - - - - Title - - +{extend name="../../admin/view/main"} - - \ No newline at end of file +{block name="button"} + +{if auth("add")} + +{/if} + +{if $type eq 'index'} + + + +{else} + + + +{/if} + +{/block} + +{block name="content"} +
+ +
+ {include file='shop_goods/index_search'} + + {notempty name='list'} + + + + + + + + + + + {/notempty} + + {foreach $list as $key=>$vo} + + + + + + + + + {/foreach} + +
+ + + + 商品信息商品状态
+ + + + + {notempty name='vo.cover'} + img + {/notempty} +
+ 商品编号:{$vo.code|default='--'} + {if auth("state") and $vo.hot_state eq 1} + 热推 + {elseif auth('state')} + 热推 + {/if} + 复制链接 +
+ 商品名称:{$vo.name|default='--'}
+
+
+ 入会礼包:{if empty($vo.vip_mod)}{else} [ {$vo.vip_level|default='0'} ]{/if}
+ 所属分类:{$vo.cate.title|default='--'}
+
+ 销售状态:{eq name='vo.status' value='0'}已下架{else}销售中{/eq}
+ 剩余库存:{$vo.number_stock-$vo.number_sales} 件 ( 已售 {$vo.number_sales} 件 )
+
+ + {if auth("edit")} + 编 辑 + {else} + 编 辑 + {/if} + + {if $type eq 'index'} + + {if isset($vo.status) and $vo.status eq 1} + + 下 架 + + 下 架 + + {else} + + 上 架 + + 上 架 + + {/if} + + {if auth("stock")} + 入 库 + {else} + 入 库 + {/if} + + + {if auth("state")} + 删 除 + {/if} + + {else} + + {if auth("state")} + 恢 复 + {/if} + + {/if} + +
+ + {empty name='list'}没有记录哦{else}{$pagehtml|raw|default=''}{/empty} + +
+
+{/block} + +{block name='script'} + +{/block} \ No newline at end of file diff --git a/app/data/view/shop_goods/index_search.html b/app/data/view/shop_goods/index_search.html new file mode 100644 index 000000000..8c281aaf7 --- /dev/null +++ b/app/data/view/shop_goods/index_search.html @@ -0,0 +1,41 @@ +
+ 条件搜索 + +
\ No newline at end of file diff --git a/app/data/view/shop_goods/select.html b/app/data/view/shop_goods/select.html new file mode 100644 index 000000000..405519949 --- /dev/null +++ b/app/data/view/shop_goods/select.html @@ -0,0 +1,58 @@ +{extend name="../../admin/view/full"} + +{block name="content"} +
+ {include file='shop_goods/index_search'} + + {notempty name='list'} + + + + + + + + + {/notempty} + + {foreach $list as $key=>$vo} + + + + + + + {/foreach} + +
商品信息商品状态
+ {notempty name='vo.logo'} + img + {/notempty} +
+ 商品编号:{$vo.id|default='--'}
+ 商品名称:{$vo.title|default='--'}
+
+
+ 入会礼包:{$vo.vip_mod?"是":"否"}
+ 所属分类:{$vo.cate.title|default='--'}
+
+ 剩余库存:{$vo.number_stock|default='0'} 件
+ 销售状态:{eq name='vo.status' value='0'}已下架{else}销售中{/eq}
+
+ 选择商品 +
+ + {empty name='list'}没有记录哦{else}{$pagehtml|raw|default=''}{/empty} + +
+{/block} + +{block name='script'} + +{/block} diff --git a/app/data/view/shop_goods/stock.html b/app/data/view/shop_goods/stock.html new file mode 100644 index 000000000..0b286e60b --- /dev/null +++ b/app/data/view/shop_goods/stock.html @@ -0,0 +1,66 @@ +
+ +
+ +
+ 商品名称 + Goods name +
{$vo.title}
+
+ +
+
+ 规格数据 + Specification data + + + + + + + + + + + + + {foreach $vo.list as $goods} + + + + + + + + + {/foreach} + +
商品规格销售价格库存统计总销统计库存剩余入库数量
+ + + + + + + + + + + + + +
+
+
+ +
+ +
+ {notempty name='vo.id'}{/notempty} + +
+ + +
+ +
diff --git a/app/wechat/controller/api/Test.php b/app/wechat/controller/api/Test.php index a3091e203..5d5b85f58 100644 --- a/app/wechat/controller/api/Test.php +++ b/app/wechat/controller/api/Test.php @@ -36,7 +36,7 @@ class Test extends Controller */ public function jsapi_qrc() { - $this->url = url('wechat/api.test/jsapi', [], false, true); + $this->url = sysuri('wechat/api.test/jsapi', [], false, true); return $this->showQrc($this->url); } @@ -49,7 +49,7 @@ class Test extends Controller */ public function oauth_qrc() { - $this->url = url('wechat/api.test/oauth', [], false, true); + $this->url = sysuri('wechat/api.test/oauth', [], false, true); return $this->showQrc($this->url); } @@ -62,7 +62,7 @@ class Test extends Controller */ public function jssdk_qrc() { - $this->url = url('wechat/api.test/jssdk', [], false, true); + $this->url = sysuri('wechat/api.test/jssdk', [], false, true); return $this->showQrc($this->url); } @@ -94,7 +94,7 @@ class Test extends Controller 'body' => '测试商品', 'total_fee' => '1', 'trade_type' => 'NATIVE', - 'notify_url' => url('wechat/api.test/notify', [], false, true)->build(), + 'notify_url' => sysuri('wechat/api.test/notify', [], false, true), 'out_trade_no' => CodeExtend::uniqidNumber(18), 'spbill_create_ip' => $this->request->ip(), ]); @@ -152,7 +152,7 @@ class Test extends Controller 'body' => "测试商品,产品ID:{$notify['product_id']}", 'total_fee' => '1', 'trade_type' => 'NATIVE', - 'notify_url' => url('wechat/api.test/notify', [], false, true)->build(), + 'notify_url' => sysuri('wechat/api.test/notify', [], false, true), 'out_trade_no' => CodeExtend::uniqidDate(18), 'spbill_create_ip' => $this->request->ip(), ]; @@ -197,7 +197,7 @@ class Test extends Controller 'openid' => $user['openid'], 'total_fee' => '1', 'trade_type' => 'JSAPI', - 'notify_url' => url('wechat/api.test/notify', [], false, true), + 'notify_url' => sysuri('wechat/api.test/notify', [], false, true), 'out_trade_no' => CodeExtend::uniqidDate(18), 'spbill_create_ip' => $this->request->ip(), ]);