diff --git a/niucloud/addon/shop/Addon.php b/niucloud/addon/shop/Addon.php
new file mode 100644
index 000000000..eefa879cb
--- /dev/null
+++ b/niucloud/addon/shop/Addon.php
@@ -0,0 +1,1273 @@
+where([
+ [ 'name', '=', '商城素材' ]
+ ])->field('id')->findOrEmpty()->toArray();
+
+ if (!empty($category_info)) {
+ $category_id = $category_info[ 'id' ];
+ } else {
+ $attachment_category = $category_model->create([
+ 'pid' => 0,
+ 'type' => 'image',
+ 'name' => '商城素材',
+ 'sort' => 1
+ ]);
+ $category_id = $attachment_category->id;
+ }
+
+ $attachment_model = new SysAttachment();
+ $attachment_list = [
+ [
+ 'name' => time() . $category_id . 'banner1.jpg', // 附件名称
+ 'real_name' => '轮播素材01', // 原始文件名
+ 'path' => 'addon/shop/attachment/banner1.jpg', // 完整地址
+ 'url' => 'addon/shop/attachment/banner1.jpg', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '84097', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ],
+ [
+ 'name' => time() . $category_id . 'banner2.jpg', // 附件名称
+ 'real_name' => '轮播素材02', // 原始文件名
+ 'path' => 'addon/shop/attachment/banner2.jpg', // 完整地址
+ 'url' => 'addon/shop/attachment/banner2.jpg', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '54862', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ],
+ [
+ 'name' => time() . $category_id . 'banner3.jpg', // 附件名称
+ 'real_name' => '轮播素材03', // 原始文件名
+ 'path' => 'addon/shop/attachment/banner3.jpg', // 完整地址
+ 'url' => 'addon/shop/attachment/banner3.jpg', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '78247', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ],
+ [
+ 'name' => time() . $category_id . 'banner4.png', // 附件名称
+ 'real_name' => '轮播素材04', // 原始文件名
+ 'path' => 'addon/shop/attachment/banner4.png', // 完整地址
+ 'url' => 'addon/shop/attachment/banner4.png', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '95324', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ],
+ [
+ 'name' => time() . $category_id . 'banner5.png', // 附件名称
+ 'real_name' => '轮播素材05', // 原始文件名
+ 'path' => 'addon/shop/attachment/banner5.png', // 完整地址
+ 'url' => 'addon/shop/attachment/banner5.png', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '97570', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ],
+ [
+ 'name' => time() . $category_id . 'logo.png', // 附件名称
+ 'real_name' => '生活圈', // 原始文件名
+ 'path' => 'addon/shop/attachment/logo.png', // 完整地址
+ 'url' => 'addon/shop/attachment/logo.png', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '1517', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ],
+ [
+ 'name' => time() . $category_id . 'nav_coupon.png', // 附件名称
+ 'real_name' => '优惠券', // 原始文件名
+ 'path' => 'addon/shop/attachment/nav_coupon.png', // 完整地址
+ 'url' => 'addon/shop/attachment/nav_coupon.png', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '30937', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ],
+ [
+ 'name' => time() . $category_id . 'nav_discount.png', // 附件名称
+ 'real_name' => '限时折扣', // 原始文件名
+ 'path' => 'addon/shop/attachment/nav_discount.png', // 完整地址
+ 'url' => 'addon/shop/attachment/nav_discount.png', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '33870', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ],
+ [
+ 'name' => time() . $category_id . 'nav_fenxiao.png', // 附件名称
+ 'real_name' => '分销管理', // 原始文件名
+ 'path' => 'addon/shop/attachment/nav_fenxiao.png', // 完整地址
+ 'url' => 'addon/shop/attachment/nav_fenxiao.png', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '24026', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ],
+ [
+ 'name' => time() . $category_id . 'nav_fenxiao_zone.png', // 附件名称
+ 'real_name' => '分销专区', // 原始文件名
+ 'path' => 'addon/shop/attachment/nav_fenxiao_zone.png', // 完整地址
+ 'url' => 'addon/shop/attachment/nav_fenxiao_zone.png', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '33429', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ],
+ [
+ 'name' => time() . $category_id . 'nav_giftcard.png', // 附件名称
+ 'real_name' => '礼品卡', // 原始文件名
+ 'path' => 'addon/shop/attachment/nav_giftcard.png', // 完整地址
+ 'url' => 'addon/shop/attachment/nav_giftcard.png', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '29399', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ],
+ [
+ 'name' => time() . $category_id . 'nav_my_address.png', // 附件名称
+ 'real_name' => '收货地址', // 原始文件名
+ 'path' => 'addon/shop/attachment/nav_my_address.png', // 完整地址
+ 'url' => 'addon/shop/attachment/nav_my_address.png', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '25280', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ],
+ [
+ 'name' => time() . $category_id . 'nav_my_newcomer.png', // 附件名称
+ 'real_name' => '新人专享', // 原始文件名
+ 'path' => 'addon/shop/attachment/nav_my_newcomer.png', // 完整地址
+ 'url' => 'addon/shop/attachment/nav_my_newcomer.png', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '32123', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ],
+ [
+ 'name' => time() . $category_id . 'nav_news_info.png', // 附件名称
+ 'real_name' => '新闻资讯', // 原始文件名
+ 'path' => 'addon/shop/attachment/nav_news_info.png', // 完整地址
+ 'url' => 'addon/shop/attachment/nav_news_info.png', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '27934', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ],
+ [
+ 'name' => time() . $category_id . 'nav_point_index.png', // 附件名称
+ 'real_name' => '积分商城', // 原始文件名
+ 'path' => 'addon/shop/attachment/nav_point_index.png', // 完整地址
+ 'url' => 'addon/shop/attachment/nav_point_index.png', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '27946 ', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ],
+ [
+ 'name' => time() . $category_id . 'nav_sign_in.png', // 附件名称
+ 'real_name' => '签到', // 原始文件名
+ 'path' => 'addon/shop/attachment/nav_sign_in.png', // 完整地址
+ 'url' => 'addon/shop/attachment/nav_sign_in.png', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '33576', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ],
+ [
+ 'name' => time() . $category_id . 'notice.png', // 附件名称
+ 'real_name' => '新闻咨询', // 原始文件名
+ 'path' => 'addon/shop/attachment/notice.png', // 完整地址
+ 'url' => 'addon/shop/attachment/notice.png', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '3069', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ],
+ [
+ 'name' => time() . $category_id . 'picture_show_head_text2.png', // 附件名称
+ 'real_name' => '品牌特卖', // 原始文件名
+ 'path' => 'addon/shop/attachment/picture_show_head_text2.png', // 完整地址
+ 'url' => 'addon/shop/attachment/picture_show_head_text2.png', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '2825', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ],
+ [
+ 'name' => time() . $category_id . 'picture_show_head_text3.png', // 附件名称
+ 'real_name' => '官方补贴', // 原始文件名
+ 'path' => 'addon/shop/attachment/picture_show_head_text3.png', // 完整地址
+ 'url' => 'addon/shop/attachment/picture_show_head_text3.png', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '2549', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ],
+ [
+ 'name' => time() . $category_id . 'single_recommend_banner1.jpg', // 附件名称
+ 'real_name' => '精选推荐01', // 原始文件名
+ 'path' => 'addon/shop/attachment/single_recommend_banner1.jpg', // 完整地址
+ 'url' => 'addon/shop/attachment/single_recommend_banner1.jpg', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '71670', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ],
+ [
+ 'name' => time() . $category_id . 'single_recommend_banner2.jpg', // 附件名称
+ 'real_name' => '精选推荐02', // 原始文件名
+ 'path' => 'addon/shop/attachment/single_recommend_banner2.jpg', // 完整地址
+ 'url' => 'addon/shop/attachment/single_recommend_banner2.jpg', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '72948', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ],
+ [
+ 'name' => time() . $category_id . 'single_recommend_text1.png', // 附件名称
+ 'real_name' => '精选推荐', // 原始文件名
+ 'path' => 'addon/shop/attachment/single_recommend_text1.png', // 完整地址
+ 'url' => 'addon/shop/attachment/single_recommend_text1.png', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '3664', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ],
+ [
+ 'name' => time() . $category_id . 'my_cart.png', // 附件名称
+ 'real_name' => '购物车', // 原始文件名
+ 'path' => 'addon/shop/attachment/my_cart.png', // 完整地址
+ 'url' => 'addon/shop/attachment/my_cart.png', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '31921', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ],
+ [
+ 'name' => time() . $category_id . 'home_delivery.png', // 附件名称
+ 'real_name' => '送货上门', // 原始文件名
+ 'path' => 'addon/shop/attachment/home_delivery.png', // 完整地址
+ 'url' => 'addon/shop/attachment/home_delivery.png', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '30811', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ],
+ [
+ 'name' => time() . $category_id . 'nav_all_class.png', // 附件名称
+ 'real_name' => '全部分类', // 原始文件名
+ 'path' => 'addon/shop/attachment/nav_all_class.png', // 完整地址
+ 'url' => 'addon/shop/attachment/nav_all_class.png', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '25427', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ],
+ [
+ 'name' => time() . $category_id . 'nav_balance.png', // 附件名称
+ 'real_name' => '我的余额', // 原始文件名
+ 'path' => 'addon/shop/attachment/nav_balance.png', // 完整地址
+ 'url' => 'addon/shop/attachment/nav_balance.png', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '31437', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ],
+ [
+ 'name' => time() . $category_id . 'nav_collect.png', // 附件名称
+ 'real_name' => '我的收藏', // 原始文件名
+ 'path' => 'addon/shop/attachment/nav_collect.png', // 完整地址
+ 'url' => 'addon/shop/attachment/nav_collect.png', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '24533', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ],
+ [
+ 'name' => time() . $category_id . 'nav_coupon_01.png', // 附件名称
+ 'real_name' => '瓜分好券', // 原始文件名
+ 'path' => 'addon/shop/attachment/nav_coupon_01.png', // 完整地址
+ 'url' => 'addon/shop/attachment/nav_coupon_01.png', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '27068', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ],
+ [
+ 'name' => time() . $category_id . 'nav_leaderboard.png', // 附件名称
+ 'real_name' => '排行榜', // 原始文件名
+ 'path' => 'addon/shop/attachment/nav_leaderboard.png', // 完整地址
+ 'url' => 'addon/shop/attachment/nav_leaderboard.png', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '30098', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ],
+ [
+ 'name' => time() . $category_id . 'nav_member.png', // 附件名称
+ 'real_name' => '会员中心', // 原始文件名
+ 'path' => 'addon/shop/attachment/nav_member.png', // 完整地址
+ 'url' => 'addon/shop/attachment/nav_member.png', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '30793', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ],
+ [
+ 'name' => time() . $category_id . 'nav_point.png', // 附件名称
+ 'real_name' => '我的积分', // 原始文件名
+ 'path' => 'addon/shop/attachment/nav_point.png', // 完整地址
+ 'url' => 'addon/shop/attachment/nav_point.png', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '28112', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ],
+ [
+ 'name' => time() . $category_id . 'nav_shop.png', // 附件名称
+ 'real_name' => '线上商城', // 原始文件名
+ 'path' => 'addon/shop/attachment/nav_shop.png', // 完整地址
+ 'url' => 'addon/shop/attachment/nav_shop.png', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '23057', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ],
+ [
+ 'name' => time() . $category_id . 'nav_travel.png', // 附件名称
+ 'real_name' => '旅游出行', // 原始文件名
+ 'path' => 'addon/shop/attachment/nav_travel.png', // 完整地址
+ 'url' => 'addon/shop/attachment/nav_travel.png', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '27429', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ],
+ [
+ 'name' => time() . $category_id . 'nva_group_booking.png', // 附件名称
+ 'real_name' => '拼团返利', // 原始文件名
+ 'path' => 'addon/shop/attachment/nva_group_booking.png', // 完整地址
+ 'url' => 'addon/shop/attachment/nva_group_booking.png', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '30421', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ],
+ [
+ 'name' => time() . $category_id . 'head_01.png', // 附件名称
+ 'real_name' => '超值爆款', // 原始文件名
+ 'path' => 'addon/shop/attachment/head_01.png', // 完整地址
+ 'url' => 'addon/shop/attachment/head_01.png', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '3958', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ],
+ [
+ 'name' => time() . $category_id . 'head_02.png', // 附件名称
+ 'real_name' => '限时折扣', // 原始文件名
+ 'path' => 'addon/shop/attachment/head_02.png', // 完整地址
+ 'url' => 'addon/shop/attachment/head_02.png', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '2408', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ],
+ [
+ 'name' => time() . $category_id . 'head_03.png', // 附件名称
+ 'real_name' => '商品榜单', // 原始文件名
+ 'path' => 'addon/shop/attachment/head_03.png', // 完整地址
+ 'url' => 'addon/shop/attachment/head_03.png', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '2621', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ],
+ [
+ 'name' => time() . $category_id . 'image_ads_01.png', // 附件名称
+ 'real_name' => '商品低至五折', // 原始文件名
+ 'path' => 'addon/shop/attachment/image_ads_01.png', // 完整地址
+ 'url' => 'addon/shop/attachment/image_ads_01.png', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '44566', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ],
+ [
+ 'name' => time() . $category_id . 'active_cube_01.png', // 附件名称
+ 'real_name' => '魔方素材01', // 原始文件名
+ 'path' => 'addon/shop/attachment/active_cube_01.png', // 完整地址
+ 'url' => 'addon/shop/attachment/active_cube_01.png', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '36850', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ],
+ [
+ 'name' => time() . $category_id . 'active_cube_02.png', // 附件名称
+ 'real_name' => '魔方素材02', // 原始文件名
+ 'path' => 'addon/shop/attachment/active_cube_02.png', // 完整地址
+ 'url' => 'addon/shop/attachment/active_cube_02.png', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '26463', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ],
+ [
+ 'name' => time() . $category_id . 'active_cube_03.png', // 附件名称
+ 'real_name' => '魔方素材03', // 原始文件名
+ 'path' => 'addon/shop/attachment/active_cube_03.png', // 完整地址
+ 'url' => 'addon/shop/attachment/active_cube_03.png', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '29142', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ],
+ [
+ 'name' => time() . $category_id . 'active_cube_04.png', // 附件名称
+ 'real_name' => '魔方素材04', // 原始文件名
+ 'path' => 'addon/shop/attachment/active_cube_04.png', // 完整地址
+ 'url' => 'addon/shop/attachment/active_cube_04.png', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '26068', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ],
+ [
+ 'name' => time() . $category_id . 'active_cube_05.png', // 附件名称
+ 'real_name' => '魔方素材05', // 原始文件名
+ 'path' => 'addon/shop/attachment/active_cube_05.png', // 完整地址
+ 'url' => 'addon/shop/attachment/active_cube_05.png', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '107422', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ],
+ [
+ 'name' => time() . $category_id . 'active_cube_06.png', // 附件名称
+ 'real_name' => '魔方素材06', // 原始文件名
+ 'path' => 'addon/shop/attachment/active_cube_06.png', // 完整地址
+ 'url' => 'addon/shop/attachment/active_cube_06.png', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '130868', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ],
+ [
+ 'name' => time() . $category_id . 'active_cube_07.png', // 附件名称
+ 'real_name' => '魔方素材07', // 原始文件名
+ 'path' => 'addon/shop/attachment/active_cube_07.png', // 完整地址
+ 'url' => 'addon/shop/attachment/active_cube_07.png', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '129386', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ],
+ [
+ 'name' => time() . $category_id . 'active_cube_08.png', // 附件名称
+ 'real_name' => '魔方素材08', // 原始文件名
+ 'path' => 'addon/shop/attachment/active_cube_08.png', // 完整地址
+ 'url' => 'addon/shop/attachment/active_cube_08.png', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '81778', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ],
+ [
+ 'name' => time() . $category_id . 'nav_sow_community.png', // 附件名称
+ 'real_name' => '种草社区', // 原始文件名
+ 'path' => 'addon/shop/attachment/nav_sow_community.png', // 完整地址
+ 'url' => 'addon/shop/attachment/nav_sow_community.png', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '24576', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ]
+ ];
+ $attachment_model->insertAll($attachment_list);
+
+ // 创建默认商品海报
+ $poster = new CorePosterService();
+ $template = $poster->getTemplateList('shop', 'shop_goods')[ 0 ];
+ $poster->add('shop', [
+ 'name' => $template[ 'name' ],
+ 'type' => $template[ 'type' ],
+ 'value' => $template[ 'data' ],
+ 'status' => 1,
+ 'is_default' => 1
+ ]);
+
+ // 创建默认积分商品海报
+ $poster = new CorePosterService();
+ $template = $poster->getTemplateList('shop', 'shop_point_goods')[ 0 ];
+ $poster->add('shop', [
+ 'name' => $template[ 'name' ],
+ 'type' => $template[ 'type' ],
+ 'value' => $template[ 'data' ],
+ 'status' => 1,
+ 'is_default' => 1
+ ]);
+
+ $diy_service = new DiyService();
+
+ // 设置 首页 默认模板
+ $diy_service->setDiyData([
+ 'key' => 'DIY_INDEX',
+ 'type' => 'index',
+ 'addon' => 'shop',
+ 'is_start' => 1
+ ]);
+
+ // 设置 个人中心 默认模板
+ $diy_service->setDiyData([
+ 'key' => 'DIY_MEMBER_INDEX',
+ 'type' => 'member_index',
+ 'addon' => 'shop',
+ 'is_start' => 1
+ ]);
+
+ // 创建 积分商城 微页面
+ $addon_flag = 'DIY_SHOP_POINT_INDEX';
+ $addon_index_template = $diy_service->getFirstPageData($addon_flag, 'shop');
+ $diy_service->add([
+ 'page_title' => $addon_index_template[ 'title' ],
+ "title" => $addon_index_template[ 'title' ],
+ "name" => $addon_flag,
+ "type" => $addon_flag,
+ "template" => $addon_index_template[ 'template' ],
+ "mode" => $addon_index_template[ 'mode' ],
+ "value" => json_encode($addon_index_template[ 'data' ]),
+ "is_default" => 1,
+ "is_change" => 0
+ ]);
+
+ // 创建物流公司
+ $company_service = new CoreCompanyService();
+
+ $company_list = [
+ [
+ 'create_time' => time(),
+ 'company_name' => '邮政EMS',
+ 'logo' => 'addon/shop/express/ems.jpg',
+ 'url' => 'https://www.ems.com.cn',
+ 'express_no' => 'EMS',
+ 'express_no_electronic_sheet' => 'EMS',
+ 'electronic_sheet_switch' => 1,
+ 'print_style' => [
+ [
+ 'template_name' => '一联130 76*130',
+ 'template_size' => '130',
+ ],
+ [
+ 'template_name' => '一联130新 76*130',
+ 'template_size' => '1301',
+ ],
+ [
+ 'template_name' => '二联180 100*180',
+ 'template_size' => '180',
+ ],
+ [
+ 'template_name' => '二联180新 100*180',
+ 'template_size' => '1801',
+ ],
+ [
+ 'template_name' => '二联150 100*150',
+ 'template_size' => '0',
+ ],
+ [
+ 'template_name' => '二联150新 100*150',
+ 'template_size' => '1501',
+ ]
+ ],
+ 'exp_type' => [
+ [
+ 'text' => '特快专递',
+ 'value' => 1
+ ],
+ [
+ 'text' => '代收到付',
+ 'value' => 8
+ ],
+ [
+ 'text' => '快递包裹',
+ 'value' => 9
+ ],
+ [
+ 'text' => '电商标快',
+ 'value' => 10
+ ],
+ [
+ 'text' => '国内标快',
+ 'value' => 11
+ ]
+ ]
+ ],
+ [
+ 'create_time' => time(),
+ 'company_name' => '邮政快递包裹',
+ 'logo' => 'addon/shop/express/youzhengkd.png',
+ 'url' => 'https://www.ems.com.cn',
+ 'express_no' => 'YZPY',
+ 'express_no_electronic_sheet' => 'YZPY',
+ 'electronic_sheet_switch' => 1,
+ 'print_style' => [
+ [
+ 'template_name' => '一联130 76*130',
+ 'template_size' => '130',
+ ],
+ [
+ 'template_name' => '一联130新 76*130',
+ 'template_size' => '1301',
+ ],
+ [
+ 'template_name' => '二联1801 100*180',
+ 'template_size' => '1801',
+ ],
+ [
+ 'template_name' => '二联180 100*180',
+ 'template_size' => '0',
+ ],
+ [
+ 'template_name' => '二联180新 100*180',
+ 'template_size' => '180',
+ ],
+ [
+ 'template_name' => '二联150 100*150',
+ 'template_size' => '150',
+ ],
+ [
+ 'template_name' => '二联150新 100*150',
+ 'template_size' => '1501',
+ ]
+ ],
+ 'exp_type' => [
+ [
+ 'text' => '标准快递',
+ 'value' => 1
+ ]
+ ]
+ ],
+ [
+ 'create_time' => time(),
+ 'company_name' => '顺丰速运',
+ 'logo' => 'addon/shop/express/shunfeng.png',
+ 'url' => 'https://www.sf-express.com/chn/sc',
+ 'express_no' => 'SF',
+ 'express_no_electronic_sheet' => 'SF',
+ 'electronic_sheet_switch' => 1,
+ 'print_style' => [
+ [
+ 'template_name' => '一联130新 76*130',
+ 'template_size' => '1301',
+ ],
+ [
+ 'template_name' => '二联150新 100*150',
+ 'template_size' => '0',
+ ],
+ [
+ 'template_name' => '二联180新 100*180',
+ 'template_size' => '180',
+ ],
+ [
+ 'template_name' => '三联210新 100*210',
+ 'template_size' => '210',
+ ]
+ ],
+ 'exp_type' => [
+ [
+ 'text' => '顺丰特快',
+ 'value' => 1
+ ],
+ [
+ 'text' => '顺丰标快',
+ 'value' => 2
+ ],
+ [
+ 'text' => '顺丰即日',
+ 'value' => 6
+ ],
+ [
+ 'text' => '冷运标快',
+ 'value' => 201
+ ],
+ [
+ 'text' => '顺丰微小件',
+ 'value' => 202
+ ]
+ ]
+ ],
+ [
+ 'create_time' => time(),
+ 'company_name' => '中通快递',
+ 'logo' => 'addon/shop/express/zhongtong.png',
+ 'url' => 'https://www.zto.com',
+ 'express_no' => 'ZTO',
+ 'express_no_electronic_sheet' => 'ZTO',
+ 'electronic_sheet_switch' => 1,
+ 'print_style' => [
+ [
+ 'template_name' => '一联130 76*130',
+ 'template_size' => '130',
+ ],
+ [
+ 'template_name' => '二联180 100*180',
+ 'template_size' => '0',
+ ],
+ [
+ 'template_name' => '二联180新 100*180',
+ 'template_size' => '180',
+ ]
+ ],
+ 'exp_type' => []
+ ],
+ [
+ 'create_time' => time(),
+ 'company_name' => '圆通速递',
+ 'logo' => 'addon/shop/express/yuantong.png',
+ 'url' => 'https://www.yto.net.cn',
+ 'express_no' => 'YTO',
+ 'express_no_electronic_sheet' => 'YTO',
+ 'electronic_sheet_switch' => 1,
+ 'print_style' => [
+ [
+ 'template_name' => '一联130 76*130',
+ 'template_size' => '130',
+ ],
+ [
+ 'template_name' => '一联130新 76*130',
+ 'template_size' => '1301',
+ ],
+ [
+ 'template_name' => '二联180 100*180',
+ 'template_size' => '0',
+ ],
+ [
+ 'template_name' => '三联180 100*180',
+ 'template_size' => '180',
+ ],
+ [
+ 'template_name' => '二联180新 100*180',
+ 'template_size' => '1801',
+ ]
+ ],
+ 'exp_type' => [
+ [
+ 'text' => '标准快递',
+ 'value' => 1
+ ],
+ [
+ 'text' => '圆准达',
+ 'value' => 2
+ ]
+ ]
+ ],
+ [
+ 'create_time' => time(),
+ 'company_name' => '申通快递',
+ 'logo' => 'addon/shop/express/shentong.png',
+ 'url' => 'https://www.sto.cn/pc',
+ 'express_no' => 'STO',
+ 'express_no_electronic_sheet' => 'STO',
+ 'electronic_sheet_switch' => 1,
+ 'print_style' => [
+ [
+ 'template_name' => '一联130 76*130',
+ 'template_size' => '130',
+ ],
+ [
+ 'template_name' => '一联130新 76*130',
+ 'template_size' => '1301',
+ ],
+ [
+ 'template_name' => '二联180 100*180',
+ 'template_size' => '0',
+ ],
+ [
+ 'template_name' => '二联180新 100*180',
+ 'template_size' => '180',
+ ],
+ [
+ 'template_name' => '三联180新 100*180',
+ 'template_size' => '1803',
+ ],
+ [
+ 'template_name' => '二联150 100*150',
+ 'template_size' => '150',
+ ]
+ ],
+ 'exp_type' => [
+ [
+ 'text' => '标准快递',
+ 'value' => 1
+ ],
+ ]
+ ],
+ [
+ 'create_time' => time(),
+ 'company_name' => '韵达速递',
+ 'logo' => 'addon/shop/express/yunda.png',
+ 'url' => 'http://www.yundaex.com/cn',
+ 'express_no' => 'YD',
+ 'express_no_electronic_sheet' => 'YD',
+ 'electronic_sheet_switch' => 1,
+ 'print_style' => [
+ [
+ 'template_name' => '一联130 100*130',
+ 'template_size' => '130',
+ ],
+ [
+ 'template_name' => '二联180 100*180',
+ 'template_size' => '180',
+ ],
+ [
+ 'template_name' => '二联203 100*203',
+ 'template_size' => '0',
+ ]
+ ],
+ 'exp_type' => []
+ ],
+ [
+ 'create_time' => time(),
+ 'company_name' => '极兔速递',
+ 'logo' => 'addon/shop/express/jitu.png',
+ 'url' => 'https://www.jtexpress.cn',
+ 'express_no' => 'JTSD',
+ 'express_no_electronic_sheet' => 'JTSD',
+ 'electronic_sheet_switch' => 1,
+ 'print_style' => [
+ [
+ 'template_name' => '一联130 100*130',
+ 'template_size' => '130',
+ ],
+ [
+ 'template_name' => '二联180 100*180',
+ 'template_size' => '0',
+ ]
+ ],
+ 'exp_type' => [
+ [
+ 'text' => '标准快递',
+ 'value' => 1
+ ],
+ [
+ 'text' => '兔优达',
+ 'value' => 2
+ ]
+ ]
+ ],
+ [
+ 'create_time' => time(),
+ 'company_name' => '菜鸟速递',
+ 'logo' => 'addon/shop/express/cainiao.jpg',
+ 'url' => 'https://express.cainiao.com/',
+ 'express_no' => 'CNSD',
+ 'express_no_electronic_sheet' => 'CNSD',
+ 'electronic_sheet_switch' => 1,
+ 'print_style' => [
+ [
+ 'template_name' => '一联130 100*130',
+ 'template_size' => '0',
+ ]
+ ],
+ 'exp_type' => [
+ [
+ 'text' => '当日达',
+ 'value' => 1
+ ],
+ [
+ 'text' => '次日达',
+ 'value' => 2
+ ],
+ [
+ 'text' => '预约配送',
+ 'value' => 3
+ ],
+ [
+ 'text' => '当日下午达',
+ 'value' => 4
+ ],
+ [
+ 'text' => '当日夜间达',
+ 'value' => 5
+ ],
+ [
+ 'text' => '次日上午达',
+ 'value' => 6
+ ]
+ ]
+ ],
+ [
+ 'create_time' => time(),
+ 'company_name' => '京东快递',
+ 'logo' => 'addon/shop/express/jingdong.jpg',
+ 'url' => 'https://www.jdl.com',
+ 'express_no' => 'JD',
+ 'express_no_electronic_sheet' => 'JD',
+ 'electronic_sheet_switch' => 1,
+ 'print_style' => [
+ [
+ 'template_name' => '一联130新 76*130',
+ 'template_size' => '130',
+ ],
+ [
+ 'template_name' => '二联110 100*110',
+ 'template_size' => '0',
+ ],
+ [
+ 'template_name' => '二联110新 100*110',
+ 'template_size' => '110',
+ ]
+ ],
+ 'exp_type' => []
+ ]
+ ];
+ $company_service->addAll($company_list);
+
+ $company_list_for_print = $company_service->getList([
+ [ 'express_no_electronic_sheet', 'in', [ 'EMS', 'YZPY', 'SF' ] ],
+ [ 'electronic_sheet_switch', '=', 1 ],
+ ], 'company_id,company_name,express_no_electronic_sheet,print_style,exp_type');
+
+ $electronic_sheet_list = [];
+ foreach ($company_list_for_print as $k => $v) {
+ $electronic_sheet_list[] = [
+ 'template_name' => $v[ 'company_name' ] . ' ' . $v[ 'print_style' ][ 0 ][ 'template_name' ],
+ 'express_company_id' => $v[ 'company_id' ],
+ 'customer_name' => '电子面单账号',
+ 'customer_pwd' => '电子面单密码',
+ 'send_site' => '',
+ 'send_staff' => '',
+ 'month_code' => '',
+ 'pay_type' => 1,
+ 'is_notice' => 0,
+ 'status' => 1,
+ 'exp_type' => $v[ 'exp_type' ][ 0 ][ 'value' ],
+ 'print_style' => $v[ 'print_style' ][ 0 ][ 'template_size' ],
+ 'is_default' => $k == 0 ? 1 : 0,
+ 'create_time' => time()
+ ];
+ }
+
+ $electronic_sheet_service = new CoreElectronicSheetService();
+ $electronic_sheet_service->addAll($electronic_sheet_list);
+
+ // 添加商品标签分组
+ $label_group_model = new LabelGroup();
+ $label_model = new Label();
+
+ // 添加默认商品标签分组
+ $label_group_res = $label_group_model->create([
+ 'group_name' => '默认',
+ 'create_time' => time(),
+ ]);
+
+ // 添加商品标签
+ $label_list = [
+ [
+ 'label_name' => '热卖',
+ 'group_id' => $label_group_res->group_id,
+ 'style_type' => 'diy',
+ 'color_json' => [
+ 'text_color' => 'rgba(255, 255, 255, 1)',
+ 'bg_color' => 'rgba(250, 35, 28, 1)',
+ 'border_color' => ''
+ ],
+ 'icon' => '',
+ 'status' => 1,
+ 'sort' => 0,
+ 'create_time' => time()
+ ],
+ [
+ 'label_name' => '新品推荐',
+ 'group_id' => $label_group_res->group_id,
+ 'style_type' => 'diy',
+ 'color_json' => [
+ 'text_color' => 'rgba(255, 255, 255, 1)',
+ 'bg_color' => 'rgba(250, 35, 28, 1)',
+ 'border_color' => ''
+ ],
+ 'icon' => '',
+ 'status' => 1,
+ 'sort' => 1,
+ 'create_time' => time()
+ ],
+ [
+ 'label_name' => '甄选优品',
+ 'group_id' => $label_group_res->group_id,
+ 'style_type' => 'diy',
+ 'color_json' => [
+ 'text_color' => 'rgba(255, 255, 255, 1)',
+ 'bg_color' => 'rgba(250, 35, 28, 1)',
+ 'border_color' => ''
+ ],
+ 'icon' => '',
+ 'status' => 1,
+ 'sort' => 2,
+ 'create_time' => time()
+ ],
+ [
+ 'label_name' => '百亿补贴',
+ 'group_id' => $label_group_res->group_id,
+ 'style_type' => 'icon',
+ 'color_json' => [
+ 'text_color' => 'rgba(255, 255, 255, 1)',
+ 'bg_color' => 'rgba(250, 35, 28, 1)',
+ 'border_color' => ''
+ ],
+ 'icon' => 'addon/shop/goods/label/icon1.png',
+ 'status' => 1,
+ 'sort' => 3,
+ 'create_time' => time()
+ ],
+ [
+ 'label_name' => '双11',
+ 'group_id' => $label_group_res->group_id,
+ 'style_type' => 'icon',
+ 'color_json' => [
+ 'text_color' => 'rgba(255, 255, 255, 1)',
+ 'bg_color' => 'rgba(250, 35, 28, 1)',
+ 'border_color' => ''
+ ],
+ 'icon' => 'addon/shop/goods/label/icon2.png',
+ 'status' => 1,
+ 'sort' => 4,
+ 'create_time' => time()
+ ],
+ [
+ 'label_name' => '双12',
+ 'group_id' => $label_group_res->group_id,
+ 'style_type' => 'icon',
+ 'color_json' => [
+ 'text_color' => 'rgba(255, 255, 255, 1)',
+ 'bg_color' => 'rgba(250, 35, 28, 1)',
+ 'border_color' => ''
+ ],
+ 'icon' => 'addon/shop/goods/label/icon3.png',
+ 'status' => 1,
+ 'sort' => 5,
+ 'create_time' => time()
+ ]
+ ];
+ $label_model->insertAll($label_list);
+
+ $listener = new ThemeColorListener();
+ $addon_theme = $listener->handle([ 'key' => 'shop' ]);
+ $diy_service->initAddonThemeColorData('shop', $addon_theme);
+ return true;
+ }
+
+ /**
+ * 插件卸载执行
+ */
+ public function uninstall()
+ {
+ // 删除自定义海报
+ $poster = new CorePosterService();
+ $poster->del([
+ [ 'type', 'in', [ 'shop_goods', 'shop_point_goods' ] ]
+ ]);
+
+ // 删除微页面
+ $diy_service = new CoreDiyService();
+ $diy_service->del([
+ [ 'name', 'in', [ 'DIY_SHOP_INDEX', 'DIY_SHOP_MEMBER_INDEX', 'DIY_SHOP_POINT_INDEX' ] ]
+ ]);
+
+ // 删除商城素材
+ $category_model = new SysAttachmentCategory();
+ $category_model->where([
+ [ 'name', '=', '商城素材' ]
+ ])->delete();
+
+ $attachment_model = new SysAttachment();
+ $path_arr = [
+ 'addon/shop/attachment/banner1.jpg',
+ 'shop/attachment/banner2.png',
+ 'addon/shop/attachment/banner3.png',
+ 'addon/shop/attachment/logo.png',
+ 'addon/shop/attachment/nav_coupon.png',
+ 'addon/shop/attachment/nav_discount.png',
+ 'addon/shop/attachment/nav_fenxiao.png',
+ 'addon/shop/attachment/nav_fenxiao_zone.png',
+ 'addon/shop/attachment/nav_giftcard.png',
+ 'addon/shop/attachment/nav_my_address.png',
+ 'addon/shop/attachment/nav_my_newcomer.png',
+ 'addon/shop/attachment/nav_news_info.png',
+ 'addon/shop/attachment/nav_point_index.png',
+ 'addon/shop/attachment/nav_sign_in.png',
+ 'addon/shop/attachment/notice.png',
+ 'addon/shop/attachment/picture_show_head_text2.png',
+ 'addon/shop/attachment/picture_show_head_text3.png',
+ 'addon/shop/attachment/single_recommend_banner1.png',
+ 'addon/shop/attachment/single_recommend_banner2.png',
+ 'addon/shop/attachment/single_recommend_text1.png',
+ 'addon/shop/attachment/my_cart.png',
+ 'addon/shop/attachment/home_delivery.png',
+ 'addon/shop/attachment/nav_all_class.png',
+ 'addon/shop/attachment/nav_balance.png',
+ 'addon/shop/attachment/nav_collect.png',
+ 'addon/shop/attachment/nav_coupon_01.png',
+ 'addon/shop/attachment/nav_leaderboard.png',
+ 'addon/shop/attachment/nav_member.png',
+ 'addon/shop/attachment/nav_point.png',
+ 'addon/shop/attachment/nav_shop.png',
+ 'addon/shop/attachment/nav_travel.png',
+ 'addon/shop/attachment/nva_group_booking.png',
+ 'addon/shop/attachment/head_01.png',
+ 'addon/shop/attachment/head_02.png',
+ 'addon/shop/attachment/head_03.png',
+ 'addon/shop/attachment/image_ads_01.png',
+ 'addon/shop/attachment/active_cube_01.png',
+ 'addon/shop/attachment/active_cube_02.png',
+ 'addon/shop/attachment/active_cube_03.png',
+ 'addon/shop/attachment/active_cube_04.png',
+ 'addon/shop/attachment/active_cube_05.png',
+ 'addon/shop/attachment/active_cube_06.png',
+ 'addon/shop/attachment/active_cube_07.png',
+ 'addon/shop/attachment/active_cube_08.png'
+ ];
+ $attachment_model->where([
+ [ 'path', 'in', $path_arr ]
+ ])->delete();
+
+ $diy_theme_model = new DiyTheme();
+ // 删除原有主题风格颜色
+ $diy_theme_model->where([ [ 'addon', '=', 'shop' ] ])->delete();
+ return true;
+ }
+
+ /**
+ * 插件升级执行
+ */
+ public function upgrade()
+ {
+ return true;
+ }
+}
diff --git a/niucloud/addon/shop/admin/api/delivery.ts b/niucloud/addon/shop/admin/api/delivery.ts
new file mode 100644
index 000000000..b05526c6c
--- /dev/null
+++ b/niucloud/addon/shop/admin/api/delivery.ts
@@ -0,0 +1,282 @@
+import request from '@/utils/request'
+
+/********************************* 物流公司 ***************************************/
+/**
+ * 获取物流公司分页列表
+ * @param params
+ * @returns
+ */
+export function getCompanyPageList(params: Record) {
+ return request.get(`shop/delivery/company`, { params })
+}
+
+/**
+ * 获取物流公司列表
+ * @param params
+ * @returns
+ */
+export function getCompanyList(params: Record) {
+ return request.get(`shop/delivery/company/list`, { params })
+}
+
+/**
+ * 获取物流公司详情
+ * @param company_id 物流公司company_id
+ * @returns
+ */
+export function getCompanyInfo(company_id: number) {
+ return request.get(`shop/delivery/company/${ company_id }`);
+}
+
+/**
+ * 添加物流公司
+ * @param params
+ * @returns
+ */
+export function addCompany(params: Record) {
+ return request.post('shop/delivery/company', params, { showErrorMessage: true, showSuccessMessage: true })
+}
+
+/**
+ * 编辑物流公司
+ * @param params
+ * @returns
+ */
+export function editCompany(params: Record) {
+ return request.put(`shop/delivery/company/${ params.company_id }`, params, {
+ showErrorMessage: true,
+ showSuccessMessage: true
+ })
+}
+
+/**
+ * 删除物流公司
+ * @param company_id
+ * @returns
+ */
+export function deleteCompany(company_id: number) {
+ return request.delete(`shop/delivery/company/${ company_id }`, { showErrorMessage: true, showSuccessMessage: true })
+}
+
+/********************************* 运费模版 ***************************************/
+/**
+ * 获取运费模版分页列表
+ * @param params
+ * @returns
+ */
+export function getShippingTemplatePageList(params: Record) {
+ return request.get(`shop/shipping/template`, { params })
+}
+
+/**
+ * 获取运费模版列表
+ * @param params
+ * @returns
+ */
+export function getShippingTemplateList(params: Record) {
+ return request.get(`shop/shipping/template/list`, { params })
+}
+
+/**
+ * 获取物运费模版详情
+ * @param template_id 运费模版template_id
+ * @returns
+ */
+export function getShippingTemplateInfo(template_id: number) {
+ return request.get(`shop/shipping/template/${ template_id }`);
+}
+
+/**
+ * 添加运费模版
+ * @param params
+ * @returns
+ */
+export function addShippingTemplate(params: Record) {
+ return request.post('shop/shipping/template', params, { showErrorMessage: true, showSuccessMessage: true })
+}
+
+/**
+ * 编辑运费模版
+ * @param params
+ * @returns
+ */
+export function editShippingTemplate(params: Record) {
+ return request.put(`shop/shipping/template/${ params.template_id }`, params, {
+ showErrorMessage: true,
+ showSuccessMessage: true
+ })
+}
+
+/**
+ * 删除运费模版
+ * @param template_id
+ * @returns
+ */
+export function deleteShippingTemplate(template_id: number) {
+ return request.delete(`shop/shipping/template/${ template_id }`, {
+ showErrorMessage: true,
+ showSuccessMessage: true
+ })
+}
+
+/********************************* 自提门店 ***************************************/
+/**
+ * 获取自提门店列表
+ * @param params
+ * @returns
+ */
+export function getStoreList(params: Record) {
+ return request.get(`shop/delivery/store`, { params })
+}
+
+/**
+ * 获取自提门店详情
+ * @param store_id 自提门店store_id
+ * @returns
+ */
+export function getStoreInfo(store_id: number) {
+ return request.get(`shop/delivery/store/${ store_id }`);
+}
+
+/**
+ * 获取初始化页面信息
+ * @returns
+ */
+export function getStoreInit() {
+ return request.get(`shop/delivery/store/init`)
+}
+
+/**
+ * 添加自提门店
+ * @param params
+ * @returns
+ */
+export function addStore(params: Record) {
+ return request.post('shop/delivery/store', params, { showErrorMessage: true, showSuccessMessage: true })
+}
+
+/**
+ * 编辑自提门店
+ * @param params
+ * @returns
+ */
+export function editStore(params: Record) {
+ return request.put(`shop/delivery/store/${ params.store_id }`, params, {
+ showErrorMessage: true,
+ showSuccessMessage: true
+ })
+}
+
+/**
+ * 删除自提门店
+ * @param store_id
+ * @returns
+ */
+export function deleteStore(store_id: number) {
+ return request.delete(`shop/delivery/store/${ store_id }`, { showErrorMessage: true, showSuccessMessage: true })
+}
+
+/********************************* 物流查询 ***************************************/
+/**
+ * 设置 物流查询配置
+ * @param params
+ * @returns
+ */
+export function setDeliverySearch(params: Record) {
+ return request.post('shop/delivery/search', params, { showErrorMessage: true, showSuccessMessage: true })
+}
+
+/**
+ * 获取 物流查询配置
+ * @returns
+ */
+export function getDeliverySearch() {
+ return request.get('shop/delivery/search')
+}
+
+/**
+ * 获取 物流管理配置
+ * @returns
+ */
+export function getShopDeliveryList() {
+ return request.get('shop/delivery/deliveryList')
+}
+
+/**
+ * 物流管理设置
+ * @param params
+ * @returns
+ */
+export function setShopDeliveryConfig(params: Record) {
+ return request.put(`shop/delivery/setConfig`, params, { showSuccessMessage: true })
+}
+
+/**
+ * 获取 配送员列表
+ * @param params
+ * @returns
+ */
+export function getShopDelivery(params: Record) {
+ return request.get('shop/delivery/staff', { params })
+}
+
+/**
+ * 获取配送员信息
+ * @param staff_id
+ * @returns
+ */
+export function getShopDeliverInfo(staff_id: number) {
+ return request.get(`shop/delivery/staff/${ staff_id }`);
+}
+
+/**
+ * 添加配送员
+ * @param params
+ * @returns
+ */
+export function addShopDeliver(params: Record) {
+ return request.post('shop/delivery/staff', params, { showSuccessMessage: true })
+}
+
+/**
+ * 编辑配送员
+ * @param params
+ * @returns
+ */
+export function editShopDeliver(params: Record) {
+ return request.put(`shop/delivery/staff/${ params.deliver_id }`, params, { showSuccessMessage: true })
+}
+
+/**
+ * 删除配送员
+ * @param staff_id
+ * @returns
+ */
+export function deleteShopDeliver(staff_id: number) {
+ return request.delete(`shop/delivery/staff/${ staff_id }`)
+}
+
+/**
+ * 获取同城配送设置
+ * @returns
+ */
+export function getLocal() {
+ return request.get('shop/local');
+}
+
+/**
+ * 设置同城配送
+ * @param params
+ * @returns
+ */
+export function setLocal(params: Record) {
+ return request.put('shop/local', params, { showSuccessMessage: true })
+}
+
+/**
+ * 三方配送
+ * @returns
+ */
+export function getThird() {
+ return request.get('shop/third/init')
+}
diff --git a/niucloud/addon/shop/admin/api/electronic_sheet.ts b/niucloud/addon/shop/admin/api/electronic_sheet.ts
new file mode 100644
index 000000000..7f75c124c
--- /dev/null
+++ b/niucloud/addon/shop/admin/api/electronic_sheet.ts
@@ -0,0 +1,116 @@
+import request from '@/utils/request'
+
+/**
+ * 获取电子面单分页列表
+ * @param params
+ * @returns
+ */
+export function getElectronicSheetPageList(params: Record) {
+ return request.get(`shop/electronic_sheet`, { params })
+}
+
+/**
+ * 获取电子面单列表
+ * @param params
+ * @returns
+ */
+export function getElectronicSheetList(params: Record) {
+ return request.get(`shop/electronic_sheet/list`, { params })
+}
+
+/**
+ * 获取电子面单详情
+ * @param id 电子面单id
+ * @returns
+ */
+export function getElectronicSheetInfo(id: number) {
+ return request.get(`shop/electronic_sheet/${ id }`);
+}
+
+/**
+ * 添加电子面单
+ * @param params
+ * @returns
+ */
+export function addElectronicSheet(params: Record) {
+ return request.post('shop/electronic_sheet', params, {
+ showErrorMessage: true,
+ showSuccessMessage: true
+ })
+}
+
+/**
+ * 编辑电子面单
+ * @param params
+ * @returns
+ */
+export function editElectronicSheet(params: Record) {
+ return request.put(`shop/electronic_sheet/${ params.id }`, params, {
+ showErrorMessage: true,
+ showSuccessMessage: true
+ })
+}
+
+/**
+ * 删除电子面单
+ * @param id
+ * @returns
+ */
+export function deleteElectronicSheet(id: number) {
+ return request.delete(`shop/electronic_sheet/${ id }`, {
+ showErrorMessage: true,
+ showSuccessMessage: true
+ })
+}
+
+/**
+ * 设置默认电子面单模板
+ * @param params
+ * @returns
+ */
+export function setDefaultElectronicSheet(params: Record) {
+ return request.put(`shop/electronic_sheet/setDefault/${ params.id }`, params, {
+ showErrorMessage: true,
+ showSuccessMessage: true
+ })
+}
+
+/**
+ * 设置电子面单 设置
+ * @param params
+ * @returns
+ */
+export function setElectronicSheetConfig(params: Record) {
+ return request.post('shop/electronic_sheet/config', params, {
+ showErrorMessage: true,
+ showSuccessMessage: true
+ })
+}
+
+/**
+ * 获取电子面单配置
+ * @returns
+ */
+export function getElectronicSheetConfig() {
+ return request.get(`shop/electronic_sheet/config`)
+}
+
+/**
+ * 获取邮费支付方式类型
+ * @returns
+ */
+export function getElectronicSheetPayType() {
+ return request.get(`shop/electronic_sheet/paytype`)
+}
+
+/**
+ * 打印电子面单
+ * @param params
+ * @returns
+ */
+export function printElectronicSheet(params: Record) {
+ return request.post('shop/electronic_sheet/print', params, {
+ showErrorMessage: true,
+ showSuccessMessage: true
+ })
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/admin/api/goods.ts b/niucloud/addon/shop/admin/api/goods.ts
new file mode 100644
index 000000000..0ff4b7ecf
--- /dev/null
+++ b/niucloud/addon/shop/admin/api/goods.ts
@@ -0,0 +1,862 @@
+import request from '@/utils/request'
+
+/**
+ * 获取商品列表
+ * @param params
+ * @returns
+ */
+export function getGoodsPageList(params: Record) {
+ return request.get(`shop/goods`, { params })
+}
+
+/**
+ * 获取商品详情
+ * @param goods_id 商品goods_id
+ * @returns
+ */
+export function getGoodsInfo(goods_id: number) {
+ return request.get(`shop/goods/${ goods_id }`);
+}
+
+
+/**
+ * 获取商品详情模板
+ * @param goods_id 商品goods_id
+ * @returns
+ */
+export function getGoodsInfoTemplate(params: any) {
+ return request.get(`diy/list`, { params });
+}
+
+/**
+ * 添加实物商品
+ * @param params
+ * @returns
+ */
+export function addGoods(params: Record) {
+ return request.post('shop/goods', params, { showErrorMessage: true, showSuccessMessage: true })
+}
+
+/**
+ * 编辑实物商品
+ * @param params
+ */
+export function editGoods(params: Record) {
+ return request.put(`shop/goods/${ params.goods_id }`, params, { showErrorMessage: true, showSuccessMessage: true })
+}
+
+/**
+ * 获取商品添加/编辑初始化数据
+ * @param params
+ */
+export function getGoodsInit(params: Record) {
+ return request.get(`shop/goods/init`, { params });
+}
+
+/**
+ * 添加虚拟商品
+ * @param params
+ * @returns
+ */
+export function addVirtualGoods(params: Record) {
+ return request.post('shop/goods/virtual', params, { showErrorMessage: true, showSuccessMessage: true })
+}
+
+/**
+ * 编辑虚拟商品
+ * @param params
+ */
+export function editVirtualGoods(params: Record) {
+ return request.put(`shop/goods/virtual/${ params.goods_id }`, params, {
+ showErrorMessage: true,
+ showSuccessMessage: true
+ })
+}
+
+/**
+ * 获取虚拟商品添加/编辑初始化数据
+ * @param params
+ */
+export function getVirtualGoodsInit(params: Record) {
+ return request.get(`shop/goods/virtual/init`, { params });
+}
+
+/**
+ * 删除商品
+ * @param params
+ * @returns
+ */
+export function deleteGoods(params: Record) {
+ return request.put(`shop/goods/delete`, params, { showErrorMessage: true, showSuccessMessage: true })
+}
+
+/**
+ * 获取回收站商品分页列表
+ * @param params
+ * @returns
+ */
+export function getRecycleGoodsPageList(params: Record) {
+ return request.get(`shop/goods/recycle`, { params })
+}
+
+/**
+ * 恢复商品
+ * @param params
+ * @returns
+ */
+export function recycleGoods(params: Record) {
+ return request.put(`shop/goods/recycle`, params, { showErrorMessage: true, showSuccessMessage: true })
+}
+
+/**
+ * 修改商品排序号
+ * @param params
+ */
+export function editGoodsSort(params: Record) {
+ return request.put(`shop/goods/sort`, params, { showSuccessMessage: true })
+}
+
+/**
+ * 修改商品上下架状态
+ * @param params
+ */
+export function editGoodsStatus(params: Record) {
+ return request.put(`shop/goods/status`, params, { showSuccessMessage: true })
+}
+
+/**
+ * 复制商品
+ * @param params
+ */
+export function copyGoods(params: Record) {
+ return request.put(`shop/goods/copy/${ params.goods_id }`, params, { showSuccessMessage: true })
+}
+
+/**
+ * 获取商品选择分页列表
+ * @param params
+ * @returns
+ */
+export function getGoodsSelectPageList(params: Record) {
+ return request.get(`shop/goods/select`, { params })
+}
+
+/**
+ * 获取商品SKU规格列表
+ * @param params
+ * @returns
+ */
+export function getGoodsSkuList(params: Record) {
+ return request.get(`shop/goods/sku`, { params })
+}
+
+/**
+ * 获取商品SKU规格不分页列表
+ * @param params
+ * @returns
+ */
+export function getGoodsSkuNoPageList(params: Record) {
+ return request.get(`shop/goods/selectgoodssku`, { params })
+}
+
+/** 查询商品参与营销活动的数量
+ * @param params
+ * @returns
+ */
+export function getActiveGoodsCount(params: Record) {
+ return request.get(`shop/goods/active/count`, { params })
+}
+
+/**
+ * 编辑商品SKU规格库存
+ * @param params
+ * @returns
+ */
+export function editGoodsListStock(params: Record) {
+ return request.put(`shop/goods/sku/stock`, params, { showSuccessMessage: true })
+}
+
+/**
+ * 编辑商品SKU规格价格
+ * @param params
+ * @returns
+ */
+export function editGoodsListPrice(params: Record) {
+ return request.put(`shop/goods/sku/price`, params, { showSuccessMessage: true })
+}
+
+/**
+ * 编辑商品SKU规格会员价格
+ * @param params
+ * @returns
+ */
+export function editGoodsListMemberPrice(params: Record) {
+ return request.put(`shop/goods/sku/member_price`, params, { showSuccessMessage: true })
+}
+
+/**
+ * 获取商品类型
+ * @returns
+ */
+export function getGoodsType() {
+ return request.get(`shop/goods/type`);
+}
+
+/**
+ * 获取商品标签分页列表
+ * @param params
+ * @returns
+ */
+export function getLabelPageList(params: Record) {
+ return request.get(`shop/goods/label`, { params })
+}
+
+/**
+ * 获取商品标签列表
+ * @param params
+ * @returns
+ */
+export function getLabelList(params: Record) {
+ return request.get(`shop/goods/label/list`, { params })
+}
+
+/**
+ * 获取商品标签详情
+ * @param label_id 商品标签label_id
+ * @returns
+ */
+export function getLabelInfo(label_id: number) {
+ return request.get(`shop/goods/label/${ label_id }`);
+}
+
+/**
+ * 添加商品标签
+ * @param params
+ * @returns
+ */
+export function addLabel(params: Record) {
+ return request.post('shop/goods/label', params, { showErrorMessage: true, showSuccessMessage: true })
+}
+
+/**
+ * 编辑商品标签
+ * @param params
+ * @returns
+ */
+export function editLabel(params: Record) {
+ return request.put(`shop/goods/label/${ params.label_id }`, params, {
+ showErrorMessage: true,
+ showSuccessMessage: true
+ })
+}
+
+/**
+ * 修改商品标签状态
+ * @param params
+ */
+export function modifyLabelStatus(params: Record) {
+ return request.put(`shop/goods/label/status`, params, { showSuccessMessage: true })
+}
+
+/**
+ * 删除商品标签
+ * @param label_id
+ * @returns
+ */
+export function deleteLabel(label_id: number) {
+ return request.delete(`shop/goods/label/${ label_id }`, { showErrorMessage: true, showSuccessMessage: true })
+}
+
+/**
+ * 修改商品标签排序号
+ * @param params
+ */
+export function modifyLabelSort(params: Record) {
+ return request.put(`shop/goods/label/sort`, params, { showSuccessMessage: true })
+}
+
+/**
+ * 获取商品标签分组分页列表
+ * @param params
+ * @returns
+ */
+export function getLabelGroupPageList(params: Record) {
+ return request.get(`shop/goods/label/group`, { params })
+}
+
+/**
+ * 获取商品标签分组列表
+ * @param params
+ * @returns
+ */
+export function getLabelGroupList(params: Record) {
+ return request.get(`shop/goods/label/group/list`, { params })
+}
+
+/**
+ * 获取商品标签分组详情
+ * @param label_id 商品标签分组label_id
+ * @returns
+ */
+export function getLabelGroupInfo(label_id: number) {
+ return request.get(`shop/goods/label/group/${ label_id }`);
+}
+
+/**
+ * 添加商品标签分组
+ * @param params
+ * @returns
+ */
+export function addLabelGroup(params: Record) {
+ return request.post('shop/goods/label/group', params, { showErrorMessage: true, showSuccessMessage: true })
+}
+
+/**
+ * 编辑商品标签分组
+ * @param params
+ * @returns
+ */
+export function editLabelGroup(params: Record) {
+ return request.put(`shop/goods/label/group/${ params.group_id }`, params, {
+ showErrorMessage: true,
+ showSuccessMessage: true
+ })
+}
+
+/**
+ * 删除商品标签分组
+ * @param group_id
+ * @returns
+ */
+export function deleteLabelGroup(group_id: number) {
+ return request.delete(`shop/goods/label/group/${ group_id }`, { showErrorMessage: true, showSuccessMessage: true })
+}
+
+/**
+ * 修改商品标签分组排序号
+ * @param params
+ */
+export function modifyLabelGroupSort(params: Record) {
+ return request.put(`shop/goods/label/group/sort`, params, { showSuccessMessage: true })
+}
+
+/**
+ * 复制标签
+ * @param params
+ */
+export function copyLabel(params: Record) {
+ return request.post(`shop/goods/label/copy/${ params.label_id }`, params, { showSuccessMessage: true })
+}
+
+/**
+ * 获取商品品牌分页列表
+ * @param params
+ * @returns
+ */
+export function getBrandPageList(params: Record) {
+ return request.get(`shop/goods/brand`, { params })
+}
+
+/**
+ * 获取商品品牌列表
+ * @param params
+ * @returns
+ */
+export function getBrandList(params: Record) {
+ return request.get(`shop/goods/brand/list`, { params })
+}
+
+/**
+ * 获取商品品牌详情
+ * @param brand_id 商品品牌brand_id
+ * @returns
+ */
+export function getBrandInfo(brand_id: number) {
+ return request.get(`shop/goods/brand/${ brand_id }`);
+}
+
+/**
+ * 添加商品品牌
+ * @param params
+ * @returns
+ */
+export function addBrand(params: Record) {
+ return request.post('shop/goods/brand', params, { showErrorMessage: true, showSuccessMessage: true })
+}
+
+/**
+ * 编辑商品品牌
+ * @param params
+ * @returns
+ */
+export function editBrand(params: Record) {
+ return request.put(`shop/goods/brand/${ params.brand_id }`, params, {
+ showErrorMessage: true,
+ showSuccessMessage: true
+ })
+}
+
+/**
+ * 修改商品品牌排序号
+ * @param params
+ */
+export function modifyBrandSort(params: Record) {
+ return request.put(`shop/goods/brand/sort`, params, { showSuccessMessage: true })
+}
+
+/**
+ * 删除商品品牌
+ * @param brand_id
+ * @returns
+ */
+export function deleteBrand(brand_id: number) {
+ return request.delete(`shop/goods/brand/${ brand_id }`, { showErrorMessage: true, showSuccessMessage: true })
+}
+
+/**
+ * 获取商品服务分页列表
+ * @param params
+ * @returns
+ */
+export function getServePageList(params: Record) {
+ return request.get(`shop/goods/service`, { params })
+}
+
+/**
+ * 获取商品服务列表
+ * @param params
+ * @returns
+ */
+export function getServeList(params: Record) {
+ return request.get(`shop/goods/service/list`, { params })
+}
+
+/**
+ * 获取商品服务详情
+ * @param service_id 商品服务service_id
+ * @returns
+ */
+export function getServeInfo(service_id: number) {
+ return request.get(`shop/goods/service/${ service_id }`);
+}
+
+/**
+ * 添加商品服务
+ * @param params
+ * @returns
+ */
+export function addServe(params: Record) {
+ return request.post('shop/goods/service', params, { showErrorMessage: true, showSuccessMessage: true })
+}
+
+/**
+ * 编辑商品服务
+ * @param params
+ * @returns
+ */
+export function editServe(params: Record) {
+ return request.put(`shop/goods/service/${ params.service_id }`, params, {
+ showErrorMessage: true,
+ showSuccessMessage: true
+ })
+}
+
+/**
+ * 删除商品服务
+ * @param service_id
+ * @returns
+ */
+export function deleteServe(service_id: number) {
+ return request.delete(`shop/goods/service/${ service_id }`, { showErrorMessage: true, showSuccessMessage: true })
+}
+
+/**
+ * 获取商品分类树结构
+ * @returns
+ */
+export function getCategoryTree() {
+ return request.get(`shop/goods/tree`)
+}
+
+/**
+ * 获取商品分类列表
+ * @param params
+ * @returns
+ */
+export function getCategoryList(params: Record) {
+ return request.get(`shop/goods/category`, { params })
+}
+
+/**
+ * 获取商品分类详情
+ * @param category_id 商品分类category_id
+ * @returns
+ */
+export function getCategoryInfo(category_id: number) {
+ return request.get(`shop/goods/category/${ category_id }`);
+}
+
+/**
+ * 添加商品分类
+ * @param params
+ * @returns
+ */
+export function addCategory(params: Record) {
+ return request.post('shop/goods/category', params, { showErrorMessage: true, showSuccessMessage: true })
+}
+
+/**
+ * 编辑商品分类
+ * @param params
+ * @returns
+ */
+export function editCategory(params: Record) {
+ return request.put(`shop/goods/category/${ params.category_id }`, params, {
+ showErrorMessage: true,
+ showSuccessMessage: true
+ })
+}
+
+/**
+ * 删除商品分类
+ * @param category_id
+ * @returns
+ */
+export function deleteCategory(category_id: number) {
+ return request.delete(`shop/goods/category/${ category_id }`, { showErrorMessage: true, showSuccessMessage: true })
+}
+
+/**
+ * 拖拽编辑商品分类
+ * @param params
+ * @returns
+ */
+export function updateCategory(params: Record) {
+ return request.post(`shop/goods/category/update`, params, { showErrorMessage: true, showSuccessMessage: true })
+}
+
+/**
+ * 设置商品分类配置
+ * @param params
+ * @returns
+ */
+export function setCategoryConfig(params: Record) {
+ return request.post(`shop/goods/category/config`, params, { showErrorMessage: true, showSuccessMessage: true })
+}
+
+/**
+ * 获取商品分类配置
+ * @returns
+ */
+export function getCategoryConfig() {
+ return request.get(`shop/goods/category/config`);
+}
+
+/**
+ * 获取商品分类树结构供弹框调用
+ * @returns
+ */
+export function getCategoryTreeComponents() {
+ return request.get(`shop/goods/category/components`)
+}
+
+/**
+ * 获取供应商列表
+ * @param params
+ * @returns
+ */
+export function getSupplierList(params: Record) {
+ return request.get(`shop_supplier/supplier/list`, { params })
+}
+
+/**
+ * 获取商品评价列表
+ * @param params
+ * @returns
+ */
+export function getEvaluateList(params: Record) {
+ return request.get(`shop/goods/evaluate`, { params })
+}
+
+/**
+ * 添加商品评价
+ * @param params
+ * @returns
+ */
+export function addEvaluate(params: Record) {
+ return request.post('shop/goods/evaluate', params, { showErrorMessage: true, showSuccessMessage: true })
+}
+
+/**
+ * 删除商品评价
+ * @param evaluate_id
+ * @returns
+ */
+export function deleteEvaluate(evaluate_id: number) {
+ return request.delete(`shop/goods/evaluate/${ evaluate_id }`, { showErrorMessage: true, showSuccessMessage: true })
+}
+
+/**
+ * 商品评价 通过
+ * @param evaluate_id
+ * @returns
+ */
+export function adoptEvaluate(evaluate_id: number) {
+ return request.put(`shop/goods/evaluate/adopt/${ evaluate_id }`, {
+ showErrorMessage: true,
+ showSuccessMessage: true
+ })
+}
+
+/**
+ * 商品评价 拒绝
+ * @param evaluate_id
+ * @returns
+ */
+export function refuseEvaluate(evaluate_id: number) {
+ return request.put(`shop/goods/evaluate/refuse/${ evaluate_id }`, {
+ showErrorMessage: true,
+ showSuccessMessage: true
+ })
+}
+
+/**
+ * 商品评价 回复
+ * @param params
+ * @returns
+ */
+export function replyEvaluate(params: Record) {
+ return request.put(`shop/goods/evaluate/reply/${ params.evaluate_id }`, params, {
+ showErrorMessage: true,
+ showSuccessMessage: true
+ })
+}
+
+/**
+ * 商品评价 置顶
+ * @param evaluate_id
+ * @returns
+ */
+export function toppingEvaluate(evaluate_id: number) {
+ return request.put(`shop/goods/evaluate/topping/${ evaluate_id }`, {
+ showErrorMessage: true,
+ showSuccessMessage: true
+ })
+}
+
+/**
+ * 商品评价 取消置顶
+ * @param evaluate_id
+ * @returns
+ */
+export function cancelToppingEvaluate(evaluate_id: number) {
+ return request.put(`shop/goods/evaluate/cancel_topping/${ evaluate_id }`, {
+ showErrorMessage: true,
+ showSuccessMessage: true
+ })
+}
+
+/**
+ * 获取商品评价状态
+ * @param params
+ * @returns
+ */
+export function getEvaluateStatus() {
+ return request.get(`shop/goods/evaluate/status`)
+}
+
+/**
+ * 批量删除商品评价
+ * @param params
+ * @returns
+ */
+export function batchDelEvaluate(params: Record) {
+ return request.post(`shop/goods/evaluate/batch/del`,params, {
+ showErrorMessage: true,
+ showSuccessMessage: true
+ })
+}
+
+/**
+ * 商品评价 批量通过
+ * @param params
+ * @returns
+ */
+export function batchAdoptEvaluate(params: Record) {
+ return request.post(`shop/goods/evaluate/batch/adopt`,params, {
+ showErrorMessage: true,
+ showSuccessMessage: true
+ })
+}
+
+/**
+ * 商品评价 批量拒绝
+ * @param params
+ * @returns
+ */
+export function batchRefuseEvaluate(params: Record) {
+ return request.post(`shop/goods/evaluate/batch/refuse`,params, {
+ showErrorMessage: true,
+ showSuccessMessage: true
+ })
+}
+
+/**
+ * 获取商品参数分页列表
+ * @param params
+ * @returns
+ */
+export function getAttrPageList(params: Record) {
+ return request.get(`shop/goods/attr`, { params })
+}
+
+/**
+ * 获取商品参数列表
+ * @param params
+ * @returns
+ */
+export function getAttrList(params: Record) {
+ return request.get(`shop/goods/attr/list`, { params })
+}
+
+/**
+ * 获取商品参数详情
+ * @param attr_id 商品参数attr_id
+ * @returns
+ */
+export function getAttrInfo(attr_id: number) {
+ return request.get(`shop/goods/attr/${ attr_id }`);
+}
+
+/**
+ * 添加商品参数
+ * @param params
+ * @returns
+ */
+export function addAttr(params: Record) {
+ return request.post('shop/goods/attr', params, { showErrorMessage: true, showSuccessMessage: true })
+}
+
+/**
+ * 编辑商品参数
+ * @param params
+ * @returns
+ */
+export function editAttr(params: Record) {
+ return request.put(`shop/goods/attr/${ params.attr_id }`, params, {
+ showErrorMessage: true,
+ showSuccessMessage: true
+ })
+}
+
+/**
+ * 删除商品参数
+ * @param attr_id
+ * @returns
+ */
+export function deleteAttr(attr_id: number) {
+ return request.delete(`shop/goods/attr/${ attr_id }`, { showErrorMessage: true, showSuccessMessage: true })
+}
+
+/**
+ * 修改商品参数排序号
+ * @param params
+ */
+export function modifyAttrSort(params: Record) {
+ return request.put(`shop/goods/attr/sort`, params, { showSuccessMessage: true })
+}
+
+/**
+ * 修改商品参数名称
+ * @param params
+ */
+export function modifyAttrName(params: Record) {
+ return request.put(`shop/goods/attr/attr_name`, params, { showSuccessMessage: true })
+}
+
+/**
+ * 修改商品参数值
+ * @param params
+ */
+export function modifyAttrValue(params: Record) {
+ return request.put(`shop/goods/attr/attr_value`, params, { showSuccessMessage: true })
+}
+
+/**
+ * 获取批量设置字典列表
+ * @returns
+ */
+export function getGoodsBatchSetDict() {
+ return request.get(`shop/goods/batchSet/dict`)
+}
+
+/**
+ * 商品批量设置
+ * @param params
+ */
+export function goodsBatchSet(params: Record) {
+ return request.put(`shop/goods/batchSet`, params, { showSuccessMessage: true })
+}
+
+/**
+ * 获取商品搜索配置
+ * @returns
+ */
+export function getGoodsConfigSearch() {
+ return request.get(`shop/goods/config/search`)
+}
+
+/**
+ * 编辑商品搜索配置
+ * @returns
+ */
+export function setGoodsConfigSearch(param: any) {
+ return request.post('shop/goods/config/search', param, { showSuccessMessage: true })
+}
+
+
+/**
+ * 获取商品唯一编码配置
+ * @returns
+ */
+export function getGoodsConfigUnique() {
+ return request.get(`shop/goods/config/unique`)
+}
+
+/**
+ * 编辑商品唯一编码配置
+ * @returns
+ */
+export function setGoodsConfigUnique(param: any) {
+ return request.post('shop/goods/config/unique', param, { showSuccessMessage: true })
+}
+
+/**
+ * 校验商品唯一编码
+
+ * @returns
+ */
+export function goodsVerify(param: any) {
+ return request.post('shop/goods/verify/skuno', param)
+}
+
+/**
+ * 获取商品排序配置
+ * @returns
+ */
+export function getGoodsConfigSort() {
+ return request.get(`shop/goods/config/sort`)
+}
+
+/**
+ * 设置商品排序配置
+ * @returns
+ */
+export function setGoodsConfigSort(param: any) {
+ return request.post('shop/goods/config/sort', param, { showSuccessMessage: true })
+}
+// 上下架
+
+export function editGoodssingleStatus(params: Record) {
+ return request.put(`shop/goods/single/status`, params, { showSuccessMessage: true })
+}
diff --git a/niucloud/addon/shop/admin/api/marketing.ts b/niucloud/addon/shop/admin/api/marketing.ts
new file mode 100644
index 000000000..2a619bd1a
--- /dev/null
+++ b/niucloud/addon/shop/admin/api/marketing.ts
@@ -0,0 +1,692 @@
+import request from '@/utils/request'
+
+/**
+ * 营销中心
+ * @param params
+ * @returns
+ */
+export function getMarketingIndex(params: Record) {
+ return request.get(`shop/marketing`, { params })
+}
+
+/**
+ * 获取商品分类列表
+ * @param params
+ * @returns
+ */
+export function getGoodsCategoryList(params: Record) {
+ return request.get(`shop/goods/coupon/init`, { params })
+}
+
+/**
+ * 添加优惠券
+ * @param params
+ * @returns
+ */
+export function addCoupon(params: Record) {
+ return request.post(`shop/goods/coupon`, params, { showErrorMessage: true, showSuccessMessage: true })
+}
+
+/**
+ * 获取优惠券状态列表
+ * @returns
+ */
+export function getCouponStatusList() {
+ return request.get(`shop/goods/coupon/status`)
+}
+
+/**
+ * 获取优惠券列表
+ * @param params
+ * @returns
+ */
+export function getCouponList(params: Record) {
+ return request.get(`shop/goods/coupon`, { params })
+}
+
+/**
+ * 获取优惠券列表
+ * @param params
+ * @returns
+ */
+export function getCouponSelectList(params: Record) {
+ return request.get(`shop/goods/coupon/select`, { params })
+}
+
+/**
+ * 获取商品分类列表
+ * @param params
+ * @returns
+ */
+export function getSelectedCouponList(params: Record) {
+ return request.get(`shop/goods/coupon/selected`, { params })
+}
+
+/**
+ * 获取优惠券领取记录
+ * @param params
+ * @returns
+ */
+export function getCouponRecords(params: Record) {
+ return request.get(`shop/goods/coupon/records`, { params });
+}
+
+/**
+ * 获取优惠券详情
+ * @param id
+ * @returns
+ */
+export function getCouponInfo(id: number) {
+ return request.get(`shop/goods/coupon/detail/${ id }`);
+}
+
+/**
+ * 优惠券状态变更
+ * @param params
+ * @returns
+ */
+export function editCouponStatus(params: Record) {
+ return request.put(`shop/goods/coupon/setstatus/${ params.status }`, params, { showSuccessMessage: true })
+}
+
+/**
+ * 编辑优惠券
+ * @param params
+ * @returns
+ */
+export function editCoupon(params: Record) {
+ return request.put(`shop/goods/coupon/edit/${ params.id }`, params, {
+ showErrorMessage: true,
+ showSuccessMessage: true
+ })
+}
+
+/**
+ * 删除优惠券
+ * @param params
+ * @returns
+ */
+export function deleteCoupon(params: Record) {
+ return request.post(`shop/goods/coupon/delete`, params, { showSuccessMessage: true })
+}
+
+/**
+ * 关闭优惠券
+ * @param params
+ * @returns
+ */
+export function closeCoupon(params: Record) {
+ return request.put(`shop/goods/coupon/invalid`, params, { showSuccessMessage: true })
+}
+
+/**
+ * 发送优惠券
+ * @param params
+ * @returns
+ */
+export function sendCoupon(params: Record) {
+ return request.post(`shop/goods/coupon/send/${ params.id }`, params, {
+ showErrorMessage: true,
+ showSuccessMessage: true
+ })
+}
+
+/**
+ * 获取优惠券发放记录
+ * @param params
+ * @returns
+ */
+export function getCouponSendRecords(params: Record) {
+ return request.get(`shop/goods/coupon/send/pages/${ params.id }`, { params });
+}
+
+/**
+ * 优惠券init
+ * @returns
+ */
+export function initCoupon() {
+ return request.get(`shop/goods/coupon/send/init`)
+}
+
+/************ 限时折扣 ****************/
+/**
+ * 获取限时折扣列表
+ * @param params
+ * @returns
+ */
+export function getActiveDiscountPageList(params: Record) {
+ return request.get(`shop/active/discount`, { params })
+}
+
+/**
+ * 获取限时折扣状态列表
+ * @returns
+ */
+export function getActiveDiscountStatusList() {
+ return request.get(`shop/active/status`)
+}
+
+/**
+ * 获取指定活动的折扣信息。
+ *
+ * @param active_id 获取基本信息
+ * @returns
+ */
+export function getBasicInformation(active_id: number) {
+ return request.get(`shop/active/discount/info/${ active_id }`);
+}
+
+/**
+ * 获取限时折扣详情 编辑
+ * @param active_id
+ * @returns
+ */
+export function getActiveDiscountInfo(active_id: number) {
+ return request.get(`shop/active/discount/${ active_id }`);
+}
+
+/**
+ * 添加限时折扣
+ * @param params
+ * @returns
+ */
+export function addActiveDiscount(params: Record) {
+ return request.post('shop/active/discount', params, { showErrorMessage: true, showSuccessMessage: true })
+}
+
+/**
+ * 编辑限时折扣
+ * @param params
+ * @returns
+ */
+export function editActiveDiscount(params: Record) {
+ return request.put(`shop/active/discount/${ params.discount_id }`, params, {
+ showErrorMessage: true,
+ showSuccessMessage: true
+ })
+}
+
+/**
+ * 关闭限时折扣
+ * @param active_id
+ * @returns
+ */
+export function closeActiveDiscount(active_id: number) {
+ return request.put(`shop/active/discount/close/${ active_id }`, {}, {
+ showErrorMessage: true,
+ showSuccessMessage: true
+ })
+}
+
+/**
+ * 删除限时折扣
+ * @param active_id
+ * @returns
+ */
+export function deleteActiveDiscount(active_id: number) {
+ return request.delete(`shop/active/discount/${ active_id }`, { showSuccessMessage: true })
+}
+
+/**
+ * 批量关闭限时折扣
+ * @param params
+ * @returns
+ */
+export function batchCloseActiveDiscount(params: Record) {
+ return request.post(`shop/active/discount/batchClose`, params, { showSuccessMessage: true })
+}
+
+/**
+ * 批量删除限时折扣
+ * @param params
+ * @returns
+ */
+export function batchDeleteActiveDiscount(params: Record) {
+ return request.post(`shop/active/discount/batchDelete`, params, { showSuccessMessage: true })
+}
+
+/**
+ * 获取参与限时折扣商品列表
+ * @param params
+ * @returns
+ */
+export function getActiveDiscountGoodsPageList(params: Record) {
+ return request.get(`shop/active/discount/goods/${ params.active_id }`, { params })
+}
+
+/**
+ * 获取参与限时折扣订单列表
+ * @param params
+ * @returns
+ */
+export function getActiveDiscountOrderPageList(params: Record) {
+ return request.get(`shop/active/discount/order/${ params.active_id }`, { params })
+}
+
+/**
+ * 限时折扣商品校验
+ * @param params
+ * @returns
+ */
+export function goodscheck(params: Record) {
+ return request.post(`shop/active/discount/goods/check`, params, {})
+}
+
+/**
+ * 获取参与限时折扣会员列表
+ * @param params
+ * @returns
+ */
+export function getActiveDiscountMemberPageList(params: Record) {
+ return request.get(`shop/active/discount/member/${ params.active_id }`, { params })
+}
+
+/**
+ * 获取活动专题
+ * @returns
+ */
+export function getActiveDiscountConfig() {
+ return request.get(`shop/active/discount/config`);
+}
+
+/**
+ * 编辑活动专题
+ * @param params
+ * @returns
+ */
+export function editActiveDiscountConfig(params: Record) {
+ return request.put(`shop/active/discount/config`, params, {
+ showErrorMessage: true,
+ showSuccessMessage: true
+ })
+}
+
+/********** 积分商品 ***********/
+
+/**
+ * 获取积分商品列表
+ * @param params
+ * @returns
+ */
+export function getActiveExchangePageList(params: Record) {
+ return request.get(`shop/active/exchange`, { params })
+}
+
+/**
+ * 获取积分商品分页列表(用于弹框选择)
+ * @param params
+ * @returns
+ */
+export function getActiveExchangeSelectPageList(params: Record) {
+ return request.get(`shop/active/exchange/select`, { params })
+}
+
+/**
+ * 获取积分商品详情
+ * @param id id
+ * @returns
+ */
+export function getActiveExchangeInfo(id: number) {
+ return request.get(`shop/active/exchange/${ id }`);
+}
+
+/**
+ * 添加积分商品
+ * @param params
+ * @returns
+ */
+export function addActiveExchange(params: Record) {
+ return request.post('shop/active/exchange', params, { showErrorMessage: true, showSuccessMessage: true })
+}
+
+/**
+ * 编辑积分商品
+ * @param params
+ * @returns
+ */
+export function editActiveExchange(params: Record) {
+ return request.put(`shop/active/exchange/${ params.id }`, params, {
+ showErrorMessage: true,
+ showSuccessMessage: true
+ })
+}
+
+/**
+ * 编辑积分商品状态
+ * @param params
+ * @returns
+ */
+export function editActiveExchangeStatus(params: Record) {
+ return request.put(`shop/active/exchange/status/${ params.id }`, params, {
+ showErrorMessage: true,
+ showSuccessMessage: true
+ })
+}
+
+/**
+ * 删除积分商品
+ * @param id
+ * @returns
+ */
+export function deleteActiveExchange(id: number) {
+ return request.delete(`shop/active/exchange/${ id }`, { showSuccessMessage: true })
+}
+
+/**
+ * 批量删除积分商品
+ * @param params
+ * @returns
+ */
+export function batchDeleteActiveExchange(params: Record) {
+ return request.post(`shop/active/exchange/batchDelete`, params, { showSuccessMessage: true })
+}
+
+/**
+ * 批量下架积分商品
+ * @param params
+ * @returns
+ */
+export function batchDownActiveExchange(params: Record) {
+ return request.post(`shop/active/exchange/batchDown`, params, { showSuccessMessage: true })
+}
+
+/**
+ * 批量上架积分商品
+ * @param params
+ * @returns
+ */
+export function batchUpActiveExchange(params: Record) {
+ return request.post(`shop/active/exchange/batchUp`, params, { showSuccessMessage: true })
+}
+
+/**
+ * 获取积分商品状态列表
+ * @returns
+ */
+export function getActiveExchangeStatus() {
+ return request.get(`shop/active/exchange/status`)
+}
+
+/************ 新人专享 ****************/
+
+/**
+ * 获取新人专享设置
+ * @returns
+ */
+export function getActiveNewcomerConfig() {
+ return request.get(`shop/active/newcomer/config`);
+}
+
+/**
+ * 编辑新人专享设置
+ * @param params
+ * @returns
+ */
+export function editActiveNewcomerConfig(params: Record) {
+ return request.put(`shop/active/newcomer/config`, params, {
+ showErrorMessage: true,
+ showSuccessMessage: true
+ })
+}
+
+/**
+ * 获取新人专享列表【首页组件-分页】
+ * @param params
+ * @returns
+ */
+export function getNewcomerGoodsList(params: Record) {
+ return request.get('shop/active/newcomer/goods/select', { params })
+}
+
+/**
+ * 新人专享 - 已选商品列表
+ * @param params
+ * @returns
+ */
+export function getNewcomerSelectGoodsList(params: Record) {
+ return request.get('shop/active/newcomer/goods/selectgoodssku', { params })
+}
+
+/************ 商品榜单 ****************/
+
+/**
+ * 设置排行榜配置
+ * @param params
+ * @returns
+ */
+export function setRankConfig(params: Record) {
+ return request.post('shop/good/rank/config', params, { showErrorMessage: true, showSuccessMessage: true })
+}
+
+/**
+ * 获取排行榜配置
+ * @returns
+ */
+export function getRankConfig() {
+ return request.get(`shop/good/rank/config`)
+}
+
+/**
+ * 获取排行榜列表
+ * @param params
+ * @returns
+ */
+export function getRankPageList(params: Record) {
+ return request.get(`shop/good/rank`, { params })
+}
+
+/**
+ * 获取排行榜选项列表
+ * @returns
+ */
+export function optionData() {
+ return request.get(`shop/good/rank/dict`)
+}
+
+/**
+ * 获取排行榜详情
+ * @param rank_id
+ * @returns
+ */
+export function getRankInfo(rank_id: number) {
+ return request.get(`shop/good/rank/${ rank_id }`);
+}
+
+/**
+ * 添加排行榜
+ * @param params
+ * @returns
+ */
+export function addGoodRank(params: Record) {
+ return request.post('shop/good/rank', params, { showErrorMessage: true, showSuccessMessage: true })
+}
+
+/**
+ * 编辑排行榜
+ * @param params
+ * @returns
+ */
+export function editGoodRank(params: Record) {
+ return request.put(`shop/good/rank/${ params.id }`, params, {
+ showErrorMessage: true,
+ showSuccessMessage: true
+ })
+}
+
+/**
+ * 排行榜状态
+ * @param params
+ * @returns
+ */
+export function editRankStatus(params: Record) {
+ return request.put(`shop/goods/rank/status`, params, {
+ showErrorMessage: true,
+ showSuccessMessage: true
+ })
+}
+
+/**
+ * 删除排行榜
+ * @param id
+ * @returns
+ */
+export function deleteGoodRank(id: number) {
+ return request.delete(`shop/good/rank/${ id }`, { showSuccessMessage: true })
+}
+
+/**
+ * 批量删除排行榜
+ * @param params
+ * @returns
+ */
+export function batchDelete(params: Record) {
+ return request.put(`shop/good/rank/batchDelete`, params, { showSuccessMessage: true })
+}
+
+/**
+ * 排行榜修改排序
+ * @param params
+ * @returns
+ */
+export function modifyGoodsRankSort(params: Record) {
+ return request.put(`shop/good/rank/sort`, params, { showSuccessMessage: true })
+}
+
+/**
+ * 商品排行榜列表
+ * @param params
+ * @returns
+ */
+export function getSelectRankPageList(params: Record) {
+ return request.get(`shop/good/rank/select`, { params })
+}
+
+/************ 满减 ****************/
+
+/**
+ * 获取满减列表
+ * @param params
+ * @returns
+ */
+export function getManjianList(params: Record) {
+ return request.get(`shop/manjian`, { params })
+}
+
+/**
+ * 获取满减状态
+ * @returns
+ */
+export function getManjianStatusList() {
+ return request.get(`shop/manjian/status`)
+}
+
+/**
+ * 添加满减
+ * @param params
+ * @returns
+ */
+export function addManjian(params: Record) {
+ return request.post('shop/manjian', params)
+}
+
+/**
+ * 编辑满减
+ * @param params
+ * @returns
+ */
+export function editManjian(params: Record) {
+ return request.put(`shop/manjian/${ params.id }`, params)
+}
+
+/**
+ * 获取满减详情
+ * @param params
+ * @returns
+ */
+export function getManjianInfo(params: Record) {
+ return request.get(`shop/manjian/init`, { params });
+}
+
+/**
+ * 检查商品
+ * @param params
+ * @returns
+ */
+export function goodsCheck(params: Record) {
+ return request.post('shop/manjian/goods/check', params)
+}
+
+/**
+ * 获取满减详情会员列表
+ * @param params
+ * @returns
+ */
+export function getManjianMemberPageList(params: Record) {
+ return request.get(`shop/manjian/member/${ params.id }`, { params })
+}
+
+/**
+ * 关闭满减
+ * @param manjian_id
+ * @returns
+ */
+export function closeManjian(manjian_id: number) {
+ return request.put(`shop/manjian/close/${ manjian_id }`, {}, {
+ showErrorMessage: true,
+ showSuccessMessage: true
+ })
+}
+
+/**
+ * 获取商品选择列表,代客下单使用
+ * @param params
+ * @returns
+ */
+export function getGoodsSelectByReplaceBuy(params: Record) {
+ return request.get(`shop/goods/buy/goods/select`, { params })
+}
+
+/**
+ * 获取选中商品选择列表,代客下单使用
+ * @param params
+ * @returns
+ */
+export function getGoodsSelectedByReplaceBuy(params: Record) {
+ return request.get(`shop/goods/buy/goods/selected`, { params })
+}
+
+/**
+ * 获取商品规格信息
+ * @param params
+ * @returns
+ */
+export function getGoodsSkuInfo(params: Record) {
+ return request.get(`shop/goods/buy/sku/select`, { params })
+}
+
+/*
+ * 删除满减
+ * @param manjian_id
+ * @returns
+ */
+export function deleteManjian(manjian_id: number) {
+ return request.delete(`shop/manjian/${ manjian_id }`, { showSuccessMessage: true })
+}
+
+/**
+ * 批量删除满减
+ * @param params
+ * @returns
+ */
+export function batchDeleteManjian(params: Record) {
+ return request.put(`shop/manjian/goods/batchDelete`, params, { showSuccessMessage: true })
+}
+
+/**
+ * 批量关闭满减
+ * @param params
+ * @returns
+ */
+export function batchCloseMajian(params: Record) {
+ return request.put(`shop/manjian/goods/batchClose`, params, { showSuccessMessage: true })
+}
diff --git a/niucloud/addon/shop/admin/api/order.ts b/niucloud/addon/shop/admin/api/order.ts
new file mode 100644
index 000000000..fecc0a4fc
--- /dev/null
+++ b/niucloud/addon/shop/admin/api/order.ts
@@ -0,0 +1,281 @@
+import request from '@/utils/request'
+
+/**
+ * 获取交易配置
+ * @returns
+ */
+export function getConfig() {
+ return request.get('shop/order/config')
+}
+
+/**
+ * 编辑交易配置
+ * @returns
+ */
+export function setConfig(param: any) {
+ return request.post('shop/order/config', param, { showSuccessMessage: true })
+}
+
+/**
+ * 获取订单列表
+ * @returns
+ */
+export function getOrderList(params: Record) {
+ return request.get('shop/order/list', { params })
+}
+
+/**
+ * 获取订单列表
+ * @returns
+ */
+export function getOrderDetail(order_id: number) {
+ return request.get(`shop/order/detail/${ order_id }`)
+}
+
+/**
+ * 获取订单状态
+ * @return
+ */
+export function getOrderStatus() {
+ return request.get(`shop/order/status`)
+}
+
+/**
+ * 获取订单类型
+ * @return
+ */
+export function getOrderType() {
+ return request.get(`shop/order/type`)
+}
+
+/**
+ * 订单关闭
+ * @return
+ */
+export function orderClose(order_id: number) {
+ return request.put(`shop/order/close/${ order_id }`)
+}
+
+/**
+ * 订单删除
+ * @return
+ */
+export function orderDelete(params: Record) {
+ return request.post(`shop/order/delete`,params, { showSuccessMessage: true })
+}
+
+
+/**
+ * 获取订单配送方式
+ * @return
+ */
+export function getOrderDeliveryType(params: Record) {
+ return request.get(`shop/order/delivery_type`, { params })
+}
+
+/**
+ * 订单发货
+ * @return
+ */
+export function orderDelivery(params: Record) {
+ return request.put(`shop/order/delivery`, params)
+}
+
+/**
+ * 商家留言
+ * @return
+ */
+export function setShopRemark(params: Record) {
+ return request.put(`shop/order/shop_remark`, params)
+}
+
+/**
+ * 订单完成
+ * @return
+ */
+export function orderFinish(order_id: number) {
+ return request.put(`shop/order/finish/${ order_id }`)
+}
+
+/**
+ * 物流包裹信息(物流跟踪)
+ * @return
+ */
+export function deliveryPackage(params: Record) {
+ return request.get(`shop/order/delivery/package`, { params })
+}
+
+/**
+ * 物流包裹列表
+ * @return
+ */
+export function deliveryPackageList(params: Record) {
+ return request.get(`shop/order/delivery/package/list`, { params })
+}
+
+/**
+ * 退款售后列表
+ * @param {Record} params
+ * @return
+ */
+export function orderRefund(params: Record) {
+ return request.get(`shop/order/refund`, { params })
+}
+
+/**
+ * 退款售后详情
+ */
+export function orderRefundDetail(refund_id: number) {
+ return request.get(`shop/order/refund/${ refund_id }`)
+}
+
+/**
+ * 退款审核
+ * @return
+ */
+export function auditRefund(params: Record) {
+ return request.put(`shop/order/refund/audit/${ params.order_refund_no }`, params)
+}
+
+/**
+ * 退款收货审核
+ * @return
+ */
+export function refundDelivery(params: Record) {
+ return request.put(`shop/order/refund/delivery/${ params.order_refund_no }`, params)
+}
+
+/**
+ * 获取可退款金额
+ */
+export function getRefundMoney(params: Record) {
+ return request.get(`shop/order/refund/refund_money`, { params })
+}
+
+/**
+ * 商家主动退款
+ */
+export function shopActiveRefund(params: Record) {
+ return request.post(`shop/order/refund/active`, params, { showSuccessMessage: true })
+}
+
+/**
+ * 获取发票列表
+ */
+export function getInvoiceList(params: Record) {
+ return request.get(`shop/invoice`, { params })
+}
+
+/**
+ * 获取发票列表
+ */
+export function getInvoiceDetail(id: number) {
+ return request.get(`shop/invoice/${ id }`)
+}
+
+/**
+ * 开具发票
+ */
+export function setInvoice(id: number, params: Record) {
+ return request.put(`shop/invoice/${ id }`, params, { showSuccessMessage: true })
+}
+
+/**
+ * 开发票
+ */
+export function createInvoice(params: Record) {
+ return request.post(`shop/invoice/add`, params, { showSuccessMessage: true })
+}
+
+/**
+ * 发票审核
+ */
+export function auditInvoice(params: Record) {
+ return request.post(`shop/invoice/audit`, params, { showSuccessMessage: true })
+}
+
+/**
+ * 获取支付类型
+ */
+export function getOrderPayType() {
+ return request.get(`shop/order/pay/type`)
+}
+
+/**
+ * 获取订单来源
+ */
+export function getOrderFrom() {
+ return request.get(`shop/order/from`)
+}
+
+/**
+ * 订单调价
+ * @return
+ */
+export function orderEditPrice(params: Record) {
+ return request.put(`shop/order/edit_price`, params, { showSuccessMessage: true })
+}
+
+/**
+ * 获取订单地址信息
+ * @return
+ */
+export function getOrderEditAddress(params: Record) {
+ return request.get(`shop/order/edit_delivery`, { params })
+}
+
+/**
+ * 获取自提点列表
+ * @return
+ */
+export function getDeliveryList() {
+ return request.get(`shop/delivery/store/list`)
+}
+
+/**
+ * 修改地址
+ * @return
+ */
+export function orderEditAddress(params: Record) {
+ return request.put(`shop/order/edit_delivery`, params)
+}
+
+/**
+ * 批量发货列表
+ * @return
+ */
+export function getOrderBatchDeliveryList(params: Record) {
+ return request.get(`shop/order_batch_delivery`, { params })
+}
+
+/**
+ * 批量发货导入
+ * @return
+ */
+export function addBatchOrderDelivery(params: Record) {
+ return request.put(`shop/order_batch_delivery/add_batch_order_delivery`, params)
+}
+
+/**
+ * 获取批量发货状态
+ * @return
+ */
+export function getOrderBatchDeliveryState() {
+ return request.get(`shop/order_batch_delivery/get_status`)
+}
+
+/**
+ * 获取批量发货操作类型
+ * @return
+ */
+export function getOrderBatchDeliveryType() {
+ return request.get(`shop/order_batch_delivery/get_type`)
+}
+
+/**
+ * 关闭售后
+ * @return
+ */
+export function closeRefund(order_refund_no: number) {
+ return request.put(`shop/order/refund/close/${order_refund_no}`)
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/admin/api/shop.ts b/niucloud/addon/shop/admin/api/shop.ts
new file mode 100644
index 000000000..b2bea12c6
--- /dev/null
+++ b/niucloud/addon/shop/admin/api/shop.ts
@@ -0,0 +1,43 @@
+import request from '@/utils/request'
+
+/**
+ * 获取统计总数
+ */
+export function getShopCountList() {
+ return request.get(`shop/stat/total`)
+}
+
+/**
+ * 获取今日统计总数
+ */
+export function getShopTodayCountList() {
+ return request.get(`shop/stat/today`)
+}
+
+/**
+ * 获取昨日统计总数
+ */
+export function getShopYesterdayCountList() {
+ return request.get(`shop/stat/yesterday`)
+}
+
+/**
+ * 获取统计图数据
+ */
+export function getShopStat() {
+ return request.get(`shop/stat`)
+}
+
+/**
+ * 获取订单统计
+ */
+export function getShopOrderStat() {
+ return request.get(`shop/stat/order`)
+}
+
+/**
+ * 获取商品统计
+ */
+export function getShopGoodsStat() {
+ return request.get(`shop/stat/goods`)
+}
diff --git a/niucloud/addon/shop/admin/api/shop_address.ts b/niucloud/addon/shop/admin/api/shop_address.ts
new file mode 100644
index 000000000..450d2ddc5
--- /dev/null
+++ b/niucloud/addon/shop/admin/api/shop_address.ts
@@ -0,0 +1,62 @@
+import request from '@/utils/request'
+
+/**
+ * 获取商家地址库列表
+ * @param params
+ * @returns
+ */
+export function getShopAddressList(params: Record) {
+ return request.get(`shop/shop_address`, { params })
+}
+
+/**
+ * 获取商家地址库详情
+ * @param id 商家地址库id
+ * @returns
+ */
+export function getShopAddressInfo(id: number) {
+ return request.get(`shop/shop_address/${ id }`);
+}
+
+/**
+ * 添加商家地址库
+ * @param params
+ * @returns
+ */
+export function addShopAddress(params: Record) {
+ return request.post('shop/shop_address', params, { showErrorMessage: true, showSuccessMessage: true })
+}
+
+/**
+ * 编辑商家地址库
+ * @param params
+ * @returns
+ */
+export function editShopAddress(params: Record) {
+ return request.put(`shop/shop_address/${ params.id }`, params, { showErrorMessage: true, showSuccessMessage: true })
+}
+
+/**
+ * 删除商家地址库
+ * @param id
+ * @returns
+ */
+export function deleteShopAddress(id: number) {
+ return request.delete(`shop/shop_address/${ id }`, { showErrorMessage: true, showSuccessMessage: true })
+}
+
+/**
+ * 获取商家默认发货地址
+ * @returns
+ */
+export function getShopDefaultDeliveryAddressInfo() {
+ return request.get('shop/shop_address/default/delivery');
+}
+
+/**
+ * 获取商家收货地址
+ * @returns
+ */
+export function getOrderRefundAddress() {
+ return request.get('shop/order/refund/address');
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/admin/api/stat.ts b/niucloud/addon/shop/admin/api/stat.ts
new file mode 100644
index 000000000..e72684a62
--- /dev/null
+++ b/niucloud/addon/shop/admin/api/stat.ts
@@ -0,0 +1,32 @@
+import request from '@/utils/request'
+
+/**
+ * 获取商品统计基本信息
+ * @returns
+ */
+export function getGoodsStatisticsBasic(params: Record) {
+ return request.get('shop/goods/statistics/basic', { params })
+}
+
+/**
+ * 获取商品排行图表统计信息
+ * @returns
+ */
+export function getGoodsStatisticsTrend(params: Record) {
+ return request.get('shop/goods/statistics/trend', { params })
+}
+
+/**
+ * 获取商品排行榜统计类型
+ */
+export function getGoodsStatisticsType() {
+ return request.get(`shop/goods/statistics/type`)
+}
+
+/**
+ * 获取商品排行信息
+ * @returns
+ */
+export function getGoodsStatisticsRank(params: Record) {
+ return request.get('shop/goods/statistics/rank', { params })
+}
diff --git a/niucloud/addon/shop/admin/assets/brand_default.png b/niucloud/addon/shop/admin/assets/brand_default.png
new file mode 100644
index 000000000..d99bddd4c
Binary files /dev/null and b/niucloud/addon/shop/admin/assets/brand_default.png differ
diff --git a/niucloud/addon/shop/admin/assets/category_default.png b/niucloud/addon/shop/admin/assets/category_default.png
new file mode 100644
index 000000000..396bbbc3c
Binary files /dev/null and b/niucloud/addon/shop/admin/assets/category_default.png differ
diff --git a/niucloud/addon/shop/admin/assets/category_style2_new.png b/niucloud/addon/shop/admin/assets/category_style2_new.png
new file mode 100644
index 000000000..36db6fa0c
Binary files /dev/null and b/niucloud/addon/shop/admin/assets/category_style2_new.png differ
diff --git a/niucloud/addon/shop/admin/assets/category_style3_new.png b/niucloud/addon/shop/admin/assets/category_style3_new.png
new file mode 100644
index 000000000..136a13d25
Binary files /dev/null and b/niucloud/addon/shop/admin/assets/category_style3_new.png differ
diff --git a/niucloud/addon/shop/admin/assets/category_style4_new.png b/niucloud/addon/shop/admin/assets/category_style4_new.png
new file mode 100644
index 000000000..c55654240
Binary files /dev/null and b/niucloud/addon/shop/admin/assets/category_style4_new.png differ
diff --git a/niucloud/addon/shop/admin/assets/discount_banner.png b/niucloud/addon/shop/admin/assets/discount_banner.png
new file mode 100644
index 000000000..0f6577ef9
Binary files /dev/null and b/niucloud/addon/shop/admin/assets/discount_banner.png differ
diff --git a/niucloud/addon/shop/admin/assets/discount_config.png b/niucloud/addon/shop/admin/assets/discount_config.png
new file mode 100644
index 000000000..ccef32cbf
Binary files /dev/null and b/niucloud/addon/shop/admin/assets/discount_config.png differ
diff --git a/niucloud/addon/shop/admin/assets/goods_default.png b/niucloud/addon/shop/admin/assets/goods_default.png
new file mode 100644
index 000000000..4a4c75bdc
Binary files /dev/null and b/niucloud/addon/shop/admin/assets/goods_default.png differ
diff --git a/niucloud/addon/shop/admin/assets/store_default.png b/niucloud/addon/shop/admin/assets/store_default.png
new file mode 100644
index 000000000..208d67be1
Binary files /dev/null and b/niucloud/addon/shop/admin/assets/store_default.png differ
diff --git a/niucloud/addon/shop/admin/lang/zh-cn/address.edit.json b/niucloud/addon/shop/admin/lang/zh-cn/address.edit.json
new file mode 100644
index 000000000..a661a0d41
--- /dev/null
+++ b/niucloud/addon/shop/admin/lang/zh-cn/address.edit.json
@@ -0,0 +1,35 @@
+{
+ "contactName": "联系人",
+ "mobile": "联系方式",
+ "provinceId": "省",
+ "cityId": "市",
+ "districtId": "区",
+ "address": "详细地址",
+ "fullAddress": "地址",
+ "lat": "纬度",
+ "lng": "经度",
+ "isDeliveryAddress": "是否是发货地址",
+ "isRefundAddress": "是否是退货地址",
+ "isDefaultDelivery": "默认发货地址",
+ "isDefaultRefund": "默认收货地址",
+ "contactNamePlaceholder": "请输入联系人",
+ "mobilePlaceholder": "请输入联系方式",
+ "mobileTips": "请输入正确的手机号",
+ "addressPlaceholder": "请输入详细地址",
+ "fullAddressPlaceholder": "请输入地址",
+ "latPlaceholder": "请输入纬度",
+ "lngPlaceholder": "请输入经度",
+ "isDeliveryAddressPlaceholder": "请输入是否是发货地址",
+ "isRefundAddressPlaceholder": "请输入是否是退货地址",
+ "isDefaultDeliveryPlaceholder": "请输入默认发货地址",
+ "isDefaultRefundPlaceholder": "请输入默认收货地址",
+ "addShopAddress": "添加商家地址库",
+ "updateShopAddress": "编辑商家地址库",
+ "shopAddressDeleteTips": "确定要删除该商家地址库吗?",
+ "addressType": "地址类型",
+ "deliveryAddress": "发货地址",
+ "refundAddress": "收货地址",
+ "defaultDeliveryAddress": "是否设为默认发货地址",
+ "defaultRefundAddress": "是否设为默认收货地址",
+ "addressTypeRequire": "至少需设置一项类型"
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/admin/lang/zh-cn/address.list.json b/niucloud/addon/shop/admin/lang/zh-cn/address.list.json
new file mode 100644
index 000000000..17372d2e0
--- /dev/null
+++ b/niucloud/addon/shop/admin/lang/zh-cn/address.list.json
@@ -0,0 +1,25 @@
+{
+ "id": "",
+ "contactName": "联系人",
+ "mobile": "联系方式",
+ "mobilePlaceholder": "请输入联系方式",
+ "provinceId": "省",
+ "cityId": "市",
+ "districtId": "区",
+ "address": "详细地址",
+ "fullAddress": "地址",
+ "fullAddressPlaceholder": "请输入地址",
+ "lat": "纬度",
+ "lng": "经度",
+ "isDeliveryAddress": "是否是发货地址",
+ "isRefundAddress": "是否是退货地址",
+ "isDefaultDelivery": "默认发货地址",
+ "isDefaultRefund": "默认收货地址",
+ "addShopAddress": "添加商家地址库",
+ "updateShopAddress": "编辑商家地址库",
+ "shopAddressDeleteTips": "确定要删除该数据吗?",
+ "addressType": "地址类型",
+ "deliveryAddress": "发货地址",
+ "refundAddress": "收货地址",
+ "default": "默认"
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/admin/lang/zh-cn/common.json b/niucloud/addon/shop/admin/lang/zh-cn/common.json
new file mode 100644
index 000000000..0cb7159f3
--- /dev/null
+++ b/niucloud/addon/shop/admin/lang/zh-cn/common.json
@@ -0,0 +1,150 @@
+{
+ "goodsSelectPopupSelectGoodsButton": "选择商品",
+ "rankSelectPopupSelectRankButton": "选择榜单",
+ "goodsSelectPopupSelect": "已选",
+ "goodsSelectPopupPiece": "个",
+ "goodsSelectPopupSelectGoodsDialog": "商品选择",
+ "goodsSelectPopupAllGoods": "全部商品",
+ "defaultGoodsSelect": "默认",
+ "goodsSelectPopupSelectedGoods": "已选商品",
+ "goodsSelectPopupGoodsName": "商品名称",
+ "goodsSelectPopupGoodsNamePlaceholder": "请输入商品名称",
+ "goodsSelectPopupGoodsStatusPlaceholder": "请选择商品状态",
+ "goodsSelectPopupGoodsCategory": "商品分类",
+ "goodsSelectPopupGoodsCategoryPlaceholder": "全部",
+ "goodsSelectPopupGoodsType": "商品类型",
+ "goodsSelectPopupGoodsTypePlaceholder": "请选择商品类型",
+ "goodsSelectPopupGoodsInfo": "商品",
+ "goodsSelectPopupGoodsPointUnit": "积分",
+ "goodsSelectPopupGoodsPriceUnit": "元",
+ "goodsSelectPopupPrice": "价格",
+ "goodsSelectPopupStock": "库存",
+ "goodsSelectPopupBeforeTip": "已选择",
+ "goodsSelectPopupAfterTip": "个商品",
+ "goodsSelectPopupClearGoods": "取消选择",
+ "goodsSelectPopupGoodsMinTip": "所选商品数量不能少于",
+ "goodsSelectPopupGoodsMaxTip": "所选商品数量不能超过",
+ "goodsTextColor": "文字颜色",
+ "textColor": "标题颜色",
+ "subTextColor": "副标题颜色",
+ "wayPlaceholder": "虚拟商品和实物商品只能选择其中一个类型,请重新选择",
+ "goodsStyle": "商品样式",
+ "goodsBgColor": "商品背景",
+ "goodsNameColor": "商品名称",
+ "goodsPriceColor": "销售价",
+ "goodsBtnText": "文本",
+ "goodsBtnTextPlaceholder": "请输入按钮文字",
+ "goodsSaleColor": "商品销量",
+ "goodsBtnColor": "按钮背景",
+ "goodsNumColor": "已兑人数",
+ "goodsBuyBtn": "购买按钮",
+ "goodsShowContent": "显示内容",
+ "goodsBtnResult": "按钮效果",
+ "goodsBtnIsShow": "是否显示",
+ "goodsCartIncident": "点击事件",
+ "goodsAddCart": "加入购物车",
+ "goodsBtnStyle": "样式",
+ "goodsSaleNum": "商品销量",
+ "goodsDetail": "商品详情",
+ "goodsRounded": "圆角",
+ "fenxiaoCommissionPriceColor": "分销佣金",
+ "goodsCategoryPlaceholder": "请选择商品分类",
+ "goodsPlaceholder": "请选择商品",
+ "goodsIsBold": "是否加粗",
+ "goodsLabel": "商品标签",
+ "headStyle1": "样式1",
+ "headStyle2": "样式2",
+ "headStyle3": "样式3",
+ "headStyle4": "样式4",
+ "goodsData": "商品数据",
+ "sortWay": "排序",
+ "default": "综合",
+ "sales": "销量",
+ "price": "价格",
+ "manyGoodsListAroundRadius": "图片圆角",
+ "manyGoodsListCategoryName": "分类名称",
+ "manyGoodsListSubTitle": "副标题",
+ "manyGoodsLisAddItem": "添加一个多商品组",
+ "couponData": "优惠券数据",
+ "couponContent": "优惠券内容",
+ "couponTitle": "标题",
+ "couponTitlePlaceholder": "请输入标题",
+ "couponSubTitle": "副标题",
+ "couponSubTitlePlaceholder": "请输入副标题",
+ "selectCoupon": "选择优惠券",
+ "allSources": "全部",
+ "couponNum": "优惠券数量",
+ "couponPlaceholder": "请选择优惠券",
+ "couponBtnText": "按钮文字",
+ "couponBtnTextPlaceholder": "请输入按钮文字",
+ "couponTitleStyle": "标题样式",
+ "couponTitleColor": "标题颜色",
+ "couponSubTitleColor": "副标题颜色",
+ "couponItemStyle": "优惠券项样式",
+ "couponMoney": "金额颜色",
+ "manyGoodsListCategorySet": "分组设置",
+ "manyGoodsListSourceDiy": "自定义",
+ "manyGoodsListSourceCategory": "商品分类",
+ "goodsSet": "商品设置",
+ "goodsSearchSet": "搜索设置",
+ "goodsSearchText": "搜索内容",
+ "goodsSearchTextPlaceholder": "请输入搜索内容",
+ "shopMemberInfoComponentUidTextColor": "编号颜色",
+ "shopMemberInfoComponentAccountTextColor": "账户颜色",
+ "shopMemberInfoComponentAccount": "账号信息",
+ "shopGoodsRecommendComponentTag": "标签",
+ "shopGoodsRecommendComponentTagColor": "标签颜色",
+ "shopGoodsRecommendComponentTagPlaceholder": "请输入标签内容",
+ "shopGoodsRecommendComponentButtonBorderColor": "按钮边框颜色",
+ "carouselStyle": "轮播样式",
+ "recommendIndicatorStyle": "指示器设置",
+ "recommendIndicatorColor": "常规颜色",
+ "recommendIndicatorActiveColor": "选中颜色",
+ "activeCubeBlockContent": "板块内容",
+ "bgImage": "背景图片",
+ "rankingTitleIcon": "图标",
+ "rankSelect": "榜单选择",
+ "rankName": "榜单名称",
+ "rankNamePlaceholder": "请输入榜单名称",
+ "showGoodsNum": "榜单商品数量",
+ "goodsSourceName": "商品来源",
+ "ruleTypeName": "排序规则",
+ "rankTypeName": "排行周期",
+ "rankSelectPopupAfterTip": "个榜单",
+ "rankSelectPopupGoodsMinTip": "所选榜单数量不能少于",
+ "rankSelectPopupGoodsMaxTip": "所选榜单数量不能超过",
+ "rankingTitleImage": "头部图片",
+ "rankingSubTitle": "副标题",
+ "rankingSubTitleTextColor": "副标题颜色",
+ "rankTextColor": "名称颜色",
+ "rankingSubTitleLink": "副标题链接",
+ "listFrameColor": "背景颜色",
+ "topRounded": "上圆角",
+ "bottomRounded": "下圆角",
+ "imageRounded": "图片圆角",
+ "rankingStyle": "板块样式",
+ "styleRecommend": "风格推荐",
+ "countDownStyle": "倒计时样式",
+ "newcomerNumberColor": "数字颜色",
+ "newcomerNumberBg": "数字背景色",
+ "newcomerOtherColor": "文字颜色",
+ "goodsCategorySelectContentName": "分类名称",
+ "goodsCategorySelectContentImage": "分类图片",
+ "goodsCategorySelectContentPlaceholder": "请选择商品分类",
+ "couponSelectContentTitle": "优惠券名称",
+ "couponSelectContentTitlePlaceholder": "请输入优惠券名称",
+ "couponSelectContentType": "类型",
+ "couponSelectContentPrice": "面值",
+ "couponSelectContentThreshold": "使用门槛",
+ "couponSelectContentTips": "请选择优惠券",
+ "pointExchangeSelectContentTitle": "商品名称",
+ "pointExchangeSelectContentTitlePlaceholder": "请输入商品名称",
+ "pointExchangeSelectContentGoodsInfo": "商品信息",
+ "pointExchangeSelectContentPrice": "兑换价格",
+ "pointExchangeSelectContentPointUnit": "积分",
+ "pointExchangeSelectContentPriceUnit": "元",
+ "pointExchangeSelectContentRedeemedAndSurplus": "已兑/剩余",
+ "pointExchangeSelectContentTips": "请选择积分商品",
+ "categoryName": "分类名称",
+ "categoryImage": "分类图片"
+}
diff --git a/niucloud/addon/shop/admin/lang/zh-cn/delivery.company.json b/niucloud/addon/shop/admin/lang/zh-cn/delivery.company.json
new file mode 100644
index 000000000..770fda74c
--- /dev/null
+++ b/niucloud/addon/shop/admin/lang/zh-cn/delivery.company.json
@@ -0,0 +1,20 @@
+{
+ "companyId": "",
+ "companyIdPlaceholder": "请输入",
+ "companyName": "名称",
+ "companyNamePlaceholder": "请输入物流公司名称",
+ "logo": "LOGO",
+ "logoPlaceholder": "请输入物流公司logo",
+ "url": "网址",
+ "urlPlaceholder": "请输入物流公司网址",
+ "expressNoPlaceholder": "请输入物流公司编号",
+ "expressNoTips": "物流公司编号作用于物流查询,请根据物流跟踪对应配置设置编号",
+ "expressNoKd100": "快递100物流跟踪编号",
+ "expressNoKd100Placeholder": "请输入快递100物流跟踪编号",
+ "addCompany": "添加物流公司",
+ "updateCompany": "编辑物流公司",
+ "electronicSheetSwitchName": "是否支持电子面单",
+ "expressNoElectronicSheet": "快递鸟电子面单编号",
+ "expressNo": "快递鸟物流跟踪编号",
+ "companyDeleteTips": "确定要删除该数据吗?"
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/admin/lang/zh-cn/delivery.company_edit.json b/niucloud/addon/shop/admin/lang/zh-cn/delivery.company_edit.json
new file mode 100644
index 000000000..fa1f2cb77
--- /dev/null
+++ b/niucloud/addon/shop/admin/lang/zh-cn/delivery.company_edit.json
@@ -0,0 +1,44 @@
+{
+ "companyId": "",
+ "companyIdPlaceholder": "请输入",
+ "companyName": "名称",
+ "companyNamePlaceholder": "请输入物流公司名称",
+ "logo": "LOGO",
+ "logoPlaceholder": "请输入物流公司logo",
+ "url": "网址",
+ "urlPlaceholder": "请输入物流公司网址",
+ "expressNo": "快递鸟物流跟踪编号",
+ "expressNoPlaceholder": "请输入快递鸟物流公司编号",
+ "expressNoTips": "物流公司编号作用于物流查询,请根据物流跟踪对应配置设置编号",
+ "expressNoKd100": "快递100物流跟踪编号",
+ "expressNoKd100Placeholder": "请输入快递100物流跟踪编号",
+ "addCompany": "添加物流公司",
+ "updateCompany": "编辑物流公司",
+ "expressNoElectronicSheet": "快递鸟电子面单编号",
+ "expressNoElectronicSheetPlaceholder": "请输入快递鸟电子面单编号",
+ "expressNoElectronicSheetTips": "电子面单编号作用于电子面单查询,请根据电子面单对应配置设置编号",
+ "printStyle": "模板样式",
+ "addPrintStyle": "添加模板样式",
+ "expType": "业务类型",
+ "addExpType": "添加业务类型",
+ "expTypeName": "业务名称",
+ "expTypeTextTips": "业务名称不能为空",
+ "expTypeValueTips": "业务值不能为空",
+ "expTypeTextRepeatTips": "业务名称不可以重复,请重新填写",
+ "expTypeValueRepeatTips": "业务值不可以重复,请重新填写",
+ "expTypeValueNullTips": "业务值不可以为零",
+ "expTypeValue": "业务值",
+ "electronicSheetSwitch": "是否支持电子面单",
+ "printStyleName": "模板名称",
+ "printStyleNameTips": "模板名称不能为空",
+ "printStyleSizeTips": "模板尺寸不能为空",
+ "printStyleNameRepeatTips": "模板名称不可以重复,请重新填写",
+ "printStyleSizeRepeatTips": "模板尺寸不可以重复,请重新填写",
+ "printStyleId": "模板尺寸",
+ "expTypeTips": "快递鸟业务类型",
+ "expTypeTips1": "不填默认为1",
+ "printStyleTips": "快递鸟模版规格(常用)",
+ "printStyleTips1": "主流快递单打印纸尺寸一般为:76*130,100*180(单位mm)",
+ "printStyleTips2": "不填写则取物流公司的默认模板",
+ "examine": "点击查看"
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/admin/lang/zh-cn/delivery.config.json b/niucloud/addon/shop/admin/lang/zh-cn/delivery.config.json
new file mode 100644
index 000000000..b177cd0eb
--- /dev/null
+++ b/niucloud/addon/shop/admin/lang/zh-cn/delivery.config.json
@@ -0,0 +1,11 @@
+{
+ "store": "启动门店自提后,买家可选择自提点提货。",
+ "express": "启用物流配送后,买家下单可以选择快递发货。",
+ "local_delivery": "启用同城配送后,在配送范围内的买家可以选择同城配送。",
+ "deliveryStaff": "配送员",
+ "deliveryCompany": "物流公司",
+ "deliveryTemplate": "运费模版",
+ "deliverySearch": "物流跟踪",
+ "deliveryStore": "自提点",
+ "localConfig": "同城配送设置"
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/admin/lang/zh-cn/delivery.electronic_sheet.json b/niucloud/addon/shop/admin/lang/zh-cn/delivery.electronic_sheet.json
new file mode 100644
index 000000000..4b72fa8bb
--- /dev/null
+++ b/niucloud/addon/shop/admin/lang/zh-cn/delivery.electronic_sheet.json
@@ -0,0 +1,17 @@
+{
+ "tabESTemplate": "电子面单模板",
+ "tabESConfig": "设置",
+ "templateName": "模板名称",
+ "templateNamePlaceholder": "请输入模板名称",
+ "expressCompany": "物流公司",
+ "expressCompanyPlaceholder": "请选择物流公司",
+ "status": "状态",
+ "statusOn": "开启",
+ "statusOff": "关闭",
+ "addElectronicSheet": "添加电子面单",
+ "payType": "邮费支付方式",
+ "isDefault": "默认",
+ "setDefault": "设为默认",
+ "electronicSheetDeleteTips": "确定要删除该数据吗?",
+ "electronicSheetSetDefaultTips": "确定要设置为默认模版吗?"
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/admin/lang/zh-cn/delivery.electronic_sheet_config.json b/niucloud/addon/shop/admin/lang/zh-cn/delivery.electronic_sheet_config.json
new file mode 100644
index 000000000..b8fdb16ad
--- /dev/null
+++ b/niucloud/addon/shop/admin/lang/zh-cn/delivery.electronic_sheet_config.json
@@ -0,0 +1,21 @@
+{
+ "tabESTemplate": "电子面单模板",
+ "tabESConfig": "设置",
+ "apiSet": "接口设置",
+ "interfaceType": "接口类型",
+ "prompt": "提示",
+ "promptTips1-1": "请到快递鸟官网申请",
+ "kdn": "快递鸟",
+ "kdnEBusinessIDLabel": "用户ID",
+ "kdnEBusinessIDPlaceholder": "请输入快递鸟用户ID",
+ "kdnEBusinessIDTips": "快递鸟用户ID,EBusinessID",
+ "kdnAppKeyPlaceholder": "请输入快递鸟API key",
+ "kdnAppKeyTips": "快递鸟分配的API key",
+ "printerSet": "打印机设置",
+ "serverPort1": "服务器端口1",
+ "serverPort1Placeholder": "请输入服务器端口1",
+ "serverPort2": "服务器端口2",
+ "serverPort2Placeholder": "请输入服务器端口2",
+ "httpsPort": "HTTPS端口",
+ "httpsPortPlaceholder": "请输入HTTPS端口"
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/admin/lang/zh-cn/delivery.electronic_sheet_edit.json b/niucloud/addon/shop/admin/lang/zh-cn/delivery.electronic_sheet_edit.json
new file mode 100644
index 000000000..94a310abc
--- /dev/null
+++ b/niucloud/addon/shop/admin/lang/zh-cn/delivery.electronic_sheet_edit.json
@@ -0,0 +1,34 @@
+{
+ "basicSettings": "基础设置",
+ "otherSettings": "其他设置",
+ "templateName": "模板名称",
+ "templateNamePlaceholder": "请输入模板名称",
+ "expressCompany": "物流公司",
+ "expressCompanyPlaceholder": "请选择物流公司",
+ "expType": "业务类型",
+ "status": "状态",
+ "customerName": "CustomerName",
+ "customerNamePlaceholder": "请输入电子面单客户账号",
+ "customerPwd": "CustomerPwd",
+ "customerPwdTips": "电子面单密码,不同快递叫法不同,例如:密码、密钥、客户编号",
+ "sendSite": "SendStaff",
+ "sendSiteTips": "不同快递叫法不同,例如:网点编码、网点编号、网点名称",
+ "sendStaff": "SendStaff",
+ "sendStaffTips": "不同快递叫法不同,例如:收件快递员、取件员编号、网点名称",
+ "monthCode": "MonthCode",
+ "monthCodeTips": "不同快递叫法不同,例如:月结号、密钥、月结编码",
+ "payType": "邮费支付方式",
+ "isNotice": "快递员上门揽件",
+ "yes": "是",
+ "no": "否",
+ "isNoticeTips": "是否通知快递员上门揽件,跨越速运,京东快运,电商标快,填舱标快,填舱电标等业务类型必填",
+ "printStyle": "模板样式",
+ "printStylePlaceholder": "请选择模板样式",
+ "printStyleTips": "快递鸟模版规格(常用)",
+ "printStyleTips1": "主流快递单打印纸尺寸一般为:76*130,100*180(单位mm)",
+ "printStyleTips2": "不填写则取物流公司的默认模板",
+ "isDefault": "是否默认",
+ "examine": "点击查看",
+ "customerNameTips": "快递鸟电子面单账号申请",
+ "customerNameTips1": "电子面单账号对照表"
+}
diff --git a/niucloud/addon/shop/admin/lang/zh-cn/delivery.local.json b/niucloud/addon/shop/admin/lang/zh-cn/delivery.local.json
new file mode 100644
index 000000000..b6fe7d276
--- /dev/null
+++ b/niucloud/addon/shop/admin/lang/zh-cn/delivery.local.json
@@ -0,0 +1,91 @@
+{
+ "basicSettings": "同城配送基础设置",
+ "timeIsOpen": "配送时间设置",
+ "timeIsOpenTips": "开启后,买家下单选择同城配送时,可选择配送时间,提交订单后,将在买家备注中显示。关闭后,买家下单默认为立即配送",
+ "close": "关闭",
+ "open": "开启",
+ "everyDay": "每天",
+ "monday": "周一",
+ "tuesday": "周二",
+ "wednesday": "周三",
+ "thursday": "周四",
+ "friday": "周五",
+ "saturday": "周六",
+ "sunday": "周日",
+ "timeWeekRequire": "请选择配送时间",
+ "deliveryTimeSetting": "配送时间设置",
+ "feeType": "收费标准",
+ "region": "按区域收取配送费",
+ "distance": "按距离收取配送费",
+ "district": "按行政区域收取配送费",
+ "feeSetting": "费用设置",
+ "weightFee": "续重收费",
+ "feeSettingTextOne": "km内按",
+ "feeSettingTextTwo": "元收取配送费,每超出",
+ "feeSettingTextThree": "km费用增加",
+ "priceUnit": "元",
+ "weightFeeTextOne": "商品重量",
+ "weightFeeTextTwo": "kg 内不额外收费,每超出",
+ "weightFeeTextThree": "kg 费用增加",
+ "areaName": "区域名称",
+ "startPrice": "起送价",
+ "deliveryPrice": "配送费",
+ "areaType": "划分方式",
+ "radius": "半径",
+ "custom": "自定义",
+ "addDeliveryArea": "添加配送区域",
+ "baseDistRequire": "请输入起始公里数",
+ "gradDistRequire": "请输入超出公里数",
+ "basePriceRequire": "请输入起始公里内的配送费用",
+ "gradPriceRequire": "请输入每超出公里部分的费用",
+ "areaNameRequire": "请输入区域名称",
+ "startPriceRequire": "请输入起送价",
+ "startPriceMin": "起送价不能小于0",
+ "deliveryPriceRequire": "请输入配送费",
+ "deliveryPriceMin": "配送费不能小于0",
+ "areaPlaceholder": "请添加配送区域",
+ "deliveryType": "配送方式",
+ "business": "商家自配送",
+ "deliveryTypeRequire": "至少需选择一种配送方式",
+ "deliveryAddress": "取货地址",
+ "defaultDeliveryAddressEmpty": "请先配置默认发货地址",
+ "toSetting": "去配置",
+ "update": "修改",
+ "deliveryAddressChange": "取货地址已变更请注意是否需重新调整配送区域",
+ "tradeTimePlaceholderTwo": "请选择自提时段",
+ "tradeTimePlaceholderThree": "请选择细分时段",
+ "tradeTimePlaceholderFour": "结束时间不能小于或等于开始时间",
+ "tradeTimePlaceholderFive": "后一个时间段的开始时间不能小于前一个时间段的结束时间",
+ "thrid":"三方配送",
+ "AppKey":"AppKey",
+ "AppSecret":"AppSecret",
+ "shopId":"商户ID",
+ "shopStoreNo":"商户门店编号",
+ "AppKeyRequire":"请输入AppKey",
+ "AppSecretRequire":"请输入AppSecret",
+ "shopIdRequire":"请输入商户ID",
+ "shopStoreNoRequire":"请输入商户门店编号",
+ "deliveryTime":"配送时段设置",
+ "startTime":"开始时间",
+ "endTime":"结束时间",
+ "timeInterval":"细分时段",
+ "addTime":"添加配送时段",
+ "deliveryTimeTips":"配送时段设置,若不在配送时段内,则无法进行配送",
+ "30minute": "30分钟",
+ "90minute": "90分钟",
+ "oneHour": "一小时",
+ "twoHour": "两小时",
+ "advancaDay": "提前预约",
+ "advance": "提前",
+ "day": "天",
+ "reservationAvailable":"可预约",
+ "withinDays":"天内",
+ "advanceTips": "若设置了提前预约,则用户在当前日期前多少天可以预约配送,不可以立即配送",
+ "mostDays": "最长预约",
+ "mostDaysTips": "预约配送最长可预约多少天内进行提货",
+ "formatError": "格式不正确",
+ "notLessThanZero": "不能小于0",
+ "mustBeGreaterThanZero": "必须大于0",
+ "thridRequire": "请选择一个三方配送服务",
+ "thridSeting": "请填写完整的三方配送配置"
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/admin/lang/zh-cn/delivery.search.json b/niucloud/addon/shop/admin/lang/zh-cn/delivery.search.json
new file mode 100644
index 000000000..99cd99416
--- /dev/null
+++ b/niucloud/addon/shop/admin/lang/zh-cn/delivery.search.json
@@ -0,0 +1,21 @@
+{
+ "prompt": "提示",
+ "promptTips1-1": "请到快递鸟官网申请",
+ "promptTips1-2": "1、按单付费查询,相同单号查询多次计费一次(代码8001)",
+ "promptTips1-3": "2、按次付费查询,相同单号查询多次计费多次(代码8002)",
+ "promptTips2": "请到快递100官网申请",
+ "interfaceType": "接口类型",
+ "kdn": "快递鸟",
+ "kd100": "快递100",
+ "kdnEBusinessIDPlaceholder": "请输入快递鸟EBusinessID",
+ "kdnEBusinessIDTips": "快递鸟电商ID",
+ "kdnAppKeyPlaceholder": "请输入快递鸟AppKey",
+ "kdnAppKeyTips": "快递鸟分配的电商加密私钥",
+ "isPayEdition": "套餐类型",
+ "PayPerUse": "按次付费",
+ "PayPerOrder": "按单付费",
+ "kd100AppKeyPlaceholder": "请输入快递100AppKey",
+ "kd100AppKeyTips": "快递100应用密钥",
+ "kd100CustomerPlaceholder": "请输入快递100Customer",
+ "kd100CustomerTips": "快递100分配给的公司编号"
+}
diff --git a/niucloud/addon/shop/admin/lang/zh-cn/delivery.staff.json b/niucloud/addon/shop/admin/lang/zh-cn/delivery.staff.json
new file mode 100644
index 000000000..75c0f0755
--- /dev/null
+++ b/niucloud/addon/shop/admin/lang/zh-cn/delivery.staff.json
@@ -0,0 +1,9 @@
+{
+ "addDeliveryPersonnel": "添加配送员",
+ "updateDeliver": "编辑配送员",
+ "deliverName": "配送员名称",
+ "deliverMobile": "配送员手机号",
+ "deliverNamePlaceholder": "请输入配送员名称",
+ "deliverMobilePlaceholder": "请输入配送员手机号",
+ "deliverDeleteTips": "确定要删除该数据吗?"
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/admin/lang/zh-cn/delivery.store.json b/niucloud/addon/shop/admin/lang/zh-cn/delivery.store.json
new file mode 100644
index 000000000..33ad259e6
--- /dev/null
+++ b/niucloud/addon/shop/admin/lang/zh-cn/delivery.store.json
@@ -0,0 +1,18 @@
+{
+ "storeId": "",
+ "storeName": "自提点信息",
+ "storeNamePlaceholder": "请输入自提点名称",
+ "storeLogo": "自提点logo",
+ "storeMobile": "联系电话",
+ "address": "详细地址",
+ "fullAddress": "联系地址",
+ "longitude": "经度",
+ "latitude": "纬度",
+ "tradeTime": "营业时间",
+ "createTime": "添加时间",
+ "createTimePlaceholder": "请输入添加时间",
+ "addStore": "添加自提点",
+ "updateStore": "编辑自提点",
+ "storeDeleteTips": "确定要删除该数据吗?",
+ "storeInfo": "自提点信息"
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/admin/lang/zh-cn/delivery.store_edit.json b/niucloud/addon/shop/admin/lang/zh-cn/delivery.store_edit.json
new file mode 100644
index 000000000..6cd0427df
--- /dev/null
+++ b/niucloud/addon/shop/admin/lang/zh-cn/delivery.store_edit.json
@@ -0,0 +1,60 @@
+{
+ "storeName": "自提点名称",
+ "storeDesc": "简介",
+ "storeLogo": "自提点logo",
+ "storeMobile": "手机号",
+ "provinceId": "省id",
+ "cityId": "市",
+ "districtId": "县(区)",
+ "address": "详细地址",
+ "fullAddress": "完整地址",
+ "longitude": "经度",
+ "latitude": "纬度",
+ "tradeTime": "营业时间",
+ "createTime": "下单时间",
+ "updateTime": "更新时间",
+ "storeNamePlaceholder": "请输入自提点名称",
+ "storeDescPlaceholder": "请输入简介",
+ "storeLogoPlaceholder": "请上传自提点logo",
+ "storeMobilePlaceholder": "请输入手机号",
+ "provinceIdPlaceholder": "请选择省id",
+ "cityIdPlaceholder": "请选择市",
+ "districtIdPlaceholder": "请选择县(区)",
+ "addressPlaceholder": "请输入详细地址",
+ "fullAddressPlaceholder": "请输入完整地址",
+ "longitudePlaceholder": "请输入经度",
+ "latitudePlaceholder": "请输入纬度",
+ "tradeTimePlaceholder": "请输入营业时间",
+ "tradeTimeTips": "例:上午9:00-12:00,下午2:00-6:00",
+ "createTimePlaceholder": "请选择添加时间",
+ "updateTimePlaceholder": "请输入更新时间",
+ "addStore": "添加自提点",
+ "updateStore": "编辑自提点",
+ "storeDeleteTips": "确定要删除该自提点吗?",
+ "storeAddress": "自提点地址",
+ "storeAddressPlaceholder": "请选择自提点地址",
+ "storeAddressDetail": "自提点详细地址",
+ "storeAddressDetailPlaceholder": "请输入自提点详细地址",
+ "storeTime": "自提时段",
+ "storeDate": "自提日期",
+ "addTimeRange": "添加时段",
+ "storeTimeInterval": "细分时段",
+ "monday": "周一",
+ "tuesday": "周二",
+ "wednesday": "周三",
+ "thursday": "周四",
+ "friday": "周五",
+ "saturday": "周六",
+ "sunday": "周日",
+ "minute": "分钟",
+ "hour": "小时",
+ "startTime": "开始时间",
+ "endTime": "结束时间",
+ "tradeTimePlaceholderTwo": "请选择自提时段",
+ "selectBusinessDays": "请选择自提日期",
+ "tradeTimePlaceholderThree": "请选择细分时段",
+ "tradeTimePlaceholderFour": "结束时间不能小于或等于开始时间",
+ "tradeTimePlaceholderFive": "后一个时间段的开始时间不能小于前一个时间段的结束时间",
+ "storeDateTips": "所设时间段为可自提时间段,可通过“细分时段”对该自提时段进一步切分",
+ "storeTimeIntervalTips": "对上方的“自提时段”进行切分,在手机端上将显示切换后的时段供用户选择"
+}
diff --git a/niucloud/addon/shop/admin/lang/zh-cn/delivery.template.json b/niucloud/addon/shop/admin/lang/zh-cn/delivery.template.json
new file mode 100644
index 000000000..7a4d8cb77
--- /dev/null
+++ b/niucloud/addon/shop/admin/lang/zh-cn/delivery.template.json
@@ -0,0 +1,12 @@
+{
+ "templateName": "运费模板名称",
+ "templateNamePlaceholder": "请输入运费模板名称",
+ "createTime": "创建时间",
+ "addTemplate": "添加运费模板",
+ "updateTemplate": "编辑运费模板",
+ "templateDeleteTips": "确定要删除该模板吗?",
+ "feeTypeName": "计费类型",
+ "freeShipping": "指定区域包邮",
+ "open": "启用",
+ "close": "关闭"
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/admin/lang/zh-cn/delivery.template_edit.json b/niucloud/addon/shop/admin/lang/zh-cn/delivery.template_edit.json
new file mode 100644
index 000000000..9ebaa81d5
--- /dev/null
+++ b/niucloud/addon/shop/admin/lang/zh-cn/delivery.template_edit.json
@@ -0,0 +1,39 @@
+{
+ "templateName": "运费模板名称",
+ "templateNamePlaceholder": "请输入运费模板名称",
+ "createTime": "创建时间",
+ "addTemplate": "添加运费模板",
+ "updateTemplate": "编辑运费模板",
+ "templateDeleteTips": "确定要删除该模板吗?",
+ "feeTypeName": "计费类型",
+ "isDefault": "默认模板",
+ "num": "按件",
+ "weight": "按重量",
+ "volume": "按体积",
+ "feeSetting": "费用设置",
+ "selectArea": "选择地区",
+ "firstNum": "首件(件)",
+ "continueNum": "续件(件)",
+ "firstWeight": "首件重量(kg)",
+ "fee": "运费(元)",
+ "continueFee": "续费(元)",
+ "continueWeight": "续件重量(kg)",
+ "firstVolume": "首件体积(m³)",
+ "continueVolume": "续件体积(m³)",
+ "deliveryArea": "配送区域",
+ "addDeliveryArea": "添加单独配送区域",
+ "freeShipping": "指定区域包邮",
+ "freeShippingArea": "包邮区域",
+ "addFreeShippingArea": "添加包邮区域",
+ "freeShippingAreaTips": "两个条件满足其一便可以包邮",
+ "noDelivery": "不配送区域",
+ "addNoDelivery": "添加不配送区域",
+ "freeShippingNum": "包邮件数",
+ "freeShippingWeight": "包邮重量(kg)",
+ "freeShippingVolume": "包邮体积(m³)",
+ "freeShippingPrice": "包邮金额",
+ "areaPlaceholder": "请选择地区",
+ "noDeliveryPlaceholder": "请选择不配送的地区",
+ "freeShippingPlaceholder": "请选择包邮的地区",
+ "notUnderZero": "不能小于等于0"
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/admin/lang/zh-cn/goods.attr.json b/niucloud/addon/shop/admin/lang/zh-cn/goods.attr.json
new file mode 100644
index 000000000..419ae1752
--- /dev/null
+++ b/niucloud/addon/shop/admin/lang/zh-cn/goods.attr.json
@@ -0,0 +1,10 @@
+{
+ "attrName": "参数模板名称",
+ "attrNamePlaceholder": "请输入参数模板名称",
+ "sortPlaceholder": "请输入排序号",
+ "addShopGoodsAttr": "添加参数模板",
+ "updateShopGoodsAttr": "编辑参数模板",
+ "goodsAttrDeleteTips": "确定要删除该数据吗?",
+ "sortTips": "排序号格式输入错误",
+ "manage": "管理"
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/admin/lang/zh-cn/goods.attr_edit.json b/niucloud/addon/shop/admin/lang/zh-cn/goods.attr_edit.json
new file mode 100644
index 000000000..0c03e2aeb
--- /dev/null
+++ b/niucloud/addon/shop/admin/lang/zh-cn/goods.attr_edit.json
@@ -0,0 +1,18 @@
+{
+ "attrName": "参数模板名称",
+ "attrNamePlaceholder": "请输入参数名称",
+ "updateAttr": "编辑参数模板",
+ "sort": "排序号",
+ "sortPlaceholder": "请输入排序号",
+ "addShopGoodsAttr": "添加商品参数",
+ "attrValueType": "参数类型",
+ "attrValueTypeRadio": "单选",
+ "attrValueTypeCheckbox": "多选",
+ "attrValueTypeText": "输入",
+ "attrValueChild": "参数内容",
+ "updateShopGoodsAttr": "编辑商品参数",
+ "goodsAttrDeleteTips": "确定要删除该数据吗?",
+ "attrValueName": "参数名称",
+ "addAttrValue": "添加参数",
+ "attrValueNamePlaceholder": "请输入参数名称"
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/admin/lang/zh-cn/goods.brand_list.json b/niucloud/addon/shop/admin/lang/zh-cn/goods.brand_list.json
new file mode 100644
index 000000000..038d763f5
--- /dev/null
+++ b/niucloud/addon/shop/admin/lang/zh-cn/goods.brand_list.json
@@ -0,0 +1,19 @@
+{
+ "brandId": "品牌ID",
+ "brandIdPlaceholder": "请输入品牌ID",
+ "brandName": "品牌名称",
+ "brandNamePlaceholder": "请输入品牌名称",
+ "logo": "品牌logo",
+ "logoPlaceholder": "请输入品牌logo",
+ "desc": "品牌介绍",
+ "descPlaceholder": "请输入品牌介绍",
+ "sort": "排序",
+ "sortPlaceholder": "请输入排序",
+ "addBrand": "添加商品品牌",
+ "updateBrand": "编辑商品品牌",
+ "brandDeleteTips": "确定要删除该数据吗?",
+ "textColor": "文字颜色",
+ "bgColor": "背景颜色",
+ "borderColor": "边框颜色",
+ "colorTips": "若未设置颜色,则为默认色"
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/admin/lang/zh-cn/goods.category.json b/niucloud/addon/shop/admin/lang/zh-cn/goods.category.json
new file mode 100644
index 000000000..89624234b
--- /dev/null
+++ b/niucloud/addon/shop/admin/lang/zh-cn/goods.category.json
@@ -0,0 +1,26 @@
+{
+ "categoryId": "商品分类id",
+ "categoryIdPlaceholder": "请输入商品分类id",
+ "categoryName": "分类名称",
+ "categoryNamePlaceholder": "请输入分类名称",
+ "image": "分类图片",
+ "imagePlaceholder": "请输入分类图片",
+ "pid": "上级分类",
+ "pidPlaceholder": "请选择上级分类",
+ "categoryFullName": "组装分类名称",
+ "categoryFullNamePlaceholder": "请输入组装分类名称",
+ "isShow": "是否显示",
+ "sort": "排序",
+ "sortPlaceholder": "请输入排序号",
+ "addCategory": "添加商品分类",
+ "updateCategory": "编辑商品分类",
+ "categoryDeleteTips": "确定要删除该数据吗?",
+ "categoryDeleteTips1": "子级分类也会删除,确定要删除该数据吗?",
+ "spreadGoodsCategory": "推广",
+ "goodsCategorySpreadTitle": "商品分类推广",
+ "spreadLink": "推广链接",
+ "copy": "复制",
+ "downloadQrcode": "下载二维码",
+ "tabGoodsCategory": "商品分类",
+ "tabGoodsCategoryConfig": "分类设置"
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/admin/lang/zh-cn/goods.category_config.json b/niucloud/addon/shop/admin/lang/zh-cn/goods.category_config.json
new file mode 100644
index 000000000..9c9dcbcb2
--- /dev/null
+++ b/niucloud/addon/shop/admin/lang/zh-cn/goods.category_config.json
@@ -0,0 +1,27 @@
+{
+ "categoryTemplate": "分类模板",
+ "categoryType": "分类类型",
+ "categorystyleOne": "一级分类",
+ "categorystyleTwo": "二级分类",
+ "pageSettings": "页面设置",
+ "pageTitle": "页面名称",
+ "pageTitlePlaceholder": "请输入页面名称",
+ "searchControl": "搜索栏",
+ "searchTitle": "搜索栏文字",
+ "searchTitlePlaceholder": "请输入搜索栏文字",
+ "open": "开启",
+ "close": "关闭",
+ "goodsStyle": "商品排列",
+ "singleCols": "单列",
+ "doubleCols": "双列",
+ "sort": "商品排序",
+ "sortPlaceholder": "请选择商品排序",
+ "cartControl": "购物车显示",
+ "cartStyle": "购物车样式",
+ "cartTextPlaceholder": "请输入购物车按钮文字",
+ "cartEvent": "点击按钮",
+ "detail": "跳转商品详情",
+ "cart": "加入购物车",
+ "tabGoodsCategory": "商品分类",
+ "tabGoodsCategoryConfig": "分类设置"
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/admin/lang/zh-cn/goods.evaluate.json b/niucloud/addon/shop/admin/lang/zh-cn/goods.evaluate.json
new file mode 100644
index 000000000..839a9197a
--- /dev/null
+++ b/niucloud/addon/shop/admin/lang/zh-cn/goods.evaluate.json
@@ -0,0 +1,59 @@
+{
+ "evaluateId": "",
+ "evaluateIdPlaceholder": "请输入",
+ "orderId": "订单id",
+ "orderIdPlaceholder": "请输入订单id",
+ "orderGoodsId": "订单项ID",
+ "orderGoodsIdPlaceholder": "请输入订单项ID",
+ "goodsId": "商品ID",
+ "goodsIdPlaceholder": "请选择商品",
+ "memberId": "会员ID",
+ "memberIdPlaceholder": "请输入会员ID",
+ "content": "评价内容",
+ "contentPlaceholder": "请输入评价内容",
+ "images": "评价图片",
+ "imagesPlaceholder": "请输入评价图片",
+ "isAnonymous": "是否匿名",
+ "anonymous": "匿名",
+ "notAnonymous": "不匿名",
+ "scores": "评价等级",
+ "scoresPlaceholder": "请输入评价分数 1-5",
+ "auditName": "审核状态",
+ "explainFirst": "商家回复",
+ "explainFirstPlaceholder": "请输入商家回复",
+ "createTime": "评价时间",
+ "createTimePlaceholder": "请输入评价时间",
+ "again": "追评",
+ "againTime": "追评时间",
+ "againTimePlaceholder": "请输入追评时间",
+ "isShow": "是否显示",
+ "show": "显示",
+ "notShow": "不显示",
+ "isShowPlaceholder": "请输入是否显示 1显示 2不显示",
+ "addEvaluate": "添加自评",
+ "updateEvaluate": "编辑商品评价",
+ "evaluateDeleteTips": "确定要删除该数据吗?",
+ "goodsInfo": "商品信息",
+ "memberHead": "会员头像",
+ "memberName": "会员名称",
+ "memberNamePlaceholder": "请输入会员名称",
+ "adopt": "通过",
+ "refuse": "拒绝",
+ "auditAdoptTips": "确定要通过审核吗?",
+ "reply": "回复",
+ "goodsName": "商品名称",
+ "goodsNamePlaceholder": "请输入商品名称",
+ "topping": "置顶",
+ "cancelTopping": "取消置顶",
+ "memberHeadPlaceholder": "请上传会员头像",
+ "batchDelete": "批量删除",
+ "batchDeleteTips": "确定要批量删除选中的评价吗?",
+ "batchAdopt": "批量通过",
+ "batchAdoptTips": "确定要批量通过选中的评价吗?",
+ "batchRefuse": "批量拒绝",
+ "batchRefuseTips": "确定要批量拒绝选中的评价吗?",
+ "batchEmptySelectedCommentsTips": "请先选择要操作的评价",
+ "status":"审核状态",
+ "statusPlaceholder":"请选择审核状态"
+
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/admin/lang/zh-cn/goods.evaluate_edit.json b/niucloud/addon/shop/admin/lang/zh-cn/goods.evaluate_edit.json
new file mode 100644
index 000000000..9283f1f59
--- /dev/null
+++ b/niucloud/addon/shop/admin/lang/zh-cn/goods.evaluate_edit.json
@@ -0,0 +1,37 @@
+{
+ "orderId": "订单id",
+ "orderGoodsId": "订单项ID",
+ "goodsId": "商品ID",
+ "memberId": "会员ID",
+ "content": "评价内容",
+ "images": "评价图片",
+ "isAnonymous": "0 匿名 1不匿名",
+ "scores": "评价分数 1-5",
+ "isAudit": "审核状态 1待审 2通过 3拒绝",
+ "explainFirst": "解释内容",
+ "againContent": "追评内容",
+ "againImages": "追评图片",
+ "againExplain": "追评解释",
+ "againTime": "追评时间",
+ "againIsAudit": "审核状态 1待审 2通过 3拒绝",
+ "isShow": "是否显示 1显示 2不显示",
+ "orderIdPlaceholder": "请输入订单id",
+ "orderGoodsIdPlaceholder": "请输入订单项ID",
+ "goodsIdPlaceholder": "请输入商品ID",
+ "memberIdPlaceholder": "请输入会员ID",
+ "contentPlaceholder": "请输入评价内容",
+ "imagesPlaceholder": "请上传评价图片",
+ "isAnonymousPlaceholder": "请输入0 匿名 1不匿名",
+ "scoresPlaceholder": "请输入评价分数 1-5",
+ "isAuditPlaceholder": "请输入审核状态 1待审 2通过 3拒绝",
+ "explainFirstPlaceholder": "请输入解释内容",
+ "againContentPlaceholder": "请输入追评内容",
+ "againImagesPlaceholder": "请上传追评图片",
+ "againExplainPlaceholder": "请输入追评解释",
+ "againTimePlaceholder": "请输入追评时间",
+ "againIsAuditPlaceholder": "请输入审核状态 1待审 2通过 3拒绝",
+ "isShowPlaceholder": "请输入是否显示 1显示 2不显示",
+ "addEvaluate": "添加商品评价",
+ "updateEvaluate": "编辑商品评价",
+ "evaluateDeleteTips": "确定要删除该商品评价吗?"
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/admin/lang/zh-cn/goods.label_group_list.json b/niucloud/addon/shop/admin/lang/zh-cn/goods.label_group_list.json
new file mode 100644
index 000000000..dfceabecd
--- /dev/null
+++ b/niucloud/addon/shop/admin/lang/zh-cn/goods.label_group_list.json
@@ -0,0 +1,12 @@
+{
+ "tabGoodsLabel": "商品标签",
+ "tabGoodsLabelGroup": "标签分组",
+ "groupName": "分组名称",
+ "groupNamePlaceholder": "请输入分组名称",
+ "sort": "排序",
+ "sortPlaceholder": "请输入排序",
+ "addLabelGroup": "添加标签分组",
+ "updateLabelGroup": "编辑标签分组",
+ "sortTips": "排序号格式输入错误",
+ "labelGroupDeleteTips": "确定要删除该数据吗?"
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/admin/lang/zh-cn/goods.label_list.json b/niucloud/addon/shop/admin/lang/zh-cn/goods.label_list.json
new file mode 100644
index 000000000..6b412506e
--- /dev/null
+++ b/niucloud/addon/shop/admin/lang/zh-cn/goods.label_list.json
@@ -0,0 +1,32 @@
+{
+ "tabGoodsLabel": "商品标签",
+ "tabGoodsLabelGroup": "标签分组",
+ "labelName": "标签名称",
+ "labelNamePlaceholder": "请输入标签名称",
+ "groupName": "标签分组",
+ "groupNamePlaceholder": "请选择标签分组",
+ "styleType": "效果设置",
+ "styleByDiy": "自定义",
+ "styleByIcon": "图片",
+ "textColor": "文字颜色",
+ "bgColor": "背景颜色",
+ "borderColor": "边框颜色",
+ "colorTips": "若未设置颜色,则为默认色",
+ "icon": "上传图片",
+ "iconTips": "建议尺寸:80px*30px,若未上传将显示默认",
+ "memo": "标签说明",
+ "memoPlaceholder": "请输入标签说明",
+ "sort": "排序",
+ "sortPlaceholder": "请输入排序",
+ "addLabel": "添加商品标签",
+ "updateLabel": "编辑商品标签",
+ "sortTips": "排序号格式输入错误",
+ "labelDeleteTips": "确定要删除该数据吗?",
+ "statusOn": "开启",
+ "statusOff": "关闭",
+ "status": "状态",
+ "label": "标签",
+ "createTime": "创建时间",
+ "copyLabel": "复制",
+ "labelCopyTips": "确定要复制该标签吗?"
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/admin/lang/zh-cn/goods.list.json b/niucloud/addon/shop/admin/lang/zh-cn/goods.list.json
new file mode 100644
index 000000000..f492e442a
--- /dev/null
+++ b/niucloud/addon/shop/admin/lang/zh-cn/goods.list.json
@@ -0,0 +1,139 @@
+{
+ "goodsName": "商品名称",
+ "goodsNamePlaceholder": "请输入商品名称",
+ "goodsCategory": "商品分类",
+ "goodsCategoryPlaceholder": "全部",
+ "goodsType": "商品类型",
+ "goodsTypePlaceholder": "请选择商品类型",
+ "brand": "商品品牌",
+ "brandPlaceholder": "请输入商品品牌",
+ "labelIds": "商品标签",
+ "labelIdsPlaceholder": "请选择商品标签",
+ "saleNum": "销量",
+ "startSaleNumPlaceholder": "最低销量",
+ "startSaleNumTips": "最低销量输入错误",
+ "endSaleNumPlaceholder": "最高销量",
+ "endSaleNumTips": "最高销量输入错误",
+ "shopSaleNumTips": "最低销量不能大于最高销量",
+ "skuPrice": "价格",
+ "startPricePlaceholder": "最低价格",
+ "startPriceTips": "最低价格输入错误",
+ "endPricePlaceholder": "最高价格",
+ "endPriceTips": "最高价格输入错误",
+ "shopPriceTips": "最低价格不能大于最高价格",
+ "statusOn": "销售中",
+ "statusOff": "仓库中",
+ "statusAll": "全部商品",
+ "batchOnGoods": "批量上架",
+ "batchOffGoods": "批量下架",
+ "batchDeleteGoods": "批量删除",
+ "batchSetting": "批量设置",
+ "batchEmptySelectedGoodsTips": "请选择要操作的商品",
+ "goodsInfo": "商品",
+ "stock": "库存",
+ "status": "状态",
+ "sort": "排序",
+ "sortTips": "排序号格式输入错误",
+ "createTime": "创建时间",
+ "addGoods": "添加商品",
+ "statusActionOn": "上架",
+ "statusActionOff": "下架",
+ "statusChangeTips": "确定要下架该商品吗?",
+ "spreadGoods": "推广",
+ "copyGoods": "复制",
+ "updateGoods": "编辑商品",
+ "goodsCopyTips": "确定要复制该商品吗?",
+ "goodsDeleteTips": "确定要删除该商品吗?",
+ "batchGoodsDeleteTips": "确定要删除这些商品吗",
+ "batchOperationSku": "批量设置",
+ "editStockPopupTitle": "编辑商品库存",
+ "editPricePopupTitle": "编辑商品价格",
+ "skuName": "规格名称",
+ "price": "销售价",
+ "pricePlaceholder": "请输入销售价",
+ "priceTips": "销售价格式输入错误",
+ "priceNotZeroTips": "销售价不能小于0",
+ "marketPrice": "划线价",
+ "marketPricePlaceholder": "请输入划线价",
+ "marketPriceTips": "划线价格式输入错误",
+ "marketPriceNotZeroTips": "划线价不能小于0",
+ "market_price": "划线价",
+ "market_pricePlaceholder": "请输入划线价",
+ "market_priceTips": "划线价格式输入错误",
+ "market_priceNotZeroTips": "划线价不能小于0",
+ "costPrice": "成本价",
+ "costPricePlaceholder": "请输入成本价",
+ "costPriceTips": "成本价格式输入错误",
+ "costPriceNotZeroTips": "成本价不能小于0",
+ "cost_price": "成本价",
+ "cost_pricePlaceholder": "请输入成本价",
+ "cost_priceTips": "成本价格式输入错误",
+ "cost_priceNotZeroTips": "成本价不能小于0",
+ "stockPlaceholder": "请输入库存",
+ "stockTips": "库存格式输入错误",
+ "stockNotZeroTips": "库存不能小于0",
+ "goodsSpreadTitle": "商品推广",
+ "spreadLink": "推广链接",
+ "copy": "复制",
+ "downloadQrcode": "下载二维码",
+ "memberPrice": "会员价",
+ "editMemberPricePopupTitle": "编辑会员价",
+ "memberDiscount": "会员价优惠方式",
+ "discount": "会员折扣",
+ "fixedPrice": "指定会员价",
+ "nonparticipation": "不参与",
+ "goodsSku": "商品规格",
+ "memberEnjoyDiscount": "会员享受折扣",
+ "discountUnit": "折",
+ "yuanUnit": "元",
+ "editMemberPrice": "修改会员价",
+ "memberLevel": "会员等级",
+ "memberPricePlaceholder": "请输入会员价",
+ "discountHint": "会员折扣说明:按照默认会员等级折扣优惠",
+ "fixedPriceHint": "会员价说明:指定优惠价格,商品未参与活动时,按照会员价优惠,若商品参与活动,则以活动价为准",
+ "addGoodsLabel": "添加商品标签",
+ "addGoodsService": "添加商品服务",
+ "addGoodsCategory": "添加分类",
+ "addGoodsBrand": "添加品牌",
+ "addGoodsPoster": "添加海报",
+ "virtualSaleNumPlaceholder": "请输入虚拟销量",
+ "posterPlaceholder": "请选择商品海报",
+ "goodsCategoryPlaceholderTwo": "请选择商品分类",
+ "virtualSaleNumDesc": "虚拟销量只在前台展示中参与计算",
+ "virtualSaleNumTips": "虚拟销量格式输入错误",
+ "virtualSaleNumNotZeroTips": "虚拟销量不能小于0",
+ "giftTips": "当商品设置为赠品时,该商品仅用于活动赠送,不会在前台展示或出售",
+ "yes": "是",
+ "no": "否",
+ "isFreeShipping": "是否免邮",
+ "feeType": "运费设置",
+ "selectTemplate": "选择模板",
+ "fixedShipping": "统一运费",
+ "deliveryMoney": "固定运费",
+ "deliveryMoneyPlaceholder": "请输入固定运费",
+ "deliveryMoneyTips": "固定运费格式输入错误",
+ "deliveryMoneyNotZeroTips": "固定运费不能小于0",
+ "deliveryTemplateId": "运费模板",
+ "deliveryTemplateIdPlaceholder": "请选择运费模板",
+ "addDeliveryTemplateId": "添加运费模板",
+ "deliveryType": "配送方式",
+ "deliveryTypePlaceholder": "请选择配送方式",
+ "yuan": "元",
+ "label": "商品标签",
+ "service": "商品服务",
+ "virtualSaleNum": "虚拟销量",
+ "goodsBrand": "商品品牌",
+ "goodsPoster": "商品海报",
+ "isGift": "是否赠品",
+ "batchSettingTip": "每次仅能设置一项,点击确认成功之后生效",
+ "setStock": "修改库存",
+ "addStock": "增加库存",
+ "reduceStock": "减少库存",
+ "stockNum": "目标数值",
+ "stockNumTips": "批量调整商品库存,若商品正在参与营销活动,则不会修改库存",
+ "confirm": "确认",
+ "diyForm": "万能表单",
+ "diyFormPlaceholder": "请选择万能表单",
+ "addDiyForm": "添加表单",
+ "productClassificationPlaceholder":"请选择商品分类"
+}
diff --git a/niucloud/addon/shop/admin/lang/zh-cn/goods.real_edit.json b/niucloud/addon/shop/admin/lang/zh-cn/goods.real_edit.json
new file mode 100644
index 000000000..65e1ab7c4
--- /dev/null
+++ b/niucloud/addon/shop/admin/lang/zh-cn/goods.real_edit.json
@@ -0,0 +1,171 @@
+{
+ "addGoods": "添加商品",
+ "updateGoods": "编辑商品",
+ "basicInfoTab": "基础信息",
+ "goodsType": "商品类型",
+ "goodsName": "商品名称",
+ "goodsNamePlaceholder": "请输入商品名称",
+ "goodsNameMaxLengthTips": "商品名称不能超过60个字符",
+ "subTitle": "副标题",
+ "subTitlePlaceholder": "请输入副标题",
+ "subTitleMaxLengthTips": "副标题不能超过100个字符",
+ "goodsImage": "商品图片",
+ "goodsImagePlaceholder": "请上传商品图片",
+ "goodsVideo": "商品视频",
+ "goodsVideoPlaceholder": "请上传商品视频",
+ "goodsVideoTipTile": "注意事项:",
+ "goodsVideoTipOne": "1、检查upload文件夹是否有读写权限。",
+ "goodsVideoTipTwo": "2、PHP默认上传限制为2MB,需要在php.ini配置文件中修改“post_max_size”和“upload_max_filesize”的大小。",
+ "goodsVideoTipThree": "3、视频支持手动输入外链视频地址或者上传本地视频文件",
+ "goodsVideoTipFour": "4、必须上传.mp4视频格式",
+ "goodsVideoTipFive": "5、视频文件大小不能超过500MB",
+ "goodsCategory": "商品分类",
+ "refresh": "刷新",
+ "addGoodsCategory": "添加分类",
+ "goodsCategoryPlaceholder": "请选择商品分类",
+ "brand": "商品品牌",
+ "brandPlaceholder": "请输入商品品牌",
+ "addGoodsBrand": "添加品牌",
+ "poster": "商品海报",
+ "posterPlaceholder": "请选择商品海报",
+ "addGoodsPoster": "添加海报",
+ "posterTips": "不设置将使用默认海报",
+ "diyForm": "万能表单",
+ "diyFormPlaceholder": "请选择万能表单",
+ "addDiyForm": "添加表单",
+ "label": "商品标签",
+ "addGoodsLabel": "添加商品标签",
+ "goodsService": "商品服务",
+ "addGoodsService": "添加商品服务",
+ "supplier": "供应商",
+ "supplierPlaceholder": "请选择供应商",
+ "addSupplier": "添加供应商",
+ "status": "商品状态",
+ "statusOn": "上架",
+ "statusOff": "下架",
+ "isGive": "是否赠品",
+ "yes": "是",
+ "no": "否",
+ "sort": "排序",
+ "sortPlaceholder": "请输入排序",
+ "sortTips": "排序号格式输入错误",
+ "priceStockTab": "价格库存",
+ "specType": "规格类型",
+ "singleSpec": "单规格",
+ "multiSpec": "多规格",
+ "price": "销售价",
+ "marketPrice": "划线价",
+ "costPrice": "成本价",
+ "weight": "重量",
+ "volume": "体积",
+ "goodsStock": "商品库存",
+ "goodsStockPlaceholder": "请输入商品库存",
+ "skuNo": "商品编码",
+ "yuan": "元",
+ "defaultUnit": "件",
+ "skuNoPlaceholder": "请输入商品编码",
+ "goodsSku": "商品规格",
+ "specNamePlaceholder": "请输入规格项,如颜色、尺码、大小",
+ "specValueNamePlaceholder": "请输入规格值,如:白色",
+ "addSpecValue": "+添加规格值",
+ "addSpec": "添加规格",
+ "batchOperationSku": "批量设置",
+ "all": "全部",
+ "stock": "库存",
+ "skuWeight": "重量(kg)",
+ "skuVolume": "体积(m³)",
+ "confirm": "确定",
+ "image": "图片",
+ "defaultSku": "默认规格",
+ "unit": "单位",
+ "unitPlaceholder": "请输入单位,默认为:件",
+ "virtualSaleNum": "虚拟销量",
+ "virtualSaleNumPlaceholder": "请输入虚拟销量",
+ "virtualSaleNumDesc": "虚拟销量只在前台展示中参与计算",
+ "virtualSaleNumTips": "虚拟销量格式输入错误",
+ "virtualSaleNumNotZeroTips": "虚拟销量不能小于0",
+ "giftTips": "当商品设置为赠品时,该商品仅用于活动赠送,不会在前台展示或出售",
+ "maxAddSpecTips": "最多添加5个规格项",
+ "pleaseEditSpecPlaceholder": "请编辑规格信息",
+ "refreshSuccess": "刷新成功",
+ "deliveryTab": "配送设置",
+ "advancedSetup": "高级设置",
+ "diyDetailTemplate": "商品详情模版",
+ "diyDetailTemplatePlaceholder": "请选择商品详情模版",
+ "addDetailTemp": "添加模板",
+ "detailTempTip": "不设置将使用默认商品详情模板",
+ "deliveryType": "配送方式",
+ "deliveryTypePlaceholder": "请选择配送方式",
+ "pleaseSelectSku": "请先选择商品规格",
+ "isLimit": "是否限购",
+ "isLimitTips": "启用限购后,购买商品时,会对该商品购买量做限制判断。",
+ "limitType": "限购类型",
+ "limitTypeTips": "单次限购是针对于每次下单不能超过限购数量,单人限购是针对于会员账号购买这个商品的总数不能超过限购数量。",
+ "singleTime": "单次限购",
+ "singlePerson": "单人限购",
+ "maxBuy": "限购数量",
+ "maxBuyPlaceholder": "请输入限购数量",
+ "maxBuyTips": "[限购数量]格式输入错误",
+ "maxBuyWarnTips": "限购数量超出商品库存时,买家将无法购买该商品",
+ "maxBuyNotZeroTips": "限购数量不能小于1",
+ "minBuy": "起购数量",
+ "minBuyTips": "起购数量超出商品库存时,买家将无法购买该商品",
+ "minBuyFormatErrorTips": "[起购数量]格式输入错误",
+ "minBuyNotZeroTips": "起购数量不能小于0",
+ "minBuyGreaterThanMaxBuyTips": "起购数量不能大于限购数量",
+ "isFreeShipping": "是否免邮",
+ "feeType": "运费设置",
+ "selectTemplate": "选择模板",
+ "fixedShipping": "统一运费",
+ "deliveryMoney": "固定运费",
+ "deliveryMoneyPlaceholder": "请输入固定运费",
+ "deliveryMoneyTips": "固定运费格式输入错误",
+ "deliveryMoneyNotZeroTips": "固定运费不能小于0",
+ "deliveryTemplateId": "运费模板",
+ "deliveryTemplateIdPlaceholder": "请选择运费模板",
+ "addDeliveryTemplateId": "添加运费模板",
+ "goodsDesc": "商品详情",
+ "goodsDescPlaceholder": "请填写商品详情",
+ "goodsDescMaxTips": "商品描述字符数应在5~50000之间",
+ "pricePlaceholder": "请输入销售价",
+ "priceTips": "[销售价]格式输入错误",
+ "priceNotZeroTips": "销售价不能小于0",
+ "marketPricePlaceholder": "请输入划线价",
+ "marketPriceTips": "[划线价]格式输入错误",
+ "marketPriceNotZeroTips": "划线价不能小于0",
+ "costPricePlaceholder": "请输入成本价",
+ "costPriceTips": "[成本价]格式输入错误",
+ "costPriceNotZeroTips": "成本价不能小于0",
+ "weightPlaceholder": "请输入重量",
+ "weightTips": "[重量(kg)]格式输入错误",
+ "weightNotZeroTips": "重量(kg)不能小于0",
+ "volumePlaceholder": "请输入体积",
+ "volumeTips": "[体积(m³)]格式输入错误",
+ "volumeNotZeroTips": "体积(m³)不能小于0",
+ "stockPlaceholder": "请输入库存",
+ "stockTips": "[库存]格式输入错误",
+ "stockNotZeroTips": "库存不能小于0",
+ "specNameRequire": "规格项不能为空",
+ "specNameRepeat": "规格项不能重复",
+ "specValueRequire": "规格值不能为空",
+ "specValueNameRepeat": "规格值不能重复",
+ "lackDefaultSpec": "商品缺少默认规格",
+ "goodsArguments": "商品参数",
+ "goodsArgumentsTemp": "商品参数模板",
+ "goodsArgumentsTempPlaceholder": "请选择商品参数模板",
+ "goodsArgumentsTempHint": "商品可以添加自定义商品参数,也可以通过参数模板批量设置商品参数",
+ "argumentsName": "参数名",
+ "argumentsValue": "参数值",
+ "argumentsSortHint": "设置排序,改变商品规格展示顺序",
+ "operation": "操作",
+ "delAttr": "删除",
+ "noData": "无数据",
+ "addGoodsArguments": "添加商品参数",
+ "memberDiscount": "会员等级折扣",
+ "discount": "会员折扣",
+ "fixedPrice": "指定会员价",
+ "nonparticipation": "不参与",
+ "discountHint": "会员折扣说明:按照默认会员等级折扣优惠",
+ "fixedPriceHint": "会员价说明:指定优惠价格,商品未参与活动时,按照会员价优惠,若商品参与活动,则以活动价为准",
+ "participateInActiveDisableTips": "商品正在参与营销活动,禁止操作"
+}
diff --git a/niucloud/addon/shop/admin/lang/zh-cn/goods.recycle.json b/niucloud/addon/shop/admin/lang/zh-cn/goods.recycle.json
new file mode 100644
index 000000000..078dd85d2
--- /dev/null
+++ b/niucloud/addon/shop/admin/lang/zh-cn/goods.recycle.json
@@ -0,0 +1,22 @@
+{
+ "goodsName": "商品名称",
+ "goodsNamePlaceholder": "请输入商品名称",
+ "goodsCategory": "商品分类",
+ "goodsCategoryPlaceholder": "全部",
+ "goodsType": "商品类型",
+ "goodsTypePlaceholder": "请选择商品类型",
+ "price": "价格",
+ "saleNum": "销量",
+ "statusOn": "销售中",
+ "statusOff": "仓库中",
+ "batchRecycle": "批量恢复",
+ "batchEmptySelectedGoodsTips": "请选择要操作的商品",
+ "goodsInfo": "商品",
+ "stock": "库存",
+ "stockPlaceholder": "请输入商品库存(总和)",
+ "status": "状态",
+ "createTime": "创建时间",
+ "recycle": "恢复",
+ "goodsRecycleTips": "确定要恢复该商品吗?",
+ "batchGoodsRecycleTips": "确定要恢复这些商品吗"
+}
diff --git a/niucloud/addon/shop/admin/lang/zh-cn/goods.search_config.json b/niucloud/addon/shop/admin/lang/zh-cn/goods.search_config.json
new file mode 100644
index 000000000..f8cd355db
--- /dev/null
+++ b/niucloud/addon/shop/admin/lang/zh-cn/goods.search_config.json
@@ -0,0 +1,26 @@
+{
+ "goodsSearch": "商品搜索",
+ "goodsCode": "商品编码",
+ "defaultSearch": "默认搜索",
+ "defaultWord": "默认搜索关键词",
+ "defaultWordPlaceholder": "请输入默认搜索关键词",
+ "defaultWordTips": "默认搜索,将显示在前台搜索框,前台点击时直接作为关键词进行搜索",
+ "hotSearch": "热门搜索",
+ "indexKeyword": "搜索的关键字",
+ "searchPlaceholder": "请输入搜索关键字",
+ "addSearch": "添加",
+ "enable": "商品编码唯一性",
+ "enableTips": "开启后,将验证商品编码唯一性,不能重复",
+ "searchTips": "列表中已存在该关键字",
+ "keyWordTips": "搜索关键字不能为空",
+ "goodSort": "商品排序",
+ "sortType": "排序方式",
+ "sortTypePlaceholder": "请选择排序方式",
+ "sortTypeTips": "选择排序方式时,前台商品将依据排序号优先进行正序或倒序排列,当排序号相同时,均按照创建时间倒序排列。",
+ "sortColumn": "排序字段",
+ "sortColumnTips": "请选择用于排序的字段,例如 排序号、价格、销量,不同的排序字段将影响商品的显示优先级。",
+ "sortColumnPlaceholder": "请选择排序字段",
+ "defaultSort": "默认排序值",
+ "defaultSortPlaceholder": "请输入默认排序值",
+ "defaultSortTips": "默认排值是当添加商品时,如果没有设置排序值的情况下,则按照该位置设置的默认数值参与排序 "
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/admin/lang/zh-cn/goods.service.json b/niucloud/addon/shop/admin/lang/zh-cn/goods.service.json
new file mode 100644
index 000000000..0fa8ac145
--- /dev/null
+++ b/niucloud/addon/shop/admin/lang/zh-cn/goods.service.json
@@ -0,0 +1,10 @@
+{
+ "serviceName": "服务名称",
+ "serviceNamePlaceholder": "请输入服务名称",
+ "desc": "描述",
+ "descPlaceholder": "请输入描述",
+ "addServe": "添加商品服务",
+ "updateServe": "编辑商品服务",
+ "serveDeleteTips": "确定要删除该数据吗?",
+ "imagePlaceholder": "请上传服务图片"
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/admin/lang/zh-cn/goods.virtual_edit.json b/niucloud/addon/shop/admin/lang/zh-cn/goods.virtual_edit.json
new file mode 100644
index 000000000..933f11caf
--- /dev/null
+++ b/niucloud/addon/shop/admin/lang/zh-cn/goods.virtual_edit.json
@@ -0,0 +1,164 @@
+{
+ "addGoods": "添加商品",
+ "updateGoods": "编辑商品",
+ "basicInfoTab": "基础信息",
+ "goodsType": "商品类型",
+ "goodsName": "商品名称",
+ "goodsNamePlaceholder": "请输入商品名称",
+ "goodsNameMaxLengthTips": "商品名称不能超过60个字符",
+ "subTitle": "副标题",
+ "subTitlePlaceholder": "请输入副标题",
+ "subTitleMaxLengthTips": "副标题不能超过100个字符",
+ "goodsImage": "商品图片",
+ "goodsImagePlaceholder": "请上传商品图片",
+ "goodsVideo": "商品视频",
+ "goodsVideoPlaceholder": "请上传商品视频",
+ "goodsVideoTipTile": "注意事项:",
+ "goodsVideoTipOne": "1、检查upload文件夹是否有读写权限。",
+ "goodsVideoTipTwo": "2、PHP默认上传限制为2MB,需要在php.ini配置文件中修改“post_max_size”和“upload_max_filesize”的大小。",
+ "goodsVideoTipThree": "3、视频支持手动输入外链视频地址或者上传本地视频文件",
+ "goodsVideoTipFour": "4、必须上传.mp4视频格式",
+ "goodsVideoTipFive": "5、视频文件大小不能超过500MB",
+ "goodsCategory": "商品分类",
+ "advancedSetup": "高级设置",
+ "diyDetailTemplate": "商品详情模版",
+ "diyDetailTemplatePlaceholder": "请选择商品详情模版",
+ "addDetailTemp": "添加模板",
+ "detailTempTip": "不设置将使用默认商品详情模板",
+ "refresh": "刷新",
+ "addGoodsCategory": "添加分类",
+ "goodsCategoryPlaceholder": "请选择商品分类",
+ "brand": "商品品牌",
+ "brandPlaceholder": "请输入商品品牌",
+ "addGoodsBrand": "添加品牌",
+ "poster": "商品海报",
+ "posterPlaceholder": "请选择商品海报",
+ "addGoodsPoster": "添加海报",
+ "posterTips": "不设置将使用默认海报",
+ "diyForm": "万能表单",
+ "diyFormPlaceholder": "请选择万能表单",
+ "addDiyForm": "添加表单",
+ "label": "商品标签",
+ "addGoodsLabel": "添加商品标签",
+ "goodsService": "商品服务",
+ "addGoodsService": "添加商品服务",
+ "supplier": "供应商",
+ "supplierPlaceholder": "请选择供应商",
+ "addSupplier": "添加供应商",
+ "status": "商品状态",
+ "statusOn": "上架",
+ "statusOff": "下架",
+ "isGive": "是否赠品",
+ "yes": "是",
+ "no": "否",
+ "sort": "排序",
+ "sortPlaceholder": "请输入排序",
+ "sortTips": "排序号格式输入错误",
+ "priceStockTab": "价格库存",
+ "specType": "规格类型",
+ "singleSpec": "单规格",
+ "multiSpec": "多规格",
+ "price": "销售价",
+ "marketPrice": "划线价",
+ "costPrice": "成本价",
+ "goodsStock": "商品库存",
+ "goodsStockPlaceholder": "请输入商品库存",
+ "skuNo": "商品编码",
+ "yuan": "元",
+ "defaultUnit": "件",
+ "skuNoPlaceholder": "请输入商品编码",
+ "goodsSku": "商品规格",
+ "specNamePlaceholder": "请输入规格项,如颜色、尺码、大小",
+ "specValueNamePlaceholder": "请输入规格值,如:白色",
+ "addSpecValue": "+添加规格值",
+ "addSpec": "添加规格",
+ "batchOperationSku": "批量设置",
+ "all": "全部",
+ "stock": "库存",
+ "confirm": "确定",
+ "image": "图片",
+ "defaultSku": "默认规格",
+ "unit": "单位",
+ "unitPlaceholder": "请输入单位,默认为:件",
+ "virtualSaleNum": "虚拟销量",
+ "virtualSaleNumPlaceholder": "请输入虚拟销量",
+ "virtualSaleNumDesc": "虚拟销量只在前台展示中参与计算",
+ "virtualSaleNumTips": "虚拟销量格式输入错误",
+ "virtualSaleNumNotZeroTips": "虚拟销量不能小于0",
+ "giftTips": "当商品设置为赠品时,该商品仅用于活动赠送,不会在前台展示或出售",
+ "virtualSetTips": "当设置为店内核销时,若存在未完成的订单,则无法编辑",
+ "maxAddSpecTips": "最多添加5个规格项",
+ "pleaseEditSpecPlaceholder": "请编辑规格信息",
+ "refreshSuccess": "刷新成功",
+ "isLimit": "是否限购",
+ "isLimitTips": "启用限购后,购买商品时,会对该商品购买量做限制判断。",
+ "limitType": "限购类型",
+ "limitTypeTips": "单次限购是针对于每次下单不能超过限购数量,单人限购是针对于会员账号购买这个商品的总数不能超过限购数量。",
+ "singleTime": "单次限购",
+ "singlePerson": "单人限购",
+ "maxBuy": "限购数量",
+ "maxBuyPlaceholder": "请输入限购数量",
+ "maxBuyTips": "[限购数量]格式输入错误",
+ "maxBuyWarnTips": "限购数量超出商品库存时,买家将无法购买该商品",
+ "maxBuyNotZeroTips": "限购数量不能小于1",
+ "minBuy": "起购数量",
+ "minBuyTips": "起购数量超出商品库存时,买家将无法购买该商品",
+ "minBuyFormatErrorTips": "[起购数量]格式输入错误",
+ "minBuyNotZeroTips": "起购数量不能小于0",
+ "minBuyGreaterThanMaxBuyTips": "起购数量不能大于限购数量",
+ "goodsDesc": "商品详情",
+ "goodsDescPlaceholder": "请填写商品详情",
+ "goodsDescMaxTips": "商品描述字符数应在5~50000之间",
+ "pricePlaceholder": "请输入销售价",
+ "priceTips": "[销售价]格式输入错误",
+ "priceNotZeroTips": "销售价不能小于0",
+ "marketPricePlaceholder": "请输入划线价",
+ "marketPriceTips": "[划线价]格式输入错误",
+ "marketPriceNotZeroTips": "划线价不能小于0",
+ "costPricePlaceholder": "请输入成本价",
+ "costPriceTips": "[成本价]格式输入错误",
+ "costPriceNotZeroTips": "成本价不能小于0",
+ "stockPlaceholder": "请输入库存",
+ "stockTips": "[库存]格式输入错误",
+ "stockNotZeroTips": "库存不能小于0",
+ "specNameRequire": "规格项不能为空",
+ "specNameRepeat": "规格项不能重复",
+ "specValueRequire": "规格值不能为空",
+ "specValueNameRepeat": "规格值不能重复",
+ "lackDefaultSpec": "商品缺少默认规格",
+ "setDeliverGoods": "发货设置",
+ "autoDeliverGoods": "自动发货",
+ "handDeliverGoods": "手动发货",
+ "setTakeGoods": "收货设置",
+ "autoTakeGoods": "自动收货",
+ "handTakeGoods": "买家确认收货",
+ "verifyTakeGoods": "到店核销",
+ "virtualIndate": "有效期",
+ "virtualIndatePlaceholder": "请输入有效期",
+ "verifyVirtualIndate": "核销有效期",
+ "verifyVirtualIndateOne": "永久",
+ "verifyVirtualIndateTwo": "购买后几日有效",
+ "verifyVirtualIndateThree": "指定过期日期",
+ "verifyHint": "无论何时购买此商品,到达指定时间后都将过期,无法核销。",
+ "sky": "天",
+ "virtualIndateErrorHint": "核销有效期不能小于1天",
+ "virtualIndateErrorOneHint": "核销有效期不能小于等于当前时间",
+ "goodsArguments": "商品参数",
+ "goodsArgumentsTemp": "商品参数模板",
+ "goodsArgumentsTempPlaceholder": "请选择商品参数模板",
+ "goodsArgumentsTempHint": "商品可以添加自定义商品参数,也可以通过参数模板批量设置商品参数",
+ "argumentsName": "参数名",
+ "argumentsValue": "参数值",
+ "argumentsSortHint": "设置排序,改变商品规格展示顺序",
+ "operation": "操作",
+ "delAttr": "删除",
+ "noData": "无数据",
+ "addGoodsArguments": "添加商品参数",
+ "memberDiscount": "会员等级折扣",
+ "discount": "会员折扣",
+ "fixedPrice": "指定会员价",
+ "nonparticipation": "不参与",
+ "discountHint": "会员折扣说明:按照默认会员等级折扣优惠",
+ "fixedPriceHint": "会员价说明:指定优惠价格,商品未参与活动时,按照会员价优惠,若商品参与活动,则以活动价为准",
+ "participateInActiveDisableTips": "商品正在参与营销活动,禁止操作"
+}
diff --git a/niucloud/addon/shop/admin/lang/zh-cn/index.index.json b/niucloud/addon/shop/admin/lang/zh-cn/index.index.json
new file mode 100644
index 000000000..cbf564f79
--- /dev/null
+++ b/niucloud/addon/shop/admin/lang/zh-cn/index.index.json
@@ -0,0 +1,20 @@
+{
+ "realtimeOverview": "实时概况",
+ "updateTime": "更新时间:",
+ "todayOrderCount": "今日订单数",
+ "todayOrderSale": "今日销售额",
+ "todayAddMemberCount": "今日退款金额",
+ "todayBrowseCount": "今日浏览量",
+ "yesterday": "昨日:",
+ "orderCount": "订单总数",
+ "salesTotal": "销售总额(元)",
+ "memberTotal": "退款金额",
+ "browseTotal": "总浏览量",
+ "agentMatters": "待办事项",
+ "waitPayOrder": "待付款订单",
+ "waitDeliveryOrder": "待发货订单",
+ "waitTakeOrder": "待收货订单",
+ "refundOrder": "退款订单",
+ "saleGoodsNum": "出售商品数量",
+ "warehouseGoodsNum": "仓库商品数量"
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/admin/lang/zh-cn/marketing.coupon.add.json b/niucloud/addon/shop/admin/lang/zh-cn/marketing.coupon.add.json
new file mode 100644
index 000000000..b99064ab8
--- /dev/null
+++ b/niucloud/addon/shop/admin/lang/zh-cn/marketing.coupon.add.json
@@ -0,0 +1,42 @@
+{
+ "addCoupon": "添加优惠券",
+ "title": "名称",
+ "titlePlaceholder": "请如:XXX优惠券,最多20个字",
+ "type": "类型",
+ "price": "面值",
+ "receiveType": "是否手动领取",
+ "startTime": "开始时间",
+ "endTime": "结束时间",
+ "remainCount": "剩余数量",
+ "limitCount": "已领取数量",
+ "receive": "领取记录",
+ "user": "是",
+ "grant": "否",
+ "limit": "限量",
+ "unlimited": "不限量",
+ "receiveNumber": "发放数量",
+ "pricePlaceholder": "请输入优惠券面值",
+ "remainCountPlaceholder": "最多发放100000张",
+ "reduction": "满减券",
+ "noThreshold": "无门槛券",
+ "threshold": "使用门槛",
+ "minConditionMoneyPlaceholder": "请输入优惠券的最低消费金额",
+ "userLimitCount": "限领张数",
+ "userLimitCountPlaceholder": "请输入限领张数",
+ "receiveTime": "领取时间",
+ "limitedTime": "限时",
+ "unlimitedTime": "不限时",
+ "days": "天数",
+ "times": "固定时间",
+ "validType": "有效期",
+ "lengthPlaceholder": "请输入使用时间",
+ "status": "状态",
+ "open": "开启",
+ "close": "关闭",
+ "cancel": "取消",
+ "save": "保存",
+ "startDate": "开始时间",
+ "endDate": "结束时间",
+ "validTimePlaceholder": "用券截止时间",
+ "arrivalTimePlaceholder": "领券截止时间"
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/admin/lang/zh-cn/marketing.coupon.edit.json b/niucloud/addon/shop/admin/lang/zh-cn/marketing.coupon.edit.json
new file mode 100644
index 000000000..932564622
--- /dev/null
+++ b/niucloud/addon/shop/admin/lang/zh-cn/marketing.coupon.edit.json
@@ -0,0 +1,42 @@
+{
+ "editCoupon": "编辑优惠券",
+ "title": "名称",
+ "titlePlaceholder": "请如:XXX优惠券,最多20个字",
+ "type": "类型",
+ "price": "面值",
+ "receiveType": "是否手动领取",
+ "startTime": "开始时间",
+ "endTime": "结束时间",
+ "remainCount": "剩余数量",
+ "limitCount": "已领取数量",
+ "receive": "领取记录",
+ "user": "是",
+ "grant": "否",
+ "limit": "限量",
+ "unlimited": "不限量",
+ "receiveNumber": "发放数量",
+ "pricePlaceholder": "请输入优惠券面值",
+ "remainCountPlaceholder": "最多发放100000张",
+ "reduction": "满减券",
+ "noThreshold": "无门槛券",
+ "threshold": "使用门槛",
+ "minConditionMoneyPlaceholder": "请输入优惠券的最低消费金额",
+ "userLimitCount": "限领张数",
+ "userLimitCountPlaceholder": "请输入限领张数",
+ "receiveTime": "领取时间",
+ "limitedTime": "限时",
+ "unlimitedTime": "不限时",
+ "days": "天数",
+ "times": "固定时间",
+ "validType": "使用时间",
+ "lengthPlaceholder": "请输入使用时间",
+ "status": "状态",
+ "open": "开启",
+ "close": "关闭",
+ "cancel": "取消",
+ "save": "保存",
+ "startDate": "开始时间",
+ "endDate": "结束时间",
+ "validTimePlaceholder": "用券截止时间",
+ "arrivalTimePlaceholder": "领券截止时间"
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/admin/lang/zh-cn/marketing.coupon.list.json b/niucloud/addon/shop/admin/lang/zh-cn/marketing.coupon.list.json
new file mode 100644
index 000000000..df6492257
--- /dev/null
+++ b/niucloud/addon/shop/admin/lang/zh-cn/marketing.coupon.list.json
@@ -0,0 +1,83 @@
+{
+ "addCoupon": "添加优惠券",
+ "title": "名称",
+ "titlePlaceholder": "请输入优惠券名称",
+ "type": "类型",
+ "price": "面值",
+ "receiveType": "是否手动领取",
+ "startTime": "开始时间",
+ "endTime": "结束时间",
+ "count": "数量",
+ "countTips1": "1、剩余数量是指可主动领取优惠券的剩余数量,总数是指可主动领取优惠券的累计数量",
+ "countTips2": "2、已领取数量是指用户在前台主动领取的优惠券数量",
+ "countTips3": "3、已发放数量是指商家在后台给用户直接发放以及用户参与各种营销活动发放的优惠券数量",
+ "countTips4": "4、发放数量不受优惠券剩余数量限制",
+ "sumCount": "剩余 / 总数",
+ "giveCount": "已发放",
+ "noLimit": "不限量",
+ "receive": "领取记录",
+ "edit": "编辑",
+ "Status": "是否关闭领取",
+ "threshold": "使用门槛",
+ "reduction": "满减券",
+ "noThreshold": "无门槛券",
+ "couponDeleteTips": "确定要删除该优惠券吗?",
+ "couponCloseTips": "确定要关闭该优惠券吗?关闭后将不可领取,若会员已领取将变为失效",
+ "validType": "有效期",
+ "statusName": "状态",
+ "receiveTypeTime": "领取有效期",
+ "spreadGoods": "推广",
+ "close": "关闭",
+ "couponSpreadTitle": "优惠券推广",
+ "downloadQrcode": "下载二维码",
+ "spreadLink": "推广链接",
+ "receiveUseCount": "已使用",
+ "collectionCoupon": "领取记录",
+ "collectionTitle": "优惠券名称",
+ "userName": "领用会员",
+ "collectionReceiveType": "领用方式",
+ "createTime": "领取时间",
+ "expireTime": "到期时间",
+ "status": "当前状态",
+ "useTime": "使用时间",
+ "validity": "使用有效期",
+ "mobile": "手机号",
+ "memberInfo": "会员信息",
+ "memberInfoPlaceholder": "请输入会员编码/昵称/手机号搜索",
+ "collectionSumCount": "发放数量",
+ "couponInfo": "优惠券基本信息",
+ "receiveCount": "已领取",
+ "receiveExpireCount": "已过期",
+ "receiveInvalidCount": "已失效",
+ "showOrder": "查看订单",
+ "send": "发券",
+ "sendRecord": "发放记录",
+ "rangeTypePlaceholder": "请选择发放对象",
+ "sendTime": "发放时间",
+ "sendStatus": "发放状态",
+ "selectCoupon": "优惠券名称",
+ "sendNum": "每人发放数量",
+ "sendNumPrompt": "请输入每人发放数量",
+ "num": "张",
+ "sendNumTip": "不受优惠券库存限制",
+ "sendNumTipTwo": "输入框限制不能输入超过10",
+ "rangeType": "发放会员",
+ "point": "积分",
+ "balance": "余额",
+ "memberLabel": "会员标签",
+ "memberLabelPlaceholder": "请选择会员标签",
+ "memberLevel": "会员等级",
+ "memberLevelPlaceholder": "请选择会员等级",
+ "memberLevelTip": "会员等级不能为空",
+ "memberTip": "会员不能为空",
+ "memberLabelTip": "会员标签不能为空",
+ "sendNumTipThree": "发放数量不能为空",
+ "sendNumTipFour": "每人发放数量要大于0小于10",
+ "sendNumTipFive": "输入格式不正确",
+ "sendCouponTitle": "优惠券发放",
+ "batchEmptySelectedGoodsTips": "请先选择需要批量操作的优惠券",
+ "batchDelete": "批量删除",
+ "batchClose": "批量关闭",
+ "batchCloseTips": "确定要关闭选中的优惠券吗?关闭后将不可领取,若会员已领取将变为失效",
+ "batchDeleteTips": "确定要删除选中的优惠券吗?"
+}
diff --git a/niucloud/addon/shop/admin/lang/zh-cn/marketing.coupon.send.json b/niucloud/addon/shop/admin/lang/zh-cn/marketing.coupon.send.json
new file mode 100644
index 000000000..4e0cb1f93
--- /dev/null
+++ b/niucloud/addon/shop/admin/lang/zh-cn/marketing.coupon.send.json
@@ -0,0 +1,23 @@
+{
+ "selectCoupon": "选择的优惠券",
+ "sendNum": "每人发放数量",
+ "sendNumPrompt": "请输入每人发放数量",
+ "num": "张",
+ "sendNumTip": "不受优惠券库存限制",
+ "sendNumTipTwo": "输入框限制不能输入超过10",
+ "rangeType": "发放对象",
+ "memberInfo": "会员信息",
+ "mobile": "手机号",
+ "point": "积分",
+ "balance": "余额",
+ "memberLabel": "会员标签",
+ "memberLabelPlaceholder": "请选择会员标签",
+ "memberLevel": "会员等级",
+ "memberLevelPlaceholder": "请选择会员等级",
+ "memberLevelTip": "会员等级不能为空",
+ "memberTip": "会员不能为空",
+ "memberLabelTip": "会员标签不能为空",
+ "sendNumTipThree": "发放数量不能为空",
+ "sendNumTipFour": "每人发放数量要大于0小于10",
+ "sendNumTipFive": "输入格式不正确"
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/admin/lang/zh-cn/marketing.discount.add.json b/niucloud/addon/shop/admin/lang/zh-cn/marketing.discount.add.json
new file mode 100644
index 000000000..ac4ec23cc
--- /dev/null
+++ b/niucloud/addon/shop/admin/lang/zh-cn/marketing.discount.add.json
@@ -0,0 +1,38 @@
+{
+ "editDiscount": "添加限时折扣",
+ "name": "活动名称",
+ "namePlaceholder": "请输入活动名称",
+ "nameTip": "活动名称用于展示在商家后台管理",
+ "title": "标题",
+ "titlePlaceholder": "请输入活动标题",
+ "titleTip": "活动标题用户展示在手机或者电脑前端展示使用,建议输入长度不要大于5",
+ "activityTime": "活动时间",
+ "discountTimePlaceholder": "请选择活动时间",
+ "selectProduct": "选择商品",
+ "selectProductPlaceholder": "请选择商品",
+ "noSpaceAllowed": "内容不能为空",
+ "batchOperation": "批量设置",
+ "batchEmptySelectedGoodsTips": "请选择要操作的商品",
+ "discountType": "折扣类型",
+ "price": "原价",
+ "discounts": "打折",
+ "discountsTips": "[打折]格式错误",
+ "discountsTipsTwo": "打折折扣不可小于0",
+ "discountsTipsThree": "打折折扣不可大于9.9",
+ "discountsPlaceholder": "请输入打折折扣",
+ "reduceMoney": "减钱",
+ "reduceMoneyTips": "[减钱]格式错误",
+ "reduceMoneyTipsTwo": "减钱金额不可小于0",
+ "reduceMoneyTipsThree": "减钱金额不可大于原价金额",
+ "reduceMoneyPlaceholder": "请输入减钱金额",
+ "promotional": "促销价",
+ "promotionalTips": "[促销价]格式错误",
+ "promotionalTipsTwo": "促销价金额不可小于0",
+ "promotionalTipsThree": "促销价金额不可大于原价金额",
+ "promotionalPlaceholder": "请输入促销价",
+ "delete": "删除",
+ "enabled": "设为参与",
+ "noEnabled": "设为不参与",
+ "skuDiscountSettings": "规格折扣设置",
+ "skuDiscountSettingsPlaceholder": "请输入规格折扣设置"
+}
diff --git a/niucloud/addon/shop/admin/lang/zh-cn/marketing.discount.config.json b/niucloud/addon/shop/admin/lang/zh-cn/marketing.discount.config.json
new file mode 100644
index 000000000..af5748583
--- /dev/null
+++ b/niucloud/addon/shop/admin/lang/zh-cn/marketing.discount.config.json
@@ -0,0 +1,8 @@
+{
+ "headTitle": "顶部广告图",
+ "image": "图片上传",
+ "imagePlaceholder": "请上传图片",
+ "toLink": "跳转链接",
+ "toLinkPlaceholder": "请输入跳转链接",
+ "addConfigList": "添加广告图"
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/admin/lang/zh-cn/marketing.discount.detail.json b/niucloud/addon/shop/admin/lang/zh-cn/marketing.discount.detail.json
new file mode 100644
index 000000000..b3364c6f8
--- /dev/null
+++ b/niucloud/addon/shop/admin/lang/zh-cn/marketing.discount.detail.json
@@ -0,0 +1,37 @@
+{
+ "baseInfo": "基础信息",
+ "name": "活动名称",
+ "title": "标题",
+ "status": "状态",
+ "paymentAmount": "支付金额",
+ "memberCount": "参与会员数",
+ "orderCount": "支付订单数",
+ "createTime": "创建时间",
+ "startTime": "活动开始时间",
+ "endTime": "活动结束时间",
+ "keywordPlaceholder": "请输入商品名称",
+ "keyword": "商品名称",
+ "goodsInfo": "商品信息",
+ "price": "商品价格",
+ "activeOrderMoney": "累计订单金额",
+ "activeOrderNum": "累计订单数",
+ "activeMemberNum": "参与会员数",
+ "activeSuccessNum": "支付销量",
+ "orderInfo": "订单编号",
+ "payTime": "支付时间",
+ "orderNo": "订单编号",
+ "orderMoney": "订单金额",
+ "buyInfo": "买家/收货人",
+ "payType": "支付类型",
+ "orderStatus": "订单状态",
+ "toBePaid": "待支付",
+ "toBeShipped": "待发货",
+ "shipped": "已发货",
+ "receivedGoods": "已收货",
+ "completed": "已完成",
+ "closed": "已关闭",
+ "consumptionMoney": "消费总额",
+ "participationNum": "参与次数",
+ "orderTime": "最后下单时间",
+ "memberInfo": "会员信息"
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/admin/lang/zh-cn/marketing.discount.edit.json b/niucloud/addon/shop/admin/lang/zh-cn/marketing.discount.edit.json
new file mode 100644
index 000000000..eb2b7001b
--- /dev/null
+++ b/niucloud/addon/shop/admin/lang/zh-cn/marketing.discount.edit.json
@@ -0,0 +1,38 @@
+{
+ "editDiscount": "编辑限时折扣",
+ "name": "活动名称",
+ "namePlaceholder": "请输入活动名称",
+ "nameTip": "活动名称用于展示在商家后台管理",
+ "title": "标题",
+ "titlePlaceholder": "请输入活动标题",
+ "titleTip": "活动标题用于在手机或者电脑前端,建议输入长度不要大于5",
+ "activityTime": "活动时间",
+ "discountTimePlaceholder": "请选择活动时间",
+ "noSpaceAllowed": "内容不能为空",
+ "selectProduct": "选择商品",
+ "selectProductPlaceholder": "请选择商品",
+ "batchOperation": "批量设置",
+ "batchEmptySelectedGoodsTips": "请选择要操作的商品",
+ "discountType": "折扣类型",
+ "price": "原价",
+ "discounts": "打折",
+ "discountsTips": "[打折]格式错误",
+ "discountsTipsTwo": "打折折扣不可小于0",
+ "discountsTipsThree": "打折折扣不可大于9.9",
+ "discountsPlaceholder": "请输入打折折扣",
+ "reduceMoney": "减钱",
+ "reduceMoneyTips": "[减钱]格式错误",
+ "reduceMoneyTipsTwo": "减钱金额不可小于0",
+ "reduceMoneyTipsThree": "减钱金额不可大于原价金额",
+ "reduceMoneyPlaceholder": "请输入减钱金额",
+ "promotional": "促销价",
+ "promotionalTips": "[促销价]格式错误",
+ "promotionalTipsTwo": "促销价金额不可小于0",
+ "promotionalTipsThree": "促销价金额不可大于原价金额",
+ "promotionalPlaceholder": "请输入促销价",
+ "delete": "删除",
+ "enabled": "设为参与",
+ "noEnabled": "设为不参与",
+ "skuDiscountSettings": "规格折扣设置",
+ "skuDiscountSettingsPlaceholder": "请输入规格折扣设置"
+}
diff --git a/niucloud/addon/shop/admin/lang/zh-cn/marketing.discount.list.json b/niucloud/addon/shop/admin/lang/zh-cn/marketing.discount.list.json
new file mode 100644
index 000000000..79530deef
--- /dev/null
+++ b/niucloud/addon/shop/admin/lang/zh-cn/marketing.discount.list.json
@@ -0,0 +1,54 @@
+{
+ "addDiscount": "添加限时折扣",
+ "name": "名称",
+ "namePlaceholder": "请输入活动名称",
+ "title": "标题",
+ "status": "状态",
+ "statusPlaceholder": "请选择状态",
+ "paymentAmount": "支付金额",
+ "memberCount": "会员数",
+ "orderCount": "订单数",
+ "discountTime": "活动时间",
+ "detail": "详情",
+ "close": "关闭",
+ "closeTips": "活动正在进行中,是否确认关闭当前活动?",
+ "deleteTips": "是否确认删除当前活动",
+ "baseInfo": "基础信息",
+ "createTime": "创建时间",
+ "startTime": "活动开始时间",
+ "endTime": "活动结束时间",
+ "keywordPlaceholder": "请输入商品名称",
+ "keyword": "商品名称",
+ "goodsInfo": "商品信息",
+ "price": "商品价格",
+ "activeOrderMoney": "累计订单金额",
+ "activeOrderNum": "累计订单数",
+ "activeMemberNum": "参与会员数",
+ "activeSuccessNum": "支付销量",
+ "orderInfo": "订单编号",
+ "payTime": "支付时间",
+ "orderNo": "订单编号",
+ "orderMoney": "订单金额",
+ "buyInfo": "买家/收货人",
+ "payType": "支付类型",
+ "orderStatus": "订单状态",
+ "toBePaid": "待支付",
+ "toBeShipped": "待发货",
+ "shipped": "已发货",
+ "receivedGoods": "已收货",
+ "completed": "已完成",
+ "closed": "已关闭",
+ "consumptionMoney": "消费总额",
+ "participationNum": "参与次数",
+ "orderTime": "最后下单时间",
+ "memberInfo": "会员信息",
+ "activeName": "活动名称",
+ "participationMemberCount": "参与会员数",
+ "payOrderCount": "支付订单数",
+ "startDate": "开始时间",
+ "endDate": "结束时间",
+ "batchCloseTips": "是否确认批量关闭当前活动?",
+ "batchDeleteTips": "是否确认批量删除当前活动?",
+ "batchClose":"批量关闭",
+ "batchDelete":"批量删除"
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/admin/lang/zh-cn/marketing.exchange.goods_add.json b/niucloud/addon/shop/admin/lang/zh-cn/marketing.exchange.goods_add.json
new file mode 100644
index 000000000..2f752442f
--- /dev/null
+++ b/niucloud/addon/shop/admin/lang/zh-cn/marketing.exchange.goods_add.json
@@ -0,0 +1,62 @@
+{
+ "addGoods": "添加商品",
+ "baseInfo": "基础设置",
+ "goodsType": "商品类型",
+ "goodsName": "商品名称",
+ "goodsNamePlaceholder": "请输入商品名称",
+ "goodsTitle": "副标题",
+ "goodsTitlePlaceholder": "请输入副标题",
+ "image": "商品图片",
+ "imagePlaceholder": "请选择商品图片",
+ "selectProduct": "选择商品",
+ "selectGoodsPlaceholder": "请选择商品",
+ "goodsStatus": "商品状态",
+ "goodsSelect": "选择商品",
+ "redemptionSettings": "积分设置",
+ "batchOperation": "批量设置",
+ "batchEmptySelectedGoodsTips": "请选择要操作的商品",
+ "goodsSelectPopupGoodsInfo": "商品信息",
+ "price": "销售价",
+ "stock": "兑换库存",
+ "stockPlaceholder": "请输入兑换库存",
+ "stockTips": "[兑换库存]格式错误",
+ "stockTipsTwo": "兑换库存不可小于等于0",
+ "stockTipsThree": "兑换限制数量不可大于商品库存",
+ "limit": "兑换限制",
+ "limitPlaceholder": "请输入兑换限制",
+ "limitTips": "[兑换限制]格式错误",
+ "limitTipsTwo": "兑换限制数量不可小于等于0",
+ "limitTipsThree": "兑换限制数量不能大于兑换库存",
+ "limitUnit": "件/人",
+ "integralUnit": "积分",
+ "prickUnit": "元",
+ "pointPlaceholder": "请输入积分积分",
+ "pointTips": "[积分]格式错误",
+ "pointTipsTwo": "积分不可小于等于0",
+ "money": "兑换价",
+ "newPrice": "价格",
+ "moneyTips": "[价格]格式错误",
+ "moneyTipsTwo": "价格不可小于0",
+ "limitRules": "每人每单可兑换件数",
+ "couponSelect": "选择优惠券",
+ "couponSelectPlaceholder": "请选择优惠券",
+ "couponName": "优惠券名称",
+ "couponType": "类型",
+ "couponPrice": "面值",
+ "sumCount": "总库存",
+ "threshold": "使用门槛",
+ "validType": "有效期",
+ "receiveTypeTime": "领取有效期",
+ "balance": "兑换余额",
+ "balancePlaceholder": "请输入兑换余额",
+ "balanceTips": "[兑换余额]格式错误",
+ "balanceTipsTwo": "兑换余额不可小于等于0",
+ "balanceType": "余额类型",
+ "goodsSkuTitle": "选择商品规格",
+ "goodsSkuPlaceholder": "请选择商品规格",
+ "goodsStock": "库存",
+ "enabled": "设为参与",
+ "noEnabled": "设为不参与",
+ "noEnabledTip": "请至少设置一个规格参与",
+ "goodsDetail": "商品详情"
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/admin/lang/zh-cn/marketing.exchange.goods_edit.json b/niucloud/addon/shop/admin/lang/zh-cn/marketing.exchange.goods_edit.json
new file mode 100644
index 000000000..7b8394145
--- /dev/null
+++ b/niucloud/addon/shop/admin/lang/zh-cn/marketing.exchange.goods_edit.json
@@ -0,0 +1,62 @@
+{
+ "editGoods": "编辑商品",
+ "baseInfo": "基础设置",
+ "goodsType": "商品类型",
+ "goodsName": "商品名称",
+ "goodsNamePlaceholder": "请输入商品名称",
+ "goodsTitle": "副标题",
+ "goodsTitlePlaceholder": "请输入副标题",
+ "image": "商品图片",
+ "imagePlaceholder": "请选择商品图片",
+ "selectProduct": "选择商品",
+ "selectGoodsPlaceholder": "请选择商品",
+ "goodsStatus": "商品状态",
+ "goodsSelect": "选择商品",
+ "redemptionSettings": "积分设置",
+ "batchOperation": "批量设置",
+ "batchEmptySelectedGoodsTips": "请选择要操作的商品",
+ "goodsSelectPopupGoodsInfo": "商品信息",
+ "price": "销售价",
+ "stock": "兑换库存",
+ "stockPlaceholder": "请输入兑换库存",
+ "stockTips": "[兑换库存]格式错误",
+ "stockTipsTwo": "兑换库存不可小于等于0",
+ "stockTipsThree": "兑换限制数量不可大于商品库存",
+ "limit": "兑换限制",
+ "limitPlaceholder": "请输入兑换限制",
+ "limitTips": "[兑换限制]格式错误",
+ "limitTipsTwo": "兑换限制数量不可小于等于0",
+ "limitTipsThree": "兑换限制数量不能大于兑换库存",
+ "limitUnit": "件/人",
+ "integralUnit": "积分",
+ "prickUnit": "元",
+ "pointPlaceholder": "请输入积分积分",
+ "pointTips": "[积分]格式错误",
+ "pointTipsTwo": "积分不可小于等于0",
+ "money": "兑换价",
+ "newPrice": "价格",
+ "moneyTips": "[价格]格式错误",
+ "moneyTipsTwo": "价格不可小于0",
+ "limitRules": "每人每单可兑换件数",
+ "couponSelect": "选择优惠券",
+ "couponSelectPlaceholder": "请选择优惠券",
+ "couponName": "优惠券名称",
+ "couponType": "类型",
+ "couponPrice": "面值",
+ "sumCount": "总库存",
+ "threshold": "使用门槛",
+ "validType": "有效期",
+ "receiveTypeTime": "领取有效期",
+ "balance": "兑换余额",
+ "balancePlaceholder": "请输入兑换余额",
+ "balanceTips": "[兑换余额]格式错误",
+ "balanceTipsTwo": "兑换余额不可小于等于0",
+ "balanceType": "余额类型",
+ "goodsSkuTitle": "选择商品规格",
+ "goodsSkuPlaceholder": "请选择商品规格",
+ "goodsStock": "库存",
+ "enabled": "设为参与",
+ "noEnabled": "设为不参与",
+ "noEnabledTip": "请至少设置一个规格参与",
+ "goodsDetail": "商品详情"
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/admin/lang/zh-cn/marketing.exchange.goods_list.json b/niucloud/addon/shop/admin/lang/zh-cn/marketing.exchange.goods_list.json
new file mode 100644
index 000000000..2d17f9df0
--- /dev/null
+++ b/niucloud/addon/shop/admin/lang/zh-cn/marketing.exchange.goods_list.json
@@ -0,0 +1,33 @@
+{
+ "addGoods": "添加商品",
+ "goods": "商品",
+ "goodsName": "商品名称",
+ "goodsNamePlaceholder": "请输入商品名称",
+ "status": "状态",
+ "statusPlaceholder": "请选择状态",
+ "goodsType": "商品类型",
+ "exchangePrice": "兑换价格",
+ "pointUnit": "积分",
+ "priceUnit": "元",
+ "redeemedAndSurplus": "已兑/剩余",
+ "deleteTips": "是否确认删除当前商品",
+ "createTime": "创建时间",
+ "spreadGoods": "推广",
+ "copyGoods": "复制",
+ "spreadLink": "推广链接",
+ "copy": "复制",
+ "downloadQrcode": "下载二维码",
+ "goodsSpreadTitle": "积分商品推广",
+ "up": "上架",
+ "upTips": "是否确认上架当前商品",
+ "down": "下架",
+ "downTips": "是否确认下架当前商品",
+ "startDate": "开始时间",
+ "endDate": "结束时间",
+ "batchUpTips":"是否确认批量上架选中的商品?",
+ "batchDownTips":"是否确认批量下架选中的商品?",
+ "batchDeleteTips":"是否确认批量删除选中的商品?",
+ "batchUp":"批量上架",
+ "batchDown":"批量下架",
+ "batchDelete":"批量删除"
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/admin/lang/zh-cn/marketing.exchange.order_list.json b/niucloud/addon/shop/admin/lang/zh-cn/marketing.exchange.order_list.json
new file mode 100644
index 000000000..799f7c236
--- /dev/null
+++ b/niucloud/addon/shop/admin/lang/zh-cn/marketing.exchange.order_list.json
@@ -0,0 +1,53 @@
+{
+ "orderNo": "订单编号",
+ "orderNoPlaceholder": "请输入订单编号",
+ "orderStatus": "订单状态",
+ "orderStatusPlaceholder": "请选择订单状态",
+ "orderFrom": "订单类型",
+ "orderFromPlaceholder": "请选择订单类型",
+ "payTime": "支付时间",
+ "orderGoods": "商品",
+ "goodsPriceNumber": "单价(元)/数量",
+ "orderMoney": "实付金额(元)",
+ "startDate": "开始时间",
+ "endDate": "结束时间",
+ "piece": "件",
+ "activeRefund": "主动退款",
+ "notes": "备注",
+ "offlinePayment": "线下支付",
+ "orderClose": "关闭订单",
+ "editPrice": "修改价格",
+ "editAddress": "修改地址",
+ "sendOutGoods": "发货",
+ "confirmTakeDelivery": "确认收货",
+ "all": "全部",
+ "toBeShipped": "待发货",
+ "shipped": "已发货",
+ "receivedGoods": "已收货",
+ "completed": "已完成",
+ "closed": "已关闭",
+ "refunding": "退款中",
+ "notesDetail": "备注信息",
+ "delivery": "订单发货",
+ "company": "物流公司",
+ "companyPlaceholder": "请选择物流公司",
+ "expressNumber": "物流单号",
+ "expressNumberPlaceholder": "请输入物流单号",
+ "orderGoodsIdsPlaceholder": "请选择订单项",
+ "virtualDelivery": "虚拟发货",
+ "goodsName": "商品名称",
+ "num": "商品数量",
+ "orderCloseTips": "关闭订单后该订单将无法支付,是否确认关闭?",
+ "orderFinishTips": "是否确认用户已经收货?",
+ "orderGoodsPlaceholder": "请选择要发货的商品",
+ "deliveryStatusName": "发货状态",
+ "fromType": "订单来源",
+ "payType": "支付类型",
+ "orderInfo": "订单信息",
+ "refundStatusName": "退款状态",
+ "outTradeNo": "交易流水号",
+ "exportOrderType": "导出订单类型",
+ "shopOrder": "订单数据表",
+ "shopOrderGoods": "订单商品表",
+ "point": "积分"
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/admin/lang/zh-cn/marketing.goods_rank.config.json b/niucloud/addon/shop/admin/lang/zh-cn/marketing.goods_rank.config.json
new file mode 100644
index 000000000..8cd1fffb9
--- /dev/null
+++ b/niucloud/addon/shop/admin/lang/zh-cn/marketing.goods_rank.config.json
@@ -0,0 +1,13 @@
+{
+ "rankName": "榜单标题",
+ "rankImages": "榜单图片",
+ "rankRemark": "榜单说明",
+ "save": "保存",
+ "imagePlaceholder": "请上传榜单图片",
+ "rankNamePlaceholder": "请输入榜单名称",
+ "rankRemarkPlaceholder": "请输入榜单说明",
+ "useDefaultRankRemark": "使用默认说明",
+ "noColor": "常规颜色",
+ "selectedColor": "选中文字颜色",
+ "selectedBgColor": "选中背景颜色"
+}
diff --git a/niucloud/addon/shop/admin/lang/zh-cn/marketing.goods_rank.edit.json b/niucloud/addon/shop/admin/lang/zh-cn/marketing.goods_rank.edit.json
new file mode 100644
index 000000000..a920fbd11
--- /dev/null
+++ b/niucloud/addon/shop/admin/lang/zh-cn/marketing.goods_rank.edit.json
@@ -0,0 +1,33 @@
+{
+ "addRanking": "添加榜单",
+ "updateRanking": "修改榜单",
+ "rankName": "榜单名称",
+ "rankBanner": "榜单banner",
+ "imagePlaceholder": "请上传图片",
+ "rankNamePlaceholder": "请输入榜单名称",
+ "rankType": "排行周期",
+ "rankTypePlaceholder": "请选择榜单周期",
+ "batchDeletion": "批量删除",
+ "goodsSource": "商品来源",
+ "goodsSourcePlaceholder": "请选择商品来源",
+ "addCategory": "添加分类",
+ "categoryTips": "商品分类不能为空",
+ "brand": "商品品牌",
+ "brandPlaceholder": "请选择商品品牌",
+ "brandTips": "商品品牌不能为空",
+ "addBrand": "添加品牌",
+ "label": "商品标签",
+ "labelTips": "商品标签不能为空",
+ "addLabel": "添加商品标签",
+ "sort": "排序",
+ "sortPlaceholder": "请输入排序号",
+ "ruleType": "排序规则",
+ "ruleTypePlaceholder": "请选择排序规则",
+ "selectGoods": "选择商品",
+ "sortTips": "排序号格式输入错误",
+ "goodsJsonEmpty": "商品数据不能为空",
+ "limitTips": "输入格式不正确",
+ "rankTypeTips": "天:1天,周:7天,月:30天,季度:90天",
+ "sortRules": "从大到小排列,支持手动修改排序号调整排名,以满足特定需求展示效果",
+ "isShow": "状态"
+}
diff --git a/niucloud/addon/shop/admin/lang/zh-cn/marketing.goods_rank.list.json b/niucloud/addon/shop/admin/lang/zh-cn/marketing.goods_rank.list.json
new file mode 100644
index 000000000..21b99f078
--- /dev/null
+++ b/niucloud/addon/shop/admin/lang/zh-cn/marketing.goods_rank.list.json
@@ -0,0 +1,17 @@
+{
+ "addRanking": "添加榜单",
+ "rankName": "榜单名称",
+ "rankType": "排行周期",
+ "rankNamePlaceholder": "请输入榜单名称",
+ "batchDeletion": "批量删除",
+ "showGoodsNum": "榜单商品数量",
+ "goodsSource": "商品来源",
+ "ruleType": "排序规则",
+ "createTime": "创建时间",
+ "deleteTips": "确定删除该榜单吗?",
+ "batchEmptySelectedGoodsTips": "请先选择要删除的榜单",
+ "batchGoodsDeleteTips": "确定删除选中的榜单吗?",
+ "sortTips": "排序号格式输入错误",
+ "sortRules": "按照排序号从大到小排序",
+ "isShow": "状态"
+}
diff --git a/niucloud/addon/shop/admin/lang/zh-cn/marketing.manjian.detail.json b/niucloud/addon/shop/admin/lang/zh-cn/marketing.manjian.detail.json
new file mode 100644
index 000000000..b3364c6f8
--- /dev/null
+++ b/niucloud/addon/shop/admin/lang/zh-cn/marketing.manjian.detail.json
@@ -0,0 +1,37 @@
+{
+ "baseInfo": "基础信息",
+ "name": "活动名称",
+ "title": "标题",
+ "status": "状态",
+ "paymentAmount": "支付金额",
+ "memberCount": "参与会员数",
+ "orderCount": "支付订单数",
+ "createTime": "创建时间",
+ "startTime": "活动开始时间",
+ "endTime": "活动结束时间",
+ "keywordPlaceholder": "请输入商品名称",
+ "keyword": "商品名称",
+ "goodsInfo": "商品信息",
+ "price": "商品价格",
+ "activeOrderMoney": "累计订单金额",
+ "activeOrderNum": "累计订单数",
+ "activeMemberNum": "参与会员数",
+ "activeSuccessNum": "支付销量",
+ "orderInfo": "订单编号",
+ "payTime": "支付时间",
+ "orderNo": "订单编号",
+ "orderMoney": "订单金额",
+ "buyInfo": "买家/收货人",
+ "payType": "支付类型",
+ "orderStatus": "订单状态",
+ "toBePaid": "待支付",
+ "toBeShipped": "待发货",
+ "shipped": "已发货",
+ "receivedGoods": "已收货",
+ "completed": "已完成",
+ "closed": "已关闭",
+ "consumptionMoney": "消费总额",
+ "participationNum": "参与次数",
+ "orderTime": "最后下单时间",
+ "memberInfo": "会员信息"
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/admin/lang/zh-cn/marketing.manjian.edit.json b/niucloud/addon/shop/admin/lang/zh-cn/marketing.manjian.edit.json
new file mode 100644
index 000000000..e966425e8
--- /dev/null
+++ b/niucloud/addon/shop/admin/lang/zh-cn/marketing.manjian.edit.json
@@ -0,0 +1,88 @@
+{
+ "addFullDiscountBonus": "添加满减送",
+ "editFullDiscountBonus": "修改满减送",
+ "activeName": "活动名称",
+ "activityTime": "活动时间",
+ "namePlaceholder": "请输入活动名称",
+ "conditionType": "条件类型",
+ "overNyuan": "满N元",
+ "overNgoods": "满N件",
+ "ruleType": "优惠规则",
+ "ladder": "阶梯优惠",
+ "cycle": "循环优惠",
+ "ruleJson": "优惠设置",
+ "activityLevel": "活动层级",
+ "addActivityLevel": "添加活动层级",
+ "discountThreshold": "优惠门槛",
+ "placeholder": "请输入",
+ "delete": "删除",
+ "discountContent": "优惠内容",
+ "discountMoney": "订单金额优惠",
+ "reduce": "减价",
+ "discountRate": "打折",
+ "freeShipping": "包邮",
+ "freeTips": "仅参与该活动的商品包邮,非整单包邮",
+ "givePoint": "送积分",
+ "giveGrowth": "送成长值",
+ "giveBalance": "送余额",
+ "giveCoupon": "送优惠券",
+ "giveCouponTips": "如果优惠券数量不足、限领数量已达上限或优惠券状态不是“进行中”,都将导致赠送失败。",
+ "name": "优惠券名称",
+ "type": "优惠券类型",
+ "couponPrice": "优惠券面值",
+ "couponGiveNum": "赠券数",
+ "giveGoods": "送赠品",
+ "giveGoodsTips": "当赠品库存不足或下架时则不赠送",
+ "stock": "库存",
+ "giveNum": "赠送数量",
+ "joinMemberType": "活动对象",
+ "allMember": "所有会员参与",
+ "selectedMemberLevel": "指定会员等级",
+ "selectedMemberLabel": "指定会员标签",
+ "memberLevel": "会员等级",
+ "memberLevelPlaceholder": "请选择会员等级",
+ "memberLabel": "会员标签",
+ "memberLabelPlaceholder": "请选择会员标签",
+ "goodsType": "参与商品",
+ "allGoods": "全部商品参与",
+ "selectedGoods": "指定商品参与",
+ "selectedGoodsNot": "指定商品不参与",
+ "selectGoods": "选择商品",
+ "remark": "备注",
+ "rankRemarkPlaceholder": "请输入备注",
+ "selectActivityTime": "请选择活动时间",
+ "selectActivityStartTime": "请选择活动开始时间",
+ "selectActivityEndTime": "请选择活动结束时间",
+ "selectActivityTimeTips": "活动结束时间不能小于等于活动开始时间",
+ "addLevelLimit": "层级限制最多添加五个",
+ "labelTips": "请选择会员标签",
+ "levelTips": "请选择会员等级",
+ "goodsJsonEmpty": "请选择商品",
+ "couponPlaceholder": "请选择优惠券",
+ "limitPlaceholder": "请输入优惠门槛",
+ "discountsPlaceholder": "请输入折扣或金额",
+ "growthPlaceholder": "请输入赠送成长值",
+ "pointPlaceholder": "请输入赠送积分",
+ "balancePlaceholder": "请输入赠送余额",
+ "valueMustBeGreaterThanZero": "优惠门槛必须大于0",
+ "pointMustBeGreaterThanZero": "赠送积分必须大于0",
+ "balanceMustBeGreaterThanZero": "赠送余额必须大于0",
+ "growthMustBeGreaterThanZero": "赠送成长值必须大于0",
+ "discountMustBeGreaterThanZero": "优惠内容必须大于0",
+ "discountMustBeGreaterThanNine": "范围大于等于0.1且小于等于9.9",
+ "limitTips": "输入格式不正确",
+ "limitTipsTwo": "每个层级的门槛金额不能相同",
+ "addSuccess": "添加成功",
+ "updateSuccess": "编辑成功",
+ "addFail": "添加失败",
+ "updateFail": "编辑失败",
+ "goodOnlyOne": "同一商品在一个时间段内只能参加一个满减送活动",
+ "discountLimit": "优惠金额不能大于优惠门槛",
+ "giveNumPlaceholder": "请输入赠送数量",
+ "giveNumMustBeGreaterThanZero": "赠送数量必须大于0",
+ "giveNumMustBeGreaterThanStock": "赠送数量不能大于库存",
+ "limitTipsThree": "必须大于上一层级的优惠门槛",
+ "ruleTypeTips": "阶梯优惠根据设定的门槛逐级增加优惠,达到特定层级门槛即可享受对应优惠,最高可设5个层级。",
+ "ruleTypeTipsTwo": "循环优惠指每次达到门槛即获赠一次优惠,无次数上限,需合理设置门槛。",
+ "goodsOffTips": "该商品已下架"
+}
diff --git a/niucloud/addon/shop/admin/lang/zh-cn/marketing.manjian.list.json b/niucloud/addon/shop/admin/lang/zh-cn/marketing.manjian.list.json
new file mode 100644
index 000000000..b880d3ee0
--- /dev/null
+++ b/niucloud/addon/shop/admin/lang/zh-cn/marketing.manjian.list.json
@@ -0,0 +1,58 @@
+{
+ "addFullDiscountBonus": "添加满减送",
+ "name": "活动名称",
+ "detailTitle": "满减送活动详情",
+ "activeDetail": "活动详情",
+ "namePlaceholder": "请输入活动名称",
+ "title": "标题",
+ "status": "状态",
+ "statusPlaceholder": "请选择状态",
+ "activityTime": "活动时间",
+ "detail": "详情",
+ "close": "关闭",
+ "closeTips": "活动正在进行中,是否确认关闭当前活动?",
+ "deleteTips": "是否确认删除当前活动",
+ "createTime": "创建时间",
+ "startTime": "活动开始时间",
+ "endTime": "活动结束时间",
+ "keywordPlaceholder": "请输入商品名称",
+ "keyword": "商品名称",
+ "price": "商品价格",
+ "activeOrderMoney": "累计订单金额",
+ "activeOrderNum": "支付订单数",
+ "activeMemberNum": "参与会员数",
+ "paymentAmount": "支付金额",
+ "memberCount": "会员数",
+ "orderCount": "订单数",
+ "activeSuccessNum": "支付销量",
+ "activeName": "活动名称",
+ "participationMemberCount": "参与会员数",
+ "startDate": "开始时间",
+ "endDate": "结束时间",
+ "all": "全部",
+ "orderTime": "最后下单时间",
+ "consumptionMoney": "消费总额",
+ "memberInfo": "会员信息",
+ "participationNum": "参与次数",
+ "goodsInfo": "商品信息",
+ "discountThreshold": "优惠门槛",
+ "giveGoods": "送赠品",
+ "givePoint": "送积分",
+ "giveBalance": "送余额",
+ "giveGrowth": "送成长值",
+ "giveCoupon": "送优惠券",
+ "discountMoney": "订单优惠",
+ "freeShipping": "包邮",
+ "basicInfo": "基本信息",
+ "totalPoint": "累计赠送积分",
+ "totalBalance": "累计赠送余额",
+ "totalCouponNum": "累计赠送优惠券",
+ "totalGoodsNum": "累计赠送商品数",
+ "activeMember": "活动会员",
+ "batchDelete": "批量删除",
+ "batchClose": "批量关闭",
+ "batchEmptySelectedActiveDeleteTips": "请先选择要删除的活动",
+ "batchEmptySelectedActiveCloseTips": "请先选择要关闭的活动",
+ "batchGoodsDeleteTips": "确定删除选中的活动吗?",
+ "batchGoodsCloseTips": "确定关闭选中的活动吗?"
+}
diff --git a/niucloud/addon/shop/admin/lang/zh-cn/marketing.newcomer.config.json b/niucloud/addon/shop/admin/lang/zh-cn/marketing.newcomer.config.json
new file mode 100644
index 000000000..93428e69c
--- /dev/null
+++ b/niucloud/addon/shop/admin/lang/zh-cn/marketing.newcomer.config.json
@@ -0,0 +1,45 @@
+{
+ "basicInfoTab": "基础设置",
+ "bannerList": "顶部广告图",
+ "activeStatus": "是否启用",
+ "validityType": "有效期",
+ "validityDay": "天数",
+ "validityDayPlaceholder": "请输入有效天数",
+ "validityDayTips": "有效天数不可小于等于0",
+ "validityDayTipsLeft": "达成门槛立即生效,",
+ "validityDayTipsRight": "天有效期",
+ "validityTime": "固定时间",
+ "validityTimePlaceholder": "请选择有效期截止时间",
+ "validityTimePlaceholderTwo": "请先选择参与门槛时间",
+ "validityTimePlaceholderThree": "有效期截止时间不可小于参与门槛时间",
+ "validityTimeTips": "达成门槛立即生效,有效期截止为",
+ "validityTimeTipsTwo": "修改有效期将同步更新所有未参与活动用户的结束时间",
+ "participationWay": "参与门槛",
+ "neverOrder": "从未下过单的会员",
+ "assignTimeOrder": "指定时间内未下过单的会员",
+ "assignTimeRegister": "指定时间内注册的会员",
+ "appointTimePlaceholder": "请选择指定时间",
+ "activityGoods": "活动商品",
+ "selectGoods": "选择商品",
+ "goodsSkuIdsPlaceholder": "请选择商品",
+ "limitNum": "限购数量",
+ "limitNumPlaceholder": "请输入限购数量",
+ "limitNumTips": "限购数量不可小于等于0",
+ "limitNumTipsThree": "限购数量不可超过已选商品数量",
+ "oldPrice": "原价",
+ "newcomerPrice": "新人价",
+ "newcomerPricePlaceholder": "请输入新人价",
+ "newcomerPriceTips": "[新人价]格式错误",
+ "newcomerPriceTipsOne": "新人价不可小于0",
+ "newcomerPriceTipsTwo": "新人价不可大于原价",
+ "batchOperation": "批量操作",
+ "batchEmptySelectedGoodsTips": "请选择要操作的商品",
+ "activeDesc": "规则说明",
+ "activeDescPlaceholder": "请输入规则说明",
+ "useDefaultActiveDesc": "使用默认说明",
+ "image": "图片上传",
+ "imagePlaceholder": "请上传图片",
+ "toLink": "跳转链接",
+ "toLinkPlaceholder": "请输入跳转链接",
+ "addConfigList": "添加广告图"
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/admin/lang/zh-cn/marketing.newcomer.order_list.json b/niucloud/addon/shop/admin/lang/zh-cn/marketing.newcomer.order_list.json
new file mode 100644
index 000000000..69e70e816
--- /dev/null
+++ b/niucloud/addon/shop/admin/lang/zh-cn/marketing.newcomer.order_list.json
@@ -0,0 +1,55 @@
+{
+ "orderNo": "订单编号",
+ "orderNoPlaceholder": "请输入订单编号",
+ "orderStatus": "订单状态",
+ "orderStatusPlaceholder": "请选择订单状态",
+ "orderFrom": "订单类型",
+ "orderFromPlaceholder": "请选择订单类型",
+ "payTime": "支付时间",
+ "orderGoods": "商品",
+ "goodsPriceNumber": "单价(元)/数量",
+ "goodsPriceNumberTips": "新人价商品购买数量为1时,单价显示新人价,购买数量大于1时,单价显示原价或折扣价或会员价",
+ "orderMoney": "实付金额(元)",
+ "startDate": "开始时间",
+ "endDate": "结束时间",
+ "piece": "件",
+ "createTime": "创建时间",
+ "activeRefund": "主动退款",
+ "notes": "备注",
+ "offlinePayment": "线下支付",
+ "orderClose": "关闭订单",
+ "editPrice": "修改价格",
+ "editAddress": "修改地址",
+ "sendOutGoods": "发货",
+ "confirmTakeDelivery": "确认收货",
+ "all": "全部",
+ "toBeShipped": "待发货",
+ "shipped": "已发货",
+ "receivedGoods": "已收货",
+ "completed": "已完成",
+ "closed": "已关闭",
+ "refunding": "退款中",
+ "notesDetail": "备注信息",
+ "delivery": "订单发货",
+ "company": "物流公司",
+ "companyPlaceholder": "请选择物流公司",
+ "expressNumber": "物流单号",
+ "expressNumberPlaceholder": "请输入物流单号",
+ "orderGoodsIdsPlaceholder": "请选择订单项",
+ "virtualDelivery": "虚拟发货",
+ "goodsName": "商品名称",
+ "num": "商品数量",
+ "orderCloseTips": "关闭订单后该订单将无法支付,是否确认关闭?",
+ "orderFinishTips": "是否确认用户已经收货?",
+ "orderGoodsPlaceholder": "请选择要发货的商品",
+ "deliveryStatusName": "发货状态",
+ "fromType": "订单来源",
+ "payType": "支付类型",
+ "orderInfo": "订单信息",
+ "refundStatusName": "退款状态",
+ "outTradeNo": "交易流水号",
+ "exportOrderType": "导出订单类型",
+ "shopOrder": "订单数据表",
+ "shopOrderGoods": "订单商品表",
+ "point": "积分"
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/admin/lang/zh-cn/order.batch_delivery.json b/niucloud/addon/shop/admin/lang/zh-cn/order.batch_delivery.json
new file mode 100644
index 000000000..8e063a3c2
--- /dev/null
+++ b/niucloud/addon/shop/admin/lang/zh-cn/order.batch_delivery.json
@@ -0,0 +1,25 @@
+{
+ "failuresNum": "发货失败单数",
+ "succeedNum": "发货成功单数",
+ "totalNum": "总发货单数",
+ "operationTime": "操作时间",
+ "operationType": "操作类型",
+ "state": "状态",
+ "operator": "操作人",
+ "importData": "批量发货",
+ "templateType": "模板类型",
+ "fullOrderDelivery": "整单发货模板",
+ "openOrderDelivery": "拆单发货模板",
+ "uploadFile": "上传文件",
+ "createTime": "时间",
+ "uploadFilePlaceholder": "请上传文件",
+ "operatorPlaceholder": "请选择操作人",
+ "causeFailure": "下载失败记录",
+ "downloadRecord": "下载记录",
+ "orderTemplate": "下载整单发货模板.xls",
+ "orderGoodsTemplate": "下载拆单发货模板.xls",
+ "checkCause": "查看失败原因",
+ "startTime": "开始时间",
+ "endTime": "结束时间",
+ "checkCause1": "失败原因"
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/admin/lang/zh-cn/order.config.json b/niucloud/addon/shop/admin/lang/zh-cn/order.config.json
new file mode 100644
index 000000000..a6cf28909
--- /dev/null
+++ b/niucloud/addon/shop/admin/lang/zh-cn/order.config.json
@@ -0,0 +1,40 @@
+{
+ "closeOrderInfo": "自动取消订单",
+ "closeOrderInfoLeft": "提交订单",
+ "closeOrderInfoRight": "分钟未付款,自动取消订单",
+ "closeOrderInfoBottom": "订单取消时间必须在10-1440分钟之间",
+ "CloseLengthPlaceholder": "请输入订单取消时间",
+ "isClose": "自动取消订单",
+ "confirm": "自动确认收货",
+ "confirmLeft": "发货后",
+ "confirmRight": "天,自动确认收货",
+ "confirmBottom": "自动确认收货时间必须在1-30天之间",
+ "finishLengthPlaceholder": "请输入自动确认收货时间",
+ "isFinish": "自动确认收货",
+ "refund": "确认收货后售后",
+ "refundLeft": "确认收货",
+ "refundRight": "天内,可申请售后",
+ "refundBottom": "确认收货后售后时间必须在1-30天之间",
+ "noAllowRefund": "确认收货后不支持售后",
+ "validRefundLengthPlaceholder": "请输入确认收货后售后时间",
+ "invoice": "发票设置",
+ "isInvoice": "发票开关",
+ "isInvoiceClose": "关闭",
+ "isInvoiceOpen": "开启",
+ "invoiceContent": "发票内容",
+ "insert": "添加",
+ "paperInvoice": "纸质发票",
+ "electronicInvoice": "电子发票",
+ "invoicePlaceholder": "所有发票内容不能为空",
+ "invoiceType": "发票类型",
+ "invoiceTypePlaceholder": "请至少选择一个发票类型",
+ "evaluate": "评价设置",
+ "isEvaluate": "评价开关",
+ "evaluateIsToExamine": "评价审核",
+ "evaluateIsShow": "评价显示",
+ "isEvaluateOpen": "开启",
+ "isEvaluateClose": "关闭",
+ "diyForm": "万能表单",
+ "diyFormPlaceholder": "请选择万能表单",
+ "addDiyForm": "添加表单"
+}
diff --git a/niucloud/addon/shop/admin/lang/zh-cn/order.detail.json b/niucloud/addon/shop/admin/lang/zh-cn/order.detail.json
new file mode 100644
index 000000000..622fd9be7
--- /dev/null
+++ b/niucloud/addon/shop/admin/lang/zh-cn/order.detail.json
@@ -0,0 +1,145 @@
+{
+ "orderNo": "订单编号",
+ "orderInfo": "订单信息",
+ "outTradeNo": "交易流水号",
+ "orderType": "订单类型",
+ "orderForm": "订单来源",
+ "takerName": "收货人",
+ "takerMobile": "收货人手机号",
+ "takerFullAddress": "收货地址",
+ "goodsDetail": "商品信息",
+ "goodsName": "商品名称",
+ "price": "价格",
+ "num": "数量",
+ "goodsMoney": "商品总额",
+ "preferentialMoney": "优惠金额",
+ "deliveryMoney": "配送金额",
+ "operateLog": "订单日志",
+ "orderNoPlaceholder": "请输入订单编号",
+ "orderStatus": "订单状态",
+ "orderStatusPlaceholder": "请选择订单状态",
+ "orderFrom": "订单类型",
+ "orderFromPlaceholder": "请选择订单类型",
+ "payTime": "支付时间",
+ "orderGoods": "商品",
+ "goodsPriceNumber": "单价(元)/数量",
+ "orderMoney": "订单金额",
+ "buyInfo": "买家/收货人",
+ "deliveryType": "配送方式",
+ "startDate": "开始时间",
+ "endDate": "结束时间",
+ "piece": "件",
+ "payType": "支付方式",
+ "notes": "备注",
+ "editAddress": "修改地址",
+ "remind": "提醒",
+ "remindTips1": "买家付款成功后,货款将直接进入您的商户号(微信、支付宝)",
+ "remindTips2": "请及时关注你发出的包裹状态,确保可以配送至买家手中",
+ "remindTips3": "如果买家表示没收到货或货物有问题,请及时联系买家处理,友好协商",
+ "close": "关闭订单",
+ "finish": "确认收货",
+ "delivery": "订单发货",
+ "deliveryTypePlaceholder": "请选择配送方式",
+ "company": "物流公司",
+ "companyPlaceholder": "请选择物流公司",
+ "expressNumber": "物流单号",
+ "expressNumberPlaceholder": "请输入物流单号",
+ "orderGoodsIdsPlaceholder": "请选择订单项",
+ "virtualDelivery": "虚拟发货",
+ "orderCloseTips": "关闭订单后该订单将无法支付,是否确认关闭?",
+ "orderFinishTips": "是否确认用户已经收货?",
+ "orderGoodsPlaceholder": "请选择要发货的商品",
+ "memberRemark": "买家留言",
+ "discountMoney": "总优惠金额",
+ "couponMoney": "优惠券优惠金额",
+ "manjianDiscountMoney": "满减优惠金额",
+ "orderDelivery": "物流信息",
+ "devliveryTime": "发货时间",
+ "companyName": "物流公司",
+ "logisticNo": "物流单号",
+ "packageInfo": "物流包裹信息",
+ "deliveryInfo": "发货信息",
+ "goodsInfo": "商品信息",
+ "logisticInfo": "物流信息",
+ "storeName": "自提点名称",
+ "storeAddress": "自提点地址",
+ "storeMobile": "自提点电话",
+ "tradeTime": "营业时间",
+ "deliveryStatusName": "发货状态",
+ "package": "包裹",
+ "noLogisticsRequired": "无需物流",
+ "notLogistics": "暂无物流信息",
+ "refundStatusName": "退款状态",
+ "orderInfoEmpty": "暂无数据",
+ "editPrice": "修改价格",
+ "adjustMoneyDialogTitle": "调整价格",
+ "adjustMoneyUnit": "元",
+ "adjustMoneyTips": "注意 : 只有订单未付款时才支持改价,改价后请联系买家刷新订单核实订单金额后再支付。当订单总额为0元时,订单将自动支付",
+ "adjustMoneyDeliveryMoney": "运费",
+ "adjustMoneyGoodsInfo": "商品信息",
+ "adjustMoneyPrice": "单价",
+ "adjustMoneyNum": "数量",
+ "adjustMoneySubTotal": "小计",
+ "adjustMoneyDiscountMoney": "优惠金额",
+ "adjustMoneyLabel": "调整金额",
+ "adjustMoneyTotal": "总计",
+ "point": "积分",
+ "electronicSheetPrintTitle": "打印电子面单",
+ "electronicSheetTemplate": "面单模板",
+ "electronicSheetTemplatePlaceholder": "请选择面单模板",
+ "electronicSheetPrintResult": "打印结果",
+ "deliveryPackageNo": "包裹编号",
+ "printStatus": "状态",
+ "printResultCode": "状态码",
+ "printRemark": "备注",
+ "electronicSheetPrintOperation": "打印面单",
+ "printTicket": "打印小票",
+ "deliveryWay": "发货方式",
+ "manualWriteWay": "手动填写",
+ "electronicSheetWay": "电子面单",
+ "contacts": "联系人",
+ "contactsPlaceholder": "请输入联系人",
+ "ContactInformation": "联系方式",
+ "ContactInformationPlaceholder": "请输入联系方式",
+ "selfPickupStores": "自提门店",
+ "address": "地址",
+ "province": "请选择省",
+ "city": "请选择市",
+ "area": "请选择区/县",
+ "detailedAddress": "请输入详细地址",
+ "refundTitle": "商家主动退款",
+ "refundMoney": "退款金额",
+ "voluntaryRefund": "主动退款",
+ "refundState": "完成状态",
+ "refundType": "退款方式",
+ "refundInstructions": "退款说明",
+ "refundInstructionsOne": "1、如果是退部分金额,退款后可以是部分退款状态或退款完成状态",
+ "refundInstructionsTwo": "2、如果是退全部金额,则退款后一定是退款完成状态",
+ "refundInstructionsThree": "3、退款完成才会执行相关业务如核销码失效,卡包失效等操作",
+ "backRefund": "原路退款",
+ "offlineRefund": "线下退款",
+ "refundToBalance": "退款到余额",
+ "partialRefund": "部分退款状态",
+ "refundFinish": "退款完成状态",
+ "shopActiveRefundMoneyPlaceholder": "主动退款金额不能为空或为零",
+ "shopActiveRefundMoneyTwoPlaceholder": "主动退款金额不能大于可退款总额",
+ "refundGoodsItem": "商品项",
+ "refundGoodsInfo": "商品信息",
+ "refundGoodsSku": "规格",
+ "refundGoodsPrice": "售价",
+ "refundPayPrice": "实付金额",
+ "refundGoodsNum": "数量",
+ "refundGoodsPlaceholder": "请选择退款的商品",
+ "formDetail": "表单详情",
+ "buyerAskDeliveryTime": "要求自提时间",
+ "verifyCode": "核销码",
+ "buyers": "买家",
+ "buyersReserveMobile": "预留手机",
+ "storeTakerName": "提货人",
+ "verifierMember": "核销人",
+ "buyerAskDeliveryTime2":"预约配送时间",
+ "deliveryTransporterMobile": "配送员手机号",
+ "deliveryTransporterName": "配送员",
+ "deliveryTransporterStatus":"配送状态",
+ "deliveryTransporterInfo":"配送信息"
+}
diff --git a/niucloud/addon/shop/admin/lang/zh-cn/order.invoice.json b/niucloud/addon/shop/admin/lang/zh-cn/order.invoice.json
new file mode 100644
index 000000000..42c363db7
--- /dev/null
+++ b/niucloud/addon/shop/admin/lang/zh-cn/order.invoice.json
@@ -0,0 +1,40 @@
+{
+ "isInvoice": "是否开票",
+ "isInvoicePlaceholder": "请输入开票类型",
+ "startDate": "开始时间",
+ "endDate": "结束时间",
+ "headType": "抬头类型",
+ "headerTypeName": "抬头类型",
+ "person": "个人",
+ "firm": "企业",
+ "headTypePlaceholder": "请输入抬头类型",
+ "headerName": "发票抬头",
+ "headerNamePlaceholder": "请输入发票抬头",
+ "name": "发票内容",
+ "tradeType": "发票类型",
+ "typeName": "发票名称",
+ "headTypeName": "抬头类型",
+ "taxNumber": "纳税人识别号",
+ "mobile": "手机号",
+ "email": "邮件",
+ "telephone": "电话号",
+ "address": "地址",
+ "bankTame": "开户银行",
+ "bankCardNumber": "开户行账号",
+ "money": "开票金额",
+ "invoiceNumber": "发票号码",
+ "invoiceVoucher": "发票凭证",
+ "remark": "备注",
+ "createTime": "创建时间",
+ "invoiceTime": "开票时间",
+ "status": "状态",
+ "operation": "操作",
+ "detail": "详情",
+ "hasInvoice": "已开票",
+ "noInvoice": "未开票",
+ "all": "全部",
+ "invoice": "开票",
+ "viewOrder": "查看订单",
+ "invoiceNumberPlaceholder": "请输入发票号码",
+ "invoiceVoucherPlaceholder": "请输入发票凭证"
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/admin/lang/zh-cn/order.list.json b/niucloud/addon/shop/admin/lang/zh-cn/order.list.json
new file mode 100644
index 000000000..93f90197b
--- /dev/null
+++ b/niucloud/addon/shop/admin/lang/zh-cn/order.list.json
@@ -0,0 +1,164 @@
+{
+ "orderNo": "订单编号",
+ "createTime": "下单时间",
+ "orderNoPlaceholder": "请输入订单编号",
+ "memberInfo": "会员信息",
+ "memberInfoPlaceholder": "请输入会员编号/昵称/账号/手机号搜索",
+ "orderStatus": "订单状态",
+ "orderStatusPlaceholder": "请选择订单状态",
+ "orderFrom": "订单类型",
+ "orderFromPlaceholder": "请选择订单类型",
+ "payTime": "支付时间",
+ "orderGoods": "商品",
+ "goodsPriceNumber": "单价(元)/数量",
+ "orderMoney": "实付金额(元)",
+ "point": "积分",
+ "buyInfo": "买家/收货人",
+ "deliveryType": "配送方式",
+ "startDate": "开始时间",
+ "endDate": "结束时间",
+ "piece": "件",
+ "rightsProtection": "售后",
+ "activeRefund": "主动退款",
+ "notes": "备注",
+ "offlinePayment": "线下支付",
+ "orderClose": "关闭订单",
+ "editPrice": "修改价格",
+ "editAddress": "修改地址",
+ "sendOutGoods": "发货",
+ "confirmTakeDelivery": "确认收货",
+ "all": "全部",
+ "toBePaid": "待支付",
+ "toBeShipped": "待发货",
+ "shipped": "已发货",
+ "receivedGoods": "已收货",
+ "completed": "已完成",
+ "closed": "已关闭",
+ "refunding": "退款中",
+ "notesDetail": "备注信息",
+ "deliveryTypePlaceholder": "请选择配送方式",
+ "company": "物流公司",
+ "companyPlaceholder": "请选择物流公司",
+ "expressNumber": "物流单号",
+ "expressNumberPlaceholder": "请输入物流单号",
+ "orderGoodsIdsPlaceholder": "请选择订单项",
+ "virtualDelivery": "虚拟发货",
+ "goodsName": "商品名称",
+ "num": "商品数量",
+ "orderCloseTips": "关闭订单后该订单将无法支付,是否确认关闭?",
+ "orderFinishTips": "是否确认用户已经收货?",
+ "orderGoodsPlaceholder": "请选择要发货的商品",
+ "deliveryStatusName": "发货状态",
+ "fromType": "订单来源",
+ "payType": "支付类型",
+ "orderInfo": "订单信息",
+ "refundStatusName": "退款状态",
+ "outTradeNo": "交易流水号",
+ "exportOrderType": "导出订单类型",
+ "shopOrder": "订单数据表",
+ "shopOrderGoods": "订单商品表",
+ "adjustMoneyDialogTitle": "调整价格",
+ "adjustMoneyUnit": "元",
+ "adjustMoneyTips": "注意 : 只有订单未付款时才支持改价,改价后请联系买家刷新订单核实订单金额后再支付。当订单总额为0元时,订单将自动支付",
+ "adjustMoneyDeliveryMoney": "运费",
+ "adjustMoneyGoodsInfo": "商品信息",
+ "adjustMoneyPrice": "单价",
+ "adjustMoneyNum": "数量",
+ "adjustMoneySubTotal": "小计",
+ "adjustMoneyDiscountMoney": "优惠金额",
+ "adjustMoneyLabel": "调整金额",
+ "adjustMoneyTotal": "总计",
+ "contacts": "联系人",
+ "contactsPlaceholder": "请输入联系人",
+ "ContactInformation": "联系方式",
+ "ContactInformationPlaceholder": "请输入联系方式",
+ "address": "地址",
+ "province": "请选择省",
+ "city": "请选择市",
+ "area": "请选择区/县",
+ "detailedAddress": "请输入详细地址",
+ "selfPickupStores": "自提门店",
+ "electronicSheetPrintTitle": "打印电子面单",
+ "electronicSheetTemplate": "面单模板",
+ "electronicSheetTemplatePlaceholder": "请选择面单模板",
+ "electronicSheetPrintResult": "打印结果",
+ "deliveryPackageNo": "包裹编号",
+ "batchPrintElectronicSheet": "批量打印电子面单",
+ "batchEmptySelectedOrderTips": "请选择要操作的订单",
+ "notSupportPrintElectronicSheetTips": "当前选择的订单不支持打印电子面单",
+ "printStatus": "状态",
+ "printResultCode": "状态码",
+ "printRemark": "备注",
+ "electronicSheetPrintOperation": "打印面单",
+ "printTicket": "打印小票",
+ "deliveryWay": "发货方式",
+ "manualWriteWay": "手动填写",
+ "electronicSheetWay": "电子面单",
+ "refundTitle": "商家主动退款",
+ "refundMoney": "退款金额",
+ "voluntaryRefund": "主动退款",
+ "refundState": "完成状态",
+ "refundType": "退款方式",
+ "refundInstructions": "退款说明",
+ "refundInstructionsOne": "1、如果是退部分金额,退款后可以是部分退款状态或退款完成状态",
+ "refundInstructionsTwo": "2、如果是退全部金额,则退款后一定是退款完成状态",
+ "refundInstructionsThree": "3、退款完成才会执行相关业务如核销码失效,卡包失效等操作",
+ "backRefund": "原路退款",
+ "offlineRefund": "线下退款",
+ "refundToBalance": "退款到余额",
+ "partialRefund": "部分退款状态",
+ "refundFinish": "退款完成状态",
+ "shopActiveRefundMoneyPlaceholder": "主动退款金额不能为空或为零",
+ "shopActiveRefundMoneyTwoPlaceholder": "主动退款金额不能大于可退款总额",
+ "refundGoodsItem": "商品项",
+ "refundGoodsInfo": "商品信息",
+ "refundGoodsSku": "规格",
+ "refundGoodsPrice": "售价",
+ "refundPayPrice": "实付金额",
+ "refundGoodsNum": "数量",
+ "refundGoodsPlaceholder": "请选择退款的商品",
+ "orderType": "订单类型",
+ "orderForm": "订单来源",
+ "takerName": "收货人",
+ "takerMobile": "收货人手机号",
+ "takerFullAddress": "收货地址",
+ "goodsDetail": "商品信息",
+ "price": "价格",
+ "detailNum": "数量",
+ "goodsMoney": "商品总额",
+ "preferentialMoney": "优惠金额",
+ "deliveryMoney": "配送金额",
+ "operateLog": "订单日志",
+ "detailOrderMoney": "订单金额",
+ "payWay": "支付方式",
+ "remind": "提醒",
+ "remindTips1": "买家付款成功后,货款将直接进入您的商户号(微信、支付宝)",
+ "remindTips2": "请及时关注你发出的包裹状态,确保可以配送至买家手中",
+ "remindTips3": "如果买家表示没收到货或货物有问题,请及时联系买家处理,友好协商",
+ "close": "关闭订单",
+ "finish": "确认收货",
+ "delivery": "订单发货",
+ "memberRemark": "买家留言",
+ "discountMoney": "总优惠金额",
+ "couponMoney": "优惠券优惠金额",
+ "manjianDiscountMoney": "满减优惠金额",
+ "orderDelivery": "物流信息",
+ "devliveryTime": "发货时间",
+ "companyName": "物流公司",
+ "logisticNo": "物流单号",
+ "packageInfo": "物流包裹信息",
+ "deliveryInfo": "发货信息",
+ "goodsInfo": "商品信息",
+ "logisticInfo": "物流信息",
+ "storeName": "自提点名称",
+ "storeAddress": "自提点地址",
+ "storeMobile": "自提点电话",
+ "tradeTime": "营业时间",
+ "package": "包裹",
+ "noLogisticsRequired": "无需物流",
+ "notLogistics": "暂无物流信息",
+ "orderInfoEmpty": "暂无数据",
+ "buyerAskDeliveryTime": "要求自提时间",
+ "deleteTips": "是否确认删除该订单?",
+ "batchDeleteTips": "是否确认批量删除选中的订单?"
+}
diff --git a/niucloud/addon/shop/admin/lang/zh-cn/order.refund.json b/niucloud/addon/shop/admin/lang/zh-cn/order.refund.json
new file mode 100644
index 000000000..5edc46c7c
--- /dev/null
+++ b/niucloud/addon/shop/admin/lang/zh-cn/order.refund.json
@@ -0,0 +1,108 @@
+{
+ "goodsName": "商品名称",
+ "orderNo": "订单编号",
+ "orderRefundNo": "退款编号",
+ "refundTime": "退款时间",
+ "startDate": "开始时间",
+ "endDate": "结束时间",
+ "goodsNamePlaceholder": "请输入商品名称",
+ "orderNoPlaceholder": "请输入订单编号",
+ "orderRefundNoPlaceholder": "请输入退款编号",
+ "goodsInfo": "商品信息",
+ "orderMoney": "订单金额",
+ "realityMoney": "实付金额",
+ "goodsMoney": "商品金额",
+ "buyMember": "买家",
+ "refundMoney": "退款金额",
+ "createTime": "申请时间",
+ "refundStatus": "退款状态",
+ "all": "全部",
+ "refundType": "退款方式",
+ "applyForRefund": "申请退款",
+ "refundEnd": "售后结束",
+ "toBeReturned": "买家待退货",
+ "receivedGoods": "卖家待收货",
+ "refundRefuse": "卖家拒绝",
+ "orderInfo": "订单信息",
+ "outTradeNo": "交易流水号",
+ "orderType": "订单类型",
+ "orderForm": "订单来源",
+ "takerName": "收货人",
+ "takerMobile": "收货人手机号",
+ "takerFullAddress": "收货地址",
+ "goodsDetail": "商品信息",
+ "price": "价格",
+ "num": "数量",
+ "preferentialMoney": "优惠金额",
+ "deliveryMoney": "配送金额",
+ "operateLog": "订单日志",
+ "orderStatus": "订单状态",
+ "orderStatusPlaceholder": "请选择订单状态",
+ "orderFrom": "订单类型",
+ "orderFromPlaceholder": "请选择订单类型",
+ "payTime": "支付时间",
+ "orderGoods": "商品",
+ "goodsPriceNumber": "单价(元)/数量",
+ "detailOrderMoney": "实付金额(元)",
+ "buyInfo": "买家/收货人",
+ "deliveryType": "配送方式",
+ "piece": "件",
+ "payType": "支付方式",
+ "notes": "备注",
+ "editAddress": "修改地址",
+ "remind": "提醒",
+ "remindTips1": "如果未发货,请点击同意退款给买家。",
+ "remindTips2": "如果实际已发货,请主动与买家联系。",
+ "remindTips3": "如果订单整体退款后,优惠券和余额会退还给买家。",
+ "close": "关闭订单",
+ "finish": "确认收货",
+ "delivery": "订单发货",
+ "deliveryTypePlaceholder": "请选择配送方式",
+ "company": "物流公司",
+ "companyPlaceholder": "请选择物流公司",
+ "expressNumber": "物流单号",
+ "expressNumberPlaceholder": "请输入物流单号",
+ "orderGoodsIdsPlaceholder": "请选择订单项",
+ "virtualDelivery": "虚拟发货",
+ "orderCloseTips": "关闭订单后该订单将无法支付,是否确认关闭?",
+ "orderFinishTips": "是否确认用户已经收货?",
+ "orderGoodsPlaceholder": "请选择要发货的商品",
+ "memberRemark": "买家留言",
+ "discountMoney": "订单详情",
+ "orderDelivery": "物流信息",
+ "devliveryTime": "发货时间",
+ "companyName": "物流公司",
+ "logisticNo": "物流单号",
+ "packageInfo": "物流包裹信息",
+ "deliveryInfo": "发货信息",
+ "logisticInfo": "物流信息",
+ "storeName": "自提点名称",
+ "storeAddress": "自提点地址",
+ "storeMobile": "自提点电话",
+ "tradeTime": "营业时间",
+ "deliveryStatusName": "发货状态",
+ "refundReason": "退款原因",
+ "afterSales": "售后信息",
+ "orderRefundRefuse": "退款拒绝",
+ "orderRefundAgree": "同意退款",
+ "agree": "同意",
+ "applyMoney": "申请金额",
+ "refuse": "拒绝",
+ "transferAccounts": "转账",
+ "refuseReason": "拒绝原因",
+ "shopReasonPlaceholder": "请输入拒绝原因",
+ "confirmDelivery": "确认收货",
+ "orderDeliveryTips": "确定商品收到了吗?",
+ "agreeRefundDelivery": "同意买家收货",
+ "refundDeliveryAddress": "退货地址",
+ "refundVoucher": "申请凭证",
+ "refundRemark": "退款描述",
+ "agreeMoney": "退款金额",
+ "moneyPlaceholder": "请输入退款金额",
+ "refundAddressPlaceholder": "请输入退货地址",
+ "expressCompany": "物流公司",
+ "expressRemark": "物流说明",
+ "orderInfoEmpty": "暂无数据",
+ "closeRefund": "关闭售后",
+ "closeRefundTips": "建议先与用户沟通协商,确认后再关闭售后流程。请谨慎操作,确定要关闭售后吗?"
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/admin/lang/zh-cn/order.refund_detail.json b/niucloud/addon/shop/admin/lang/zh-cn/order.refund_detail.json
new file mode 100644
index 000000000..cd5792721
--- /dev/null
+++ b/niucloud/addon/shop/admin/lang/zh-cn/order.refund_detail.json
@@ -0,0 +1,94 @@
+{
+ "orderNo": "订单编号",
+ "orderInfo": "订单信息",
+ "outTradeNo": "交易流水号",
+ "orderType": "订单类型",
+ "orderForm": "订单来源",
+ "takerName": "收货人",
+ "takerMobile": "收货人手机号",
+ "takerFullAddress": "收货地址",
+ "goodsDetail": "商品信息",
+ "goodsName": "商品名称",
+ "price": "价格",
+ "num": "数量",
+ "goodsMoney": "商品总额",
+ "preferentialMoney": "优惠金额",
+ "deliveryMoney": "配送金额",
+ "operateLog": "订单日志",
+ "orderNoPlaceholder": "请输入订单编号",
+ "orderStatus": "订单状态",
+ "orderStatusPlaceholder": "请选择订单状态",
+ "orderFrom": "订单类型",
+ "orderFromPlaceholder": "请选择订单类型",
+ "payTime": "支付时间",
+ "orderGoods": "商品",
+ "goodsPriceNumber": "单价(元)/数量",
+ "orderMoney": "实付金额(元)",
+ "buyInfo": "买家/收货人",
+ "deliveryType": "配送方式",
+ "startDate": "开始时间",
+ "endDate": "结束时间",
+ "piece": "件",
+ "payType": "支付方式",
+ "notes": "备注",
+ "editAddress": "修改地址",
+ "remind": "提醒",
+ "remindTips1": "如果未发货,请点击同意退款给买家。",
+ "remindTips2": "如果实际已发货,请主动与买家联系。",
+ "remindTips3": "如果订单整体退款后,优惠券和余额会退还给买家。",
+ "close": "关闭订单",
+ "finish": "确认收货",
+ "delivery": "订单发货",
+ "deliveryTypePlaceholder": "请选择配送方式",
+ "company": "物流公司",
+ "companyPlaceholder": "请选择物流公司",
+ "expressNumber": "物流单号",
+ "expressNumberPlaceholder": "请输入物流单号",
+ "orderGoodsIdsPlaceholder": "请选择订单项",
+ "virtualDelivery": "虚拟发货",
+ "orderCloseTips": "关闭订单后该订单将无法支付,是否确认关闭?",
+ "orderFinishTips": "是否确认用户已经收货?",
+ "orderGoodsPlaceholder": "请选择要发货的商品",
+ "memberRemark": "买家留言",
+ "discountMoney": "订单详情",
+ "orderDelivery": "物流信息",
+ "devliveryTime": "发货时间",
+ "companyName": "物流公司",
+ "logisticNo": "物流单号",
+ "packageInfo": "物流包裹信息",
+ "deliveryInfo": "发货信息",
+ "goodsInfo": "商品信息",
+ "logisticInfo": "物流信息",
+ "storeName": "自提点名称",
+ "storeAddress": "自提点地址",
+ "storeMobile": "自提点电话",
+ "tradeTime": "营业时间",
+ "deliveryStatusName": "发货状态",
+ "orderRefundNo": "退款编号",
+ "createTime": "申请时间",
+ "refundMoney": "退款金额",
+ "refundReason": "退款原因",
+ "afterSales": "售后信息",
+ "refundStatus": "退款状态",
+ "orderRefundRefuse": "退款拒绝",
+ "orderRefundAgree": "同意退款",
+ "agree": "同意",
+ "applyMoney": "申请金额",
+ "refuse": "拒绝",
+ "transferAccounts": "转账",
+ "refuseReason": "拒绝原因",
+ "shopReasonPlaceholder": "请输入拒绝原因",
+ "confirmDelivery": "确认收货",
+ "orderDeliveryTips": "确定商品收到了吗?",
+ "agreeRefundDelivery": "同意买家收货",
+ "refundDeliveryAddress": "退货地址",
+ "refundVoucher": "申请凭证",
+ "refundRemark": "退款描述",
+ "agreeMoney": "退款金额",
+ "refundType": "退款方式",
+ "moneyPlaceholder": "请输入退款金额",
+ "refundAddressPlaceholder": "请输入退货地址",
+ "expressCompany": "物流公司",
+ "expressRemark": "物流说明",
+ "orderInfoEmpty": "暂无数据"
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/admin/lang/zh-cn/stat.goods.json b/niucloud/addon/shop/admin/lang/zh-cn/stat.goods.json
new file mode 100644
index 000000000..b89f14d16
--- /dev/null
+++ b/niucloud/addon/shop/admin/lang/zh-cn/stat.goods.json
@@ -0,0 +1,37 @@
+{
+ "goodsOverview": "商品概况",
+ "timeFilter": "时间筛选",
+ "startTime": "开始时间",
+ "endTime": "结束时间",
+ "search": "搜索",
+ "goodsAccessNum": "商品浏览量",
+ "goodsAccessNumTip": "统计时间内,所有商品详情页被访问的次数,一个人在统计时间内访问多次记为多次",
+ "goodsVisitCount": "商品访客数",
+ "goodsVisitCountTips": "统计时间内,访问任何商品详情页的人数,一个人在统计时间范围内访问多次只记为一个",
+ "cartNum": "加购件数",
+ "cartNumTips": "统计时间内,添加商品进入购物车的商品件数",
+ "saleNum": "下单件数",
+ "saleNumTips": "统计时间内,成功下单的商品件数之和(不剔除退款订单)",
+ "payNum": "支付件数",
+ "payNumTips": "统计时间内, 成功付款订单的商品件数之和(不剔除退款订单)",
+ "payMoney": "支付金额",
+ "payMoneyTips": "统计时间内,成功付款订单的商品金额之和(不剔除退款订单)",
+ "refundMoney": "退款金额",
+ "refundMoneyTips": "统计时间内,成功退款的商品金额之和",
+ "refundNum": "退款件数",
+ "refundNumTips": "统计时间内,成功退款的商品件数之和",
+ "goodsRank": "商品排行",
+ "goodsName": "商品名称",
+ "goodsNamePlaceholder": "请输入商品名称",
+ "goodsCategory": "商品分类",
+ "all": "全部",
+ "totalType": "统计类型",
+ "totalTypePlaceholder": "请选择统计类型",
+ "goodsInfo": "商品信息",
+ "accessNum": "访问次数",
+ "visitCount": "访客数",
+ "cartNumber": "加入购物车数量",
+ "saleNumber": "商品销量",
+ "payTotal": "支付总金额",
+ "collectNum": "收藏数量"
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/admin/views/address/edit.vue b/niucloud/addon/shop/admin/views/address/edit.vue
new file mode 100644
index 000000000..5327979e7
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/address/edit.vue
@@ -0,0 +1,432 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/address/list.vue b/niucloud/addon/shop/admin/views/address/list.vue
new file mode 100644
index 000000000..b50b57526
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/address/list.vue
@@ -0,0 +1,157 @@
+
+
+
+
+
+ {{ pageName }}
+ {{ t('addShopAddress') }}
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('search') }}
+ {{ t('reset') }}
+
+
+
+
+
+
+
+ {{ !shopAddressTable.loading ? t('emptyData') : '' }}
+
+
+
+
+
+
+
+ {{ t('deliveryAddress') }}
+ {{ t('default') }}
+
+
+ {{ t('refundAddress') }}
+ {{ t('default') }}
+
+
+
+
+
+
+ {{ t('edit') }}
+ {{ t('delete') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/delivery/company.vue b/niucloud/addon/shop/admin/views/delivery/company.vue
new file mode 100644
index 000000000..f68afcf51
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/delivery/company.vue
@@ -0,0 +1,157 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('search') }}
+ {{ t('reset') }}
+
+
+ {{ t('addCompany') }}
+
+
+
+
+
+
+ {{ !companyTable.loading ? t('emptyData') : '' }}
+
+
+
+
+
+
![]()
+
+
+
+
+
+
+
+
+
+ {{ row.electronic_sheet_switch == 1 ? '支持' : '不支持' }}
+
+
+
+
+ {{ t('edit') }}
+ {{ t('delete') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/delivery/company_edit.vue b/niucloud/addon/shop/admin/views/delivery/company_edit.vue
new file mode 100644
index 000000000..dfe4f45d1
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/delivery/company_edit.vue
@@ -0,0 +1,316 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{{ t('expressNoTips') }}
+
+
+
+
+
+
{{ t('expressNoTips') }}
+
+
+
+
+
+
{{ t('expressNoElectronicSheetTips') }}
+
+
+
+
+
+
+
+
+
+
+ {{ formData.exp_type.length == 0 ? t('emptyData') : '' }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('delete') }}
+
+
+
+
+
+
{{ t('addExpType') }}
+
+
{{ t('expTypeTips') }}
+
{{ t('examine') }}
+
+
{{ t('expTypeTips1') }}
+
+
+
+
+
+
+
+ {{ formData.print_style.length == 0 ? t('emptyData') : '' }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('delete') }}
+
+
+
+
+
+
{{ t('addPrintStyle') }}
+
+
{{ t('printStyleTips') }}
+
{{ t('examine') }}
+
+
{{ t('printStyleTips1') }}
+
{{ t('printStyleTips2') }}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/delivery/components/delivery-personnel-edit.vue b/niucloud/addon/shop/admin/views/delivery/components/delivery-personnel-edit.vue
new file mode 100644
index 000000000..050978958
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/delivery/components/delivery-personnel-edit.vue
@@ -0,0 +1,111 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/delivery/config.vue b/niucloud/addon/shop/admin/views/delivery/config.vue
new file mode 100644
index 000000000..da66460b7
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/delivery/config.vue
@@ -0,0 +1,137 @@
+
+
+
+
+ {{ pageName }}
+
+
+
+
+
+
+
+
+
+
+ {{ item.name }}
+
+
+
+
+
+
+
+
+
{{ t(item.key) }}
+
+
+ {{ t('deliveryStaff') }}
+ {{ t('localConfig') }}
+
+
+ {{ t('deliveryCompany') }}
+ {{ t('deliveryTemplate') }}
+ {{ t('deliverySearch') }}
+
+
+ {{ t('deliveryStore') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/delivery/electronic_sheet.vue b/niucloud/addon/shop/admin/views/delivery/electronic_sheet.vue
new file mode 100644
index 000000000..80f863971
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/delivery/electronic_sheet.vue
@@ -0,0 +1,198 @@
+
+
+
+
+
+ {{pageName}}
+ {{ t('addElectronicSheet') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('search') }}
+ {{ t('reset') }}
+
+
+
+
+
+
+
+ {{ !tableData.loading ? t('emptyData') : '' }}
+
+
+
+ {{ t('isDefault') }}
+ {{row.template_name}}
+
+
+
+
+
+ {{ row.company.company_name }}
+
+
+
+
+
+
+ {{ t('statusOn') }}
+ {{ t('statusOff') }}
+
+
+
+
+
+ {{ t('setDefault') }}
+ {{ t('edit') }}
+ {{ t('delete') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/delivery/electronic_sheet_config.vue b/niucloud/addon/shop/admin/views/delivery/electronic_sheet_config.vue
new file mode 100644
index 000000000..246a0b843
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/delivery/electronic_sheet_config.vue
@@ -0,0 +1,185 @@
+
+
+
+
+
+ {{ pageName }}
+
+
+
+
+
+
+
+
+
+ {{ t('apiSet') }}
+
+
+
+
+ {{ t('kdn') }}
+
+
+
+ {{ t('promptTips1-1') }}
+ https://www.kdniao.com
+
+
+
+
+
+
+
+
+
+
{{ t('kdnEBusinessIDTips') }}
+
+
+
+
+
+
+
{{ t('kdnAppKeyTips') }}
+
+
+
+
+
+
+
+
+ {{ t('printerSet') }}
+
+
+
+ 用双端口加载主JS文件Lodop.js(或CLodopfuncs.js兼容老版本)以防其中某端口被占
+ HTTP推荐端口:8000/18000,HTTPS推荐端口:8443
+ 1. 请将打印机连接至本机。
+ 2. 在本机上安装打印控件。下载链接:http://www.lodop.net/download.html
+ 3. 将打印控件中的打印端口下面的打印端口设为相同。
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/delivery/electronic_sheet_edit.vue b/niucloud/addon/shop/admin/views/delivery/electronic_sheet_edit.vue
new file mode 100644
index 000000000..e7862d447
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/delivery/electronic_sheet_edit.vue
@@ -0,0 +1,270 @@
+
+
+
+
+
+
+
+
+
+ {{ t('basicSettings') }}
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ item.text }}
+
+
+
+
+
+
+
+
+
{{ t('printStyleTips1') }}
+
{{ t('printStyleTips2') }}
+
+
+
+
+
+ {{ t('otherSettings') }}
+
+
+
+
+
+
+
+
+
{{ t('customerPwdTips') }}
+
+
+
+
+
+
+
{{ t('sendSiteTips') }}
+
+
+
+
+
+
+
{{ t('sendStaffTips') }}
+
+
+
+
+
+
+
{{ t('monthCodeTips') }}
+
+
+
+
+
+ {{ item }}
+
+
+
+
+
+
+ {{ t('yes') }}
+ {{ t('no') }}
+
+
{{ t('isNoticeTips') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/delivery/local.vue b/niucloud/addon/shop/admin/views/delivery/local.vue
new file mode 100644
index 000000000..d9feec95f
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/delivery/local.vue
@@ -0,0 +1,749 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('business') }}
+ {{ t('thrid') }}
+
+
+
+
+
+ {{ service.name }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('open') }}
+ {{ t('close') }}
+
+
{{t('timeIsOpenTips')}}
+
+
+
+
+
+ {{ t('everyDay') }}
+ {{ t('custom') }}
+
+
+
+
+ {{ t('monday') }}
+ {{ t('tuesday') }}
+ {{ t('wednesday') }}
+ {{ t('thursday') }}
+ {{ t('friday') }}
+ {{ t('saturday') }}
+ {{ t('sunday') }}
+
+
+
+
+
+
+
+ -
+
+ {{ t('delete') }}
+
+
{{ t('addTime') }}
+
+
{{ t('deliveryTimeTips') }}
+
+
+
+
+
+
+
+ {{ t('30minute') }}
+ {{ t('oneHour') }}
+ {{ t('90minute') }}
+ {{ t('twoHour') }}
+
+
+
+
+
+
+
+
+ {{ t('advance') }}
+
+
+
+ {{ t('day') }}
+
+
{{ t('advanceTips') }}
+
+
+
+
+
+ {{ t('reservationAvailable') }}
+
+
+
+ {{ t('withinDays') }}
+
+
{{ t('mostDaysTips') }}
+
+
+
+
+
+
+
+ {{ defaultDeliveryAddress ? defaultDeliveryAddress.full_address :
+ t('defaultDeliveryAddressEmpty') }}
+ {{ defaultDeliveryAddress ? t('update') : t('toSetting')
+ }}
+
+
+ {{ t('deliveryAddressChange') }}
+
+
+
+
+ {{ t('region') }}
+ {{ t('distance') }}
+
+
+
+
+
+
+
+ {{ t('feeSettingTextOne') }}
+
+
+
+ {{ t('feeSettingTextTwo') }}
+
+
+
+ {{ t('feeSettingTextThree') }}
+
+
+
+ {{ t('priceUnit') }}
+
+
+
+
+ {{ t('weightFeeTextOne') }}
+
+
+
+ {{ t('weightFeeTextTwo') }}
+
+
+
+ {{ t('weightFeeTextThree') }}
+
+
+
+ {{ t('priceUnit') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('radius') }}
+ {{ t('custom') }}
+
+
+
+
{{ t('delete') }}
+
+
+ {{ t('addDeliveryArea') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/delivery/search.vue b/niucloud/addon/shop/admin/views/delivery/search.vue
new file mode 100644
index 000000000..801876024
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/delivery/search.vue
@@ -0,0 +1,164 @@
+
+
+
+
+
+
+
+
+
+
+ {{ t('kdn') }}
+ {{ t('kd100') }}
+
+
+ {{ t('promptTips1-1') }}
+ https://www.kdniao.com
+
+
+ {{ t('promptTips2') }}https://www.kuaidi100.com
+
+
+
+
+
+
+
+ {{ t('PayPerOrder') }}
+ {{ t('PayPerUse') }}
+
+
+ {{ t('promptTips1-2') }}
+
+
+ {{ t('promptTips1-3') }}
+
+
+
+
+
+
+
+
{{ t('kdnEBusinessIDTips') }}
+
+
+
+
+
+
+
{{ t('kdnAppKeyTips') }}
+
+
+
+
+
+
+
+
+
+
{{ t('kd100AppKeyTips') }}
+
+
+
+
+
+
+
{{ t('kd100CustomerTips') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/delivery/staff.vue b/niucloud/addon/shop/admin/views/delivery/staff.vue
new file mode 100644
index 000000000..0c2606c29
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/delivery/staff.vue
@@ -0,0 +1,139 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('search') }}
+ {{ t('reset') }}
+
+
+
+ {{ t('addDeliveryPersonnel') }}
+
+
+
+
+
+
+
+ {{ !tableData.loading ? t('emptyData') : '' }}
+
+
+
+
+
+ {{ t('edit') }}
+ {{ t('delete') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/delivery/store.vue b/niucloud/addon/shop/admin/views/delivery/store.vue
new file mode 100644
index 000000000..bfcafb6e5
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/delivery/store.vue
@@ -0,0 +1,164 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('search') }}
+ {{ t('reset') }}
+
+
+
+ {{ t('addStore') }}
+
+
+
+
+
+
+
+ {{ !storeTable.loading ? t('emptyData') : '' }}
+
+
+
+
+
+
+
+

+
+
+
+
{{ row.store_name }}
+
+
+
+
+
+
+
+
+ {{ row.create_time || '' }}
+
+
+
+
+
+ {{ t('edit') }}
+ {{ t('delete') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/delivery/store_edit.vue b/niucloud/addon/shop/admin/views/delivery/store_edit.vue
new file mode 100644
index 000000000..c0eb5624d
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/delivery/store_edit.vue
@@ -0,0 +1,531 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{{ t('tradeTimeTips') }}
+
+
+
+
+
+ {{ t('monday') }}
+ {{ t('tuesday') }}
+ {{ t('wednesday') }}
+ {{ t('thursday') }}
+ {{ t('friday') }}
+ {{ t('saturday') }}
+ {{ t('sunday') }}
+
+
+
+
+
+
+
+
+
+ -
+
+ {{ t('delete') }}
+
+
{{ t('addTimeRange') }}
+
+
{{ t('storeDateTips') }}
+
+
+
+
+
+
+
+ {{ item.name }}
+
+
{{ t('storeTimeIntervalTips') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/delivery/template.vue b/niucloud/addon/shop/admin/views/delivery/template.vue
new file mode 100644
index 000000000..78d229d01
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/delivery/template.vue
@@ -0,0 +1,144 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('search') }}
+ {{ t('reset') }}
+
+
+
+ {{ t('addTemplate') }}
+
+
+
+
+
+
+
+ {{ !templateTable.loading ? t('emptyData') : '' }}
+
+
+
+
+
+ {{ row.is_free_shipping ? t('open') : t('close') }}
+
+
+
+
+
+ {{ t('edit') }}
+ {{ t('delete') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/delivery/template_edit.vue b/niucloud/addon/shop/admin/views/delivery/template_edit.vue
new file mode 100644
index 000000000..91031345b
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/delivery/template_edit.vue
@@ -0,0 +1,505 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('num') }}
+ {{ t('weight') }}
+ {{ t('volume') }}
+
+
+
+
+
+
+
+ {{ row.fee_area_names ? row.fee_area_names : t('areaPlaceholder') }}
+ {{ row.fee_area_names ? row.fee_area_names : t('areaPlaceholder') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('delete') }}
+
+
+
+
+ {{ t('addDeliveryArea') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('delete') }}
+
+
+
+ {{ t('freeShippingAreaTips') }}
+
+ {{ t('addFreeShippingArea') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('delete') }}
+
+
+
+
+ {{ t('addNoDelivery') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/diy/components/edit-goods-coupon.vue b/niucloud/addon/shop/admin/views/diy/components/edit-goods-coupon.vue
new file mode 100644
index 000000000..3640fa3e6
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/diy/components/edit-goods-coupon.vue
@@ -0,0 +1,254 @@
+
+
+
+
+
+
{{ t('selectStyle') }}
+
+
+ {{ diyStore.editComponent.styleName }}
+
+
+
+
+
+
+
+
+
+
+
![]()
+
+
+
+
+
+
+
+
+
+
+
+
+
{{ t('couponContent') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{{ t('couponData') }}
+
+
+
+
+ {{ t('allSources') }}
+ {{ t('manualSelectionSources') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{{ t("couponTitleStyle") }}
+
+
+
+
+
+
+
+
+
+
+
+
{{ t("couponItemStyle") }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/diy/components/edit-goods-list.vue b/niucloud/addon/shop/admin/views/diy/components/edit-goods-list.vue
new file mode 100644
index 000000000..e4169ef37
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/diy/components/edit-goods-list.vue
@@ -0,0 +1,370 @@
+
+
+
+
+
{{ t('selectStyle') }}
+
+
+
+
+
+
+
+
+
{{ t("selectSource") }}
+
+
+
+ {{ t('default') }}
+ {{ t('sales') }}
+ {{ t('price') }}
+
+
+
+
+ {{ t('goodsSelectPopupAllGoods') }}
+ {{ t('selectCategory') }}
+ {{ t('manualSelectionSources') }}
+
+
+
+
+
+ {{ diyStore.editComponent.goods_category_name }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ !categoryTable.loading ? t('emptyData') : '' }}
+
+
+
+
+ {{ row.category_name }}
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+ {{ t('confirm') }}
+ {{ t('cancel') }}
+
+
+
+
+
+
+
{{ t("goodsBuyBtn") }}
+
+
+
+
+
+
+ {{ t('goodsDetail') }}
+ {{ t('goodsAddCart') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
{{ t("goodsShowContent") }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{{ t('goodsStyle') }}
+
+
+
+
+
+
+
+
+ {{ t('fontWeightNormal') }}
+ {{ t('fontWeightBold') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{{ t("goodsBuyBtn") }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/diy/components/edit-many-goods-list.vue b/niucloud/addon/shop/admin/views/diy/components/edit-many-goods-list.vue
new file mode 100644
index 000000000..6cf3edad5
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/diy/components/edit-many-goods-list.vue
@@ -0,0 +1,654 @@
+
+
+
+
+
{{ t('selectStyle') }}
+
+
+
+ {{ t('headStyle1') }}
+ {{ t('headStyle2') }}
+ {{ t('headStyle3') }}
+ {{ t('headStyle4') }}
+
+
+
+
+
+
+
+
+
{{ t('goodsSet') }}
+
+
+
+ {{ t('default') }}
+ {{ t('sales') }}
+ {{ t('price') }}
+
+
+
+
+
+
+
+
+
{{ t("manyGoodsListCategorySet") }}
+
+
+
+ {{ t('manyGoodsListSourceDiy') }}
+ {{ t('manyGoodsListSourceCategory') }}
+
+
+
+
+
+
+
+
+
+
+
+
{{ t('dragMouseAdjustOrder') }}
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('goodsSelectPopupAllGoods') }}
+ {{ t('selectCategory') }}
+ {{ t('manualSelectionSources') }}
+
+
+
+
+
+ {{ item.goods_category_name }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{{ t('manyGoodsLisAddItem') }}
+
+
+
+
+
+
+
+
+ {{ !firstCategoryTable.loading ? t('emptyData') : '' }}
+
+
+
+ {{ row.category_name }}
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+ {{ t('confirm') }}
+ {{ t('cancel') }}
+
+
+
+
+
+
+
+
+
+
+
{{ t('categoryName') }}
+
{{ t('categoryImage') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ row.category_name }}
+
+
+
+
+
+
+
+
+

+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ item.category_name }}
+
+
+
+
+
+
+
+
+

+
+
+
+

+
+
+
+
+
+
{{ t('emptyData') }}
+
+
+
+ {{ t('confirm') }}
+ {{ t('cancel') }}
+
+
+
+
+
+
+
{{ t("goodsBuyBtn") }}
+
+
+
+
+
+
+ {{ t('goodsDetail') }}
+ {{ t('goodsAddCart') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
{{ t("goodsShowContent") }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{{ t('goodsStyle') }}
+
+
+
+
+
+
+
+
+ {{ t('fontWeightNormal') }}
+ {{ t('fontWeightBold') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{{ t("goodsBuyBtn") }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/diy/components/edit-shop-exchange-goods.vue b/niucloud/addon/shop/admin/views/diy/components/edit-shop-exchange-goods.vue
new file mode 100644
index 000000000..06b5cb4bf
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/diy/components/edit-shop-exchange-goods.vue
@@ -0,0 +1,142 @@
+
+
+
+
+
+
+
{{ t("selectSource") }}
+
+
+
+ {{ t('default') }}
+ {{ t('sales') }}
+ {{ t('price') }}
+
+
+
+
+ {{ t('goodsSelectPopupAllGoods') }}
+ {{ t('manualSelectionSources') }}
+
+
+
+
+
+ {{ t('goodsSelectPopupSelectGoodsButton') }}
+
+
+ {{ t('goodsSelectPopupSelect') }}
+ {{ diyStore.editComponent.goods_ids.length }}
+ {{ t('goodsSelectPopupPiece') }}
+
+
+
+
+
+
+
+
+
+
+
+
{{ t('goodsStyle') }}
+
+
+
+
+
+ {{ t('fontWeightNormal') }}
+ {{ t('fontWeightBold') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/diy/components/edit-shop-exchange-info.vue b/niucloud/addon/shop/admin/views/diy/components/edit-shop-exchange-info.vue
new file mode 100644
index 000000000..c833d13e5
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/diy/components/edit-shop-exchange-info.vue
@@ -0,0 +1,38 @@
+
+
+
+
+
{{ t('memberStyle') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/diy/components/edit-shop-goods-detail-attr.vue b/niucloud/addon/shop/admin/views/diy/components/edit-shop-goods-detail-attr.vue
new file mode 100644
index 000000000..896d4d70b
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/diy/components/edit-shop-goods-detail-attr.vue
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+ {{ t('显示') }}
+ {{ t('隐藏') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/diy/components/edit-shop-goods-detail-basic-info.vue b/niucloud/addon/shop/admin/views/diy/components/edit-shop-goods-detail-basic-info.vue
new file mode 100644
index 000000000..1475d28db
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/diy/components/edit-shop-goods-detail-basic-info.vue
@@ -0,0 +1,334 @@
+
+
+
+
+
{{ t('顶部导航') }}
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('菜单内容最少选择2个') }}
+
+
+
+
+
{{ t('商品媒体') }}
+
+
+
+ {{ t('固定方图') }}
+ {{ t('高度自适应') }}
+ {{ t('注意:高度自适应指商品主图的高度与第一张商品图的高度保持一致') }}
+
+
+
+
+ {{ t('显示') }}
+ {{ t('隐藏') }}
+
+
+
+
+
+
{{ t('价格展示') }}
+
+
+
+ {{ t('常规') }}
+ {{ t('置顶') }}
+
+
+
+
+
+
{{ t('普通价格背景图') }}
+
+
+ {{ diyStore.editComponent.priceRegion.goodsStyle.title }}
+
+
+
+
+
+
+ {{ t('背景图片推荐尺寸:750*148') }}
+
+
+
+
+
{{ t('活动价格背景图') }}
+
+ {{ t('适用场景:限时折扣、新人专享、会员价') }}
+
+ {{ diyStore.editComponent.priceRegion.marketingStyle.title }}
+
+
+
+
+
+
+ {{ t('背景图片推荐尺寸:750*148') }}
+
+
+
+
+
{{ t('销售信息') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
![]()
+
+
+
+
+
+
+
+
+
+
+
+
+
+
![]()
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{{ t('价格样式') }}
+
{{ t('仅在普通价格置顶时或营销活动开启的情况下生效') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{{ t('商品信息样式') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/diy/components/edit-shop-goods-detail-bottom.vue b/niucloud/addon/shop/admin/views/diy/components/edit-shop-goods-detail-bottom.vue
new file mode 100644
index 000000000..d34b48dbb
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/diy/components/edit-shop-goods-detail-bottom.vue
@@ -0,0 +1,127 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('菜单内容最多选择3个,最少选择1个') }}
+
+
+
+ {{ t('显示') }}
+ {{ t('隐藏') }}
+
+ {{ t('注意:该设置在实物商品或虚拟商品且不核销的情况下生效') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{{ t('加入购物车') }}
+
+
+
+
+
+
+
+
+
+ {{ t('topToBottom') }}
+ {{ t('leftToRight') }}
+
+
+
+
+
+
+
+
+
+
+
+
{{ t('立即购买') }}
+
+
+
+
+
+
+
+
+
+ {{ t('topToBottom') }}
+ {{ t('leftToRight') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/diy/components/edit-shop-goods-detail-desc.vue b/niucloud/addon/shop/admin/views/diy/components/edit-shop-goods-detail-desc.vue
new file mode 100644
index 000000000..896d4d70b
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/diy/components/edit-shop-goods-detail-desc.vue
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+ {{ t('显示') }}
+ {{ t('隐藏') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/diy/components/edit-shop-goods-detail-evaluate.vue b/niucloud/addon/shop/admin/views/diy/components/edit-shop-goods-detail-evaluate.vue
new file mode 100644
index 000000000..896d4d70b
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/diy/components/edit-shop-goods-detail-evaluate.vue
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+ {{ t('显示') }}
+ {{ t('隐藏') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/diy/components/edit-shop-goods-detail-purchase-service.vue b/niucloud/addon/shop/admin/views/diy/components/edit-shop-goods-detail-purchase-service.vue
new file mode 100644
index 000000000..bd15cf792
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/diy/components/edit-shop-goods-detail-purchase-service.vue
@@ -0,0 +1,53 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('商品服务最少选择2个') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/diy/components/edit-shop-goods-detail-sow.vue b/niucloud/addon/shop/admin/views/diy/components/edit-shop-goods-detail-sow.vue
new file mode 100644
index 000000000..896d4d70b
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/diy/components/edit-shop-goods-detail-sow.vue
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+ {{ t('显示') }}
+ {{ t('隐藏') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/diy/components/edit-shop-goods-ranking.vue b/niucloud/addon/shop/admin/views/diy/components/edit-shop-goods-ranking.vue
new file mode 100644
index 000000000..ffd34a845
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/diy/components/edit-shop-goods-ranking.vue
@@ -0,0 +1,132 @@
+
+
+
+
+
{{ t('activeCubeBlockContent') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('defaultSources') }}
+ {{ t('manualSelectionSources') }}
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('activeCubeAddItem') }}
+
+
+
+
+
+
+
+
+
{{ t('rankingStyle') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/diy/components/edit-shop-goods-recommend.vue b/niucloud/addon/shop/admin/views/diy/components/edit-shop-goods-recommend.vue
new file mode 100644
index 000000000..0ebd624f9
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/diy/components/edit-shop-goods-recommend.vue
@@ -0,0 +1,188 @@
+
+
+
+
+
{{ t("selectSource") }}
+
+
+
+ {{ t('defaultGoodsSelect') }}
+ {{ t('manualSelectionSources') }}
+
+
+
+
+
+
+
+
+
+
+ {{ t('activeCubeBlockContent') }}
+ {{ t('dragMouseAdjustOrder') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('activeCubeAddItem') }}
+
+
+
+
+
+
+
+
{{ t('goodsStyle') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/diy/components/edit-shop-member-info.vue b/niucloud/addon/shop/admin/views/diy/components/edit-shop-member-info.vue
new file mode 100644
index 000000000..1fa4e4574
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/diy/components/edit-shop-member-info.vue
@@ -0,0 +1,56 @@
+
+
+
+
+
{{ t('memberStyle') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{{ t('memberStyle') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/diy/components/edit-shop-newcomer.vue b/niucloud/addon/shop/admin/views/diy/components/edit-shop-newcomer.vue
new file mode 100644
index 000000000..5643d8533
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/diy/components/edit-shop-newcomer.vue
@@ -0,0 +1,298 @@
+
+
+
+
+
{{ t('styleRecommend') }}
+
+
+ {{ diyStore.editComponent.style.title }}
+
+
+
+
+
+
+
+
+
+
+
![]()
+
+
+
+
+
+
+
+
+
+
+
+
{{ t('titleContent') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{{ t("selectSource") }}
+
+
+
+ {{ t('goodsSelectPopupAllGoods') }}
+ {{ t('manualSelectionSources') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{{ t('goodsStyle') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{{ t('subTitleStyle') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
{{ t('countDownStyle') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/diy/components/edit-shop-order-info.vue b/niucloud/addon/shop/admin/views/diy/components/edit-shop-order-info.vue
new file mode 100644
index 000000000..39ebffa16
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/diy/components/edit-shop-order-info.vue
@@ -0,0 +1,90 @@
+
+
+
+
+
{{ t('titleContent') }}
+
+
+
+
+
+
+
+
+
{{ t('subTitle') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{{ t('titleStyle') }}
+
+
+
+
+
+
+ {{ t('fontWeightNormal') }}
+ {{ t('fontWeightBold') }}
+
+
+
+
+
+
+
+
+
+
{{ t('subTitleStyle') }}
+
+
+
+
+
+
+
+
+
{{ t('textSet') }}
+
+
+
+
+
+
+ {{ t('fontWeightNormal') }}
+ {{ t('fontWeightBold') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/diy/components/edit-shop-search.vue b/niucloud/addon/shop/admin/views/diy/components/edit-shop-search.vue
new file mode 100644
index 000000000..918b606ef
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/diy/components/edit-shop-search.vue
@@ -0,0 +1,34 @@
+
+
+
+
+
+
{{ t('goodsSearchSet') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/diy/components/edit-single-recommend.vue b/niucloud/addon/shop/admin/views/diy/components/edit-single-recommend.vue
new file mode 100644
index 000000000..979854054
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/diy/components/edit-single-recommend.vue
@@ -0,0 +1,337 @@
+
+
+
+
+
{{ t('titleContent') }}
+
+
+ {{ diyStore.editComponent.titleStyle.title }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
![]()
+
+
+
+
+
+
+
+
+
+
+
+
+
{{ t("selectSource") }}
+
+
+
+ {{ t('defaultGoodsSelect') }}
+ {{ t('manualSelectionSources') }}
+
+
+
+
+
+
+
+
+
+
{{ t('imageSet') }}
+
+
+
+
+ {{ t('addImageAd') }}
+
+
+
+
+
+
+
+ {{ !categoryTable.loading ? t('emptyData') : '' }}
+
+
+
+
+ {{ row.category_name }}
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+ {{ t('confirm') }}
+ {{ t('cancel') }}
+
+
+
+
+
+
+
+
{{ t('titleStyle') }}
+
+
+
+
+
+
+
+
{{ t('carouselStyle') }}
+
+
+
+
+
+
+
+
+
+
+
{{ t('recommendIndicatorStyle') }}
+
+
+
+
+
+
+
+
+
+
+
{{ t('goodsStyle') }}
+
+
+
+
+
+
+
+
+ {{ t('fontWeightNormal') }}
+ {{ t('fontWeightBold') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/goods/attr.vue b/niucloud/addon/shop/admin/views/goods/attr.vue
new file mode 100644
index 000000000..ef480195a
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/goods/attr.vue
@@ -0,0 +1,258 @@
+
+
+
+
+
+ {{pageName}}
+ {{ t('addShopGoodsAttr') }}
+
+
+
+
+
+
+
+
+ {{ t('search') }}
+ {{ t('reset') }}
+
+
+
+
+
+
+
+ {{ !goodsAttrTable.loading ? t('emptyData') : '' }}
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('manage') }}
+ {{ t('edit') }}
+ {{ t('delete') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/goods/attr_edit.vue b/niucloud/addon/shop/admin/views/goods/attr_edit.vue
new file mode 100644
index 000000000..1daa12b5b
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/goods/attr_edit.vue
@@ -0,0 +1,442 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ attrInfo.attr_name }}
+
+
+
+ {{ attrInfo.sort }}
+
+
+ {{ t('edit') }}
+
+
+
+ {{ t('addShopGoodsAttr') }}
+
+
+
+ {{ !goodsAttrTable.loading ? t('emptyData') : '' }}
+
+
+
+
+
+
+
+ {{ t('attrValueTypeRadio') }}
+
+
+ {{ t('attrValueTypeCheckbox') }}
+
+
+ {{ t('attrValueTypeText') }}
+
+
+
+
+
+
+
+
+ {{ item.name }}
+
+
+
+ -
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('edit') }}
+ {{ t('delete') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ formAttrValueData.child.length == 0 ? t('emptyData') : '' }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('delete') }}
+
+
+
+
+
+ {{ t('addAttrValue') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/goods/brand_list.vue b/niucloud/addon/shop/admin/views/goods/brand_list.vue
new file mode 100644
index 000000000..ae81f52a3
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/goods/brand_list.vue
@@ -0,0 +1,205 @@
+
+
+
+
+
+ {{ pageName }}
+
+ {{ t('addBrand') }}
+
+
+
+
+
+
+
+
+
+
+ {{ t('search') }}
+ {{ t('reset') }}
+
+
+
+
+
+
+
+ {{ !brandTable.loading ? t('emptyData') : '' }}
+
+
+
+
+ {{ row.brand_name }}
+
+ {{ row.brand_name }}
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('edit') }}
+ {{ t('delete') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/goods/category.vue b/niucloud/addon/shop/admin/views/goods/category.vue
new file mode 100644
index 000000000..3c3a30426
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/goods/category.vue
@@ -0,0 +1,264 @@
+
+
+
+
+ {{ pageName }}
+
+ {{ t('addCategory') }}
+
+
+
+
+
+
+
+
+
+ {{ !categoryTable.loading ? t('emptyData') : '' }}
+
+
+
+
+ {{ row.category_name }}
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+ {{ row.is_show != 2 ? '是' : '否' }}
+
+
+
+
+
+ {{ t('spreadGoodsCategory') }}
+ {{ t('edit') }}
+ {{ t('delete') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/goods/category_config.vue b/niucloud/addon/shop/admin/views/goods/category_config.vue
new file mode 100644
index 000000000..4ea865594
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/goods/category_config.vue
@@ -0,0 +1,236 @@
+
+
+
+ {{ pageName }}
+
+
+
+
+
+
+
+ {{ t('categoryTemplate') }}
+
+
+ {{ t('categorystyleOne') }}
+ {{ t('categorystyleTwo') }}
+
+
+
+
+
+
![]()
+
+
+
+
+
+
+ {{ t('pageSettings') }}
+
+
+
+
+
+ {{ t('open') }}
+ {{ t('close') }}
+
+
+
+
+
+
+
+
+
+
+ {{ t('show') }}
+ {{ t('hidden') }}
+
+
+
+
+
+
+
+ {{ formData.cart.text }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('detail') }}
+ {{ t('cart') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/goods/components/brand-edit.vue b/niucloud/addon/shop/admin/views/goods/components/brand-edit.vue
new file mode 100644
index 000000000..d6cf65751
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/goods/components/brand-edit.vue
@@ -0,0 +1,159 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('colorTips') }}
+
+
+
+ {{ t('colorTips') }}
+
+
+
+ {{ t('colorTips') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/goods/components/category-edit.vue b/niucloud/addon/shop/admin/views/goods/components/category-edit.vue
new file mode 100644
index 000000000..2fd0f87cc
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/goods/components/category-edit.vue
@@ -0,0 +1,144 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/goods/components/coupon-select-popup.vue b/niucloud/addon/shop/admin/views/goods/components/coupon-select-popup.vue
new file mode 100644
index 000000000..54be0890b
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/goods/components/coupon-select-popup.vue
@@ -0,0 +1,302 @@
+
+
+
+
+ {{ t('选择优惠券') }}
+
+ {{ t('已选') }}
+ {{ couponIds.length }}
+ {{ t('张') }}
+
+
+
+
+
+
+
+
+
+
+ {{ t('search') }}
+ {{ t('reset') }}
+
+
+
+
+
+ {{ !couponTable.loading ? t('emptyData') : '' }}
+
+
+
+
+
+
+
+ ¥{{row.price}}
+
+
+
+
+ 无门槛
+ 满{{ row.min_condition_money }}元可用
+
+
+
+
+ 领取之日起{{ row.length || '' }} 天内有效
+ 使用截止时间至{{ row.valid_end_time || ''}}
+
+
+
+
+
+
+
+ {{ t('已选择') }}
+ {{ selectCouponNum }}
+ {{ t('张优惠券') }}
+
+
{{ t('取消选择') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/goods/components/evaluate-add.vue b/niucloud/addon/shop/admin/views/goods/components/evaluate-add.vue
new file mode 100644
index 000000000..61052688a
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/goods/components/evaluate-add.vue
@@ -0,0 +1,155 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('anonymous') }}
+ {{ t('notAnonymous') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/goods/components/goods-batch-settings-popup.vue b/niucloud/addon/shop/admin/views/goods/components/goods-batch-settings-popup.vue
new file mode 100644
index 000000000..6aa8fa546
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/goods/components/goods-batch-settings-popup.vue
@@ -0,0 +1,690 @@
+
+
+
+
+
+
+
+
+ {{ value }}
+
+
+
+
+
+
+
+
+ {{ item.label_name }}
+
+
+ {{ t('refresh') }}
+ {{ t('addGoodsLabel') }}
+
+
+
+
+
+ {{ item.service_name }}
+
+
+ {{ t('refresh') }}
+ {{ t('addGoodsService') }}
+
+
+
+
+
+
+ {{ formData.unit ? formData.unit : '件' }}
+
+
{{ t('virtualSaleNumDesc') }}
+
+
+
+
+
+
+ {{ t('refresh') }}
+ {{ t('addGoodsCategory') }}
+
+
+
+
+
+
+
+
+ {{ t('refresh') }}
+ {{ t('addGoodsBrand') }}
+
+
+
+
+
+
+
+
+ {{ t('refresh') }}
+ {{ t('addGoodsPoster') }}
+
+
+
+
+
+
+ {{ t('yes') }}
+ {{ t('no') }}
+
+
{{ t('giftTips') }}
+
+
+
+
+
+
+
+ {{ item.name }}
+
+
只针对实物商品有效
+
请先在配置设置中设置配送方式
+
+
+
+
+
+
+
+
+
+ {{ t('selectTemplate') }}
+ {{ t('fixedShipping') }}
+
+
+
+
+ {{ t('yuan') }}
+
+
+
+
+
+
+
+ {{ t('refresh') }}
+ {{ t('addDeliveryTemplateId') }}
+
+
+
+
+
+
+
+ {{ t('addStock') }}
+ {{ t('reduceStock') }}
+
+
+
+
+
+
{{ t('stockNumTips') }}
+
+
+
+
+
+ {{ t('不参与') }}
+ {{ t('参与') }}
+
+
+
+
+
+
+
+
+ {{ t('refresh') }}
+ {{ t('addDiyForm') }}
+
+
+
+
+
+
+
+
+ {{ t('refresh') }}
+ 添加模板
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/goods/components/goods-category-select-content.vue b/niucloud/addon/shop/admin/views/goods/components/goods-category-select-content.vue
new file mode 100644
index 000000000..2d32d4d24
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/goods/components/goods-category-select-content.vue
@@ -0,0 +1,231 @@
+
+
+
+
+
+
+
+
{{ t('categoryName') }}
+
{{ t('categoryImage') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ row.category_name }}
+
+
+
+
+
+
+
+
+

+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ item.category_name }}
+
+
+
+
+
+
+
+
+

+
+
+
+

+
+
+
+
+
+
{{ t('emptyData') }}
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/goods/components/goods-category-spread-popup.vue b/niucloud/addon/shop/admin/views/goods/components/goods-category-spread-popup.vue
new file mode 100644
index 000000000..f41c0fb19
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/goods/components/goods-category-spread-popup.vue
@@ -0,0 +1,102 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/goods/components/goods-member-price-popup.vue b/niucloud/addon/shop/admin/views/goods/components/goods-member-price-popup.vue
new file mode 100644
index 000000000..33c07334f
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/goods/components/goods-member-price-popup.vue
@@ -0,0 +1,294 @@
+
+
+
+
+
+
+
+
+ {{ t('nonparticipation') }}
+ {{ t('discount') }}
+ {{ t('fixedPrice') }}
+
+
{{t('discountHint')}}
+
{{t('fixedPriceHint')}}
+
+
+
+
+
+ {{ !tableData.loading ? t('emptyData') : '' }}
+
+
+
+ {{t('memberEnjoyDiscount')}}
+
+
+
+
+ {{item.level_benefits.discount.discount}}
+
+
+
+
+
+
+
+
+ {{item.level_name}}
+
+
+
+
+ {{ !tableData.loading ? t('emptyData') : '' }}
+
+
+
+
+
+
+
+ {{t('yuanUnit')}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/goods/components/goods-price-edit-popup.vue b/niucloud/addon/shop/admin/views/goods/components/goods-price-edit-popup.vue
new file mode 100644
index 000000000..bdd466024
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/goods/components/goods-price-edit-popup.vue
@@ -0,0 +1,296 @@
+
+
+
+
+
+
+
+
+
+

+
+
+
+

+
+
+ {{ goods.goods_name }}
+ {{ goods.goods_type_name }}
+
+
+
+
+
+
+
+
+
+ {{ t('confirm') }}
+ {{ t('cancel') }}
+
+
+ {{ t('price') }}
+ {{ t('marketPrice') }}
+ {{ t('costPrice') }}
+
+
+
+
+
+ {{ !goodsTable.loading ? t('emptyData') : '' }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/goods/components/goods-select-content.vue b/niucloud/addon/shop/admin/views/goods/components/goods-select-content.vue
new file mode 100644
index 000000000..d147025b4
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/goods/components/goods-select-content.vue
@@ -0,0 +1,360 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('search') }}
+ {{ t('reset') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+

+
+
+ {{ row.goods_name }}
+ {{ row.goods_type_name }}
+ 赠品
+
+
+
¥{{ row.goodsSku.price }}
+
{{ row.stock }}
+
+
+
+
暂无数据
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/goods/components/goods-select-popup.vue b/niucloud/addon/shop/admin/views/goods/components/goods-select-popup.vue
new file mode 100644
index 000000000..9659b24c7
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/goods/components/goods-select-popup.vue
@@ -0,0 +1,711 @@
+
+
+
+
+ {{ t('goodsSelectPopupSelectGoodsButton') }}
+
+ {{ t('goodsSelectPopupSelect') }}
+ {{ goodsIds.length }}
+ {{ t('goodsSelectPopupPiece') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('search') }}
+ {{ t('reset') }}
+
+
+
+
+
+
+
+
+
+
商品信息
+
商品价格
+
库存
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+

+
+
+ {{ row.goods_name }}
+ {{ row.goods_type_name }}
+ 赠品
+
+
+
¥{{ row.goodsSku.price }}
+
{{row.stock}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+

+
+
+ {{ item.sku_name || row.goods_name }}
+ {{ row.goods_type_name }}
+
+
+
¥{{ item.price }}
+
{{ item.stock }}
+
+
+
+
+
暂无数据
+
+
+
+
+
+
+ {{ t('goodsSelectPopupBeforeTip') }}
+ {{ selectGoodsNum }}
+ {{ t('goodsSelectPopupAfterTip') }}
+
+
{{ t('goodsSelectPopupClearGoods') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/goods/components/goods-spread-popup.vue b/niucloud/addon/shop/admin/views/goods/components/goods-spread-popup.vue
new file mode 100644
index 000000000..70aebafeb
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/goods/components/goods-spread-popup.vue
@@ -0,0 +1,112 @@
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/goods/components/goods-stock-edit-popup.vue b/niucloud/addon/shop/admin/views/goods/components/goods-stock-edit-popup.vue
new file mode 100644
index 000000000..3bb9e4b12
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/goods/components/goods-stock-edit-popup.vue
@@ -0,0 +1,238 @@
+
+
+
+
+
+
+
+
+
+

+
+
+
+

+
+
+ {{ goods.goods_name }}
+ {{ goods.goods_type_name }}
+
+
+
+
+
+
+
+ {{ t('confirm') }}
+
+
+
+
+ {{ !goodsTable.loading ? t('emptyData') : '' }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/goods/components/label-edit.vue b/niucloud/addon/shop/admin/views/goods/components/label-edit.vue
new file mode 100644
index 000000000..89b9920e8
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/goods/components/label-edit.vue
@@ -0,0 +1,187 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('styleByDiy') }}
+ {{ t('styleByIcon') }}
+
+
+
+
+ {{ t('colorTips') }}
+
+
+
+ {{ t('colorTips') }}
+
+
+
+ {{ t('colorTips') }}
+
+
+
+
+ {{ t('iconTips') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/goods/components/label-group-edit.vue b/niucloud/addon/shop/admin/views/goods/components/label-group-edit.vue
new file mode 100644
index 000000000..a7dfc8c83
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/goods/components/label-group-edit.vue
@@ -0,0 +1,109 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/goods/components/newcomer-goods-select-popup.vue b/niucloud/addon/shop/admin/views/goods/components/newcomer-goods-select-popup.vue
new file mode 100644
index 000000000..c6a004c56
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/goods/components/newcomer-goods-select-popup.vue
@@ -0,0 +1,693 @@
+
+
+
+
+ {{ t('goodsSelectPopupSelectGoodsButton') }}
+
+ {{ t('goodsSelectPopupSelect') }}
+ {{ goodsIds.length }}
+ {{ t('goodsSelectPopupPiece') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('search') }}
+ {{ t('reset') }}
+
+
+
+
+
+
+
+
+
+
商品信息
+
商品价格
+
库存
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+

+
+
+ {{ row.goods_name }}
+ {{ row.goods_type_name }}
+
+
+
¥{{ row.skuList.length > 1 ? row.goodsSku.price : row.goodsSku.newcomer_price }}
+
{{row.stock}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+

+
+
+ {{ item.sku_name || row.goods_name }}
+ {{ row.goods_type_name }}
+
+
+
¥{{ item.newcomer_price }}
+
{{ item.stock }}
+
+
+
+
+
暂无数据
+
+
+
+
+
+
+ {{ t('goodsSelectPopupBeforeTip') }}
+ {{ selectGoodsNum }}
+ {{ t('goodsSelectPopupAfterTip') }}
+
+
{{ t('goodsSelectPopupClearGoods') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/goods/components/service-edit.vue b/niucloud/addon/shop/admin/views/goods/components/service-edit.vue
new file mode 100644
index 000000000..d4ba688c3
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/goods/components/service-edit.vue
@@ -0,0 +1,112 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/goods/evaluate.vue b/niucloud/addon/shop/admin/views/goods/evaluate.vue
new file mode 100644
index 000000000..8771044e9
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/goods/evaluate.vue
@@ -0,0 +1,425 @@
+
+
+
+
+
+ {{ pageName }}
+ {{ t('addEvaluate') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('search') }}
+ {{ t('reset') }}
+
+
+
+
+
+
+
+ {{t("batchDelete")}}
+ {{t("batchAdopt")}}
+ {{t("batchRefuse")}}
+
+
+
+ {{ !evaluateTable.loading ? t('emptyData') : '' }}
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+

+
+
+
{{ row.goods.goods_name }}
+
+
+
+
+
+
+
+
{{ row.content }}
+
+
+
+
+
+

+
+
+
+

+
+
+
{{ t('explainFirst') }}:{{ row.explain_first }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('adopt') }}
+ {{ t('refuse') }}
+ {{ t('reply') }}
+ {{ t('delete') }}
+ {{ t('topping') }}
+ {{ t('cancelTopping') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/goods/label_group_list.vue b/niucloud/addon/shop/admin/views/goods/label_group_list.vue
new file mode 100644
index 000000000..d5b0a8bad
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/goods/label_group_list.vue
@@ -0,0 +1,195 @@
+
+
+
+
+
+ {{pageName}}
+
+ {{ t('addLabelGroup') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('search') }}
+ {{ t('reset') }}
+
+
+
+
+
+
+
+ {{ !labelTable.loading ? t('emptyData') : '' }}
+
+
+
+
+
+
+
+
+
+
+ {{ t('edit') }}
+ {{ t('delete') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/goods/label_list.vue b/niucloud/addon/shop/admin/views/goods/label_list.vue
new file mode 100644
index 000000000..a206120ae
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/goods/label_list.vue
@@ -0,0 +1,282 @@
+
+
+
+
+
+ {{pageName}}
+
+ {{ t('addLabel') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('search') }}
+ {{ t('reset') }}
+
+
+
+
+
+
+
+ {{ !labelTable.loading ? t('emptyData') : '' }}
+
+
+
+
+ {{ row.label_name }}
+
+
+
+
+
+
+ {{ row.group.group_name }}
+ --
+
+
+
+
+ {{ t('statusOn') }}
+ {{ t('statusOff') }}
+
+
+
+
+
+
+
+
+
+
+
+ {{ row.create_time }}
+
+
+
+
+
+ {{ t('edit') }}
+ {{ t('delete') }}
+ {{ t('copyLabel') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/goods/list.vue b/niucloud/addon/shop/admin/views/goods/list.vue
new file mode 100644
index 000000000..49de2a2f6
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/goods/list.vue
@@ -0,0 +1,945 @@
+
+
+
+
+
+ {{ pageName }}
+ {{ t('addGoods') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+ -
+
+
+
+
+
+ {{ t('search') }}
+ {{ t('reset') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ currentSelectMode === 'all' ? t('全选所有页') : t('全选当前页')}}({{ selectedCount }})
+
+
+
+
+
+
+
+ 全选所有页
+
+
+ 全选当前页
+
+
+
+
+
+
+
{{ t('batchOnGoods') }}
+
{{ t('batchOffGoods') }}
+
{{ t('batchDeleteGoods') }}
+
{{ t('batchSetting') }}
+
+
+
+
+ {{ !goodsTable.loading ? t('emptyData') : '' }}
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+

+
+
+
{{ row.goods_name }}
+
{{ row.goods_type_name }}
+
赠品
+
+
+
+
+ {{item.name.trim() || item.short?.active_name }}
+
+
+
+ {{ item.short?.name }}
+
+
+
+
+
+
+
+
+
+
+
+ ¥{{ row.goodsSku.price }}
+
+
+
+
+
+
+
+
+
+
+ {{ row.stock }}
+
+
+
+
+
+
+
+
+
+ {{ t('statusOn') }}
+ {{ t('statusOff') }}
+
+
+
+
+
+
+
+
+
+
+ {{ row.create_time }}
+
+
+
+
+
+ {{ t('edit') }}
+ {{ t('spreadGoods') }}
+ {{ t('memberPrice') }}
+ {{ t('statusActionOff') }}
+ {{ t('statusActionOn') }}
+ {{ t('copyGoods') }}
+ {{ t('delete') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/goods/public/css/goods_edit.scss b/niucloud/addon/shop/admin/views/goods/public/css/goods_edit.scss
new file mode 100644
index 000000000..6c497868a
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/goods/public/css/goods_edit.scss
@@ -0,0 +1,231 @@
+.goods-type-wrap {
+ width: 120px;
+ height: 60px;
+ background: #fff;
+ border-radius: 3px;
+ float: left;
+ text-align: center;
+ padding-top: 8px;
+ position: relative;
+ cursor: pointer;
+ line-height: 23px;
+ border: 1px solid #e7e7e7;
+
+ .goods-type-name {
+ font-size: 14px;
+ font-weight: 600;
+ color: rgba(0, 0, 0, .85);
+ }
+
+ .goods-type-desc {
+ font-size: 12px;
+ font-weight: 400;
+ color: #999;
+ }
+
+ .triangle {
+ position: absolute;
+ bottom: 0;
+ right: 0;
+ width: 0;
+ height: 0;
+ border-bottom: 26px solid var(--el-color-primary);
+ border-left: 26px solid transparent;
+ }
+
+ .selected {
+ position: absolute;
+ bottom: -2px;
+ right: 2px;
+ color: #fff;
+ }
+
+ &.selected {
+ border: 1px solid var(--el-color-primary);
+ }
+
+ &.disabled {
+ cursor: not-allowed;
+
+ .goods-type-name {
+ color: #999;
+ }
+ }
+
+ &:nth-child(2n) {
+ margin: 0 12px;
+ }
+
+}
+
+.spec-wrap {
+ flex: 1;
+
+ .spec-edit-list {
+ .spec-item {
+ background: #f7f7f7;
+ padding: 20px;
+ margin-bottom: 20px;
+ position: relative;
+ border-radius: 6px;
+
+ .spec-name-wrap {
+ /*margin-bottom: 20px;*/
+ }
+
+ .spec-value-wrap {
+ padding: 25px 30px 0 30px;
+ position: relative;
+
+ ul {
+
+ display: flex;
+ flex-wrap: wrap;
+ flex: 1;
+ align-items: baseline;
+
+ li {
+ margin: 0 10px 10px 0;
+ position: relative;
+
+ .input-width {
+ width: 200px;
+ }
+
+ .icon {
+ width: 32px;
+ padding: 0;
+ display: none;
+ position: absolute;
+ top: -12px;
+ right: -20px;
+ cursor: pointer;
+ }
+
+ &:hover {
+ .icon {
+ display: block;
+ }
+ }
+ }
+
+ }
+
+ .add-spec-value {
+ cursor: pointer;
+ user-select: none;
+ }
+
+ .box {
+ position: absolute;
+ top: 0;
+ left: 10px;
+ width: 20px;
+ height: 40px;
+ border: 1px solid #b8b9bd;
+ border-top: none;
+ border-right: none;
+ }
+ }
+
+ .del-spec {
+ border: none;
+ position: absolute;
+ top: 10px;
+ right: 10px;
+ display: none;
+ cursor: pointer;
+
+ }
+
+ &:hover {
+ .del-spec {
+ display: block;
+ }
+ }
+ }
+ }
+}
+
+.el-input__suffix {
+ cursor: pointer;
+}
+
+.el-table__row:focus {
+ outline: none !important;
+}
+
+.add-spec {
+ margin-bottom: 16px;
+}
+
+.batch-operation-sku {
+ display: flex;
+ margin-bottom: 16px;
+ background-color: #ffffff;
+ -ms-flex-wrap: nowrap;
+ flex-wrap: nowrap;
+ -webkit-box-align: center;
+ -ms-flex-align: center;
+ align-items: center;
+
+ label {
+ font-size: 14px;
+ margin-right: 10px;
+ }
+
+ .set-spec-select {
+ margin-right: 10px;
+ max-width: 130px;
+ }
+
+ .set-input {
+ max-width: 130px;
+ min-width: 60px;
+ margin-right: 10px;
+ }
+}
+
+.editor-width {
+ width: 990px;
+}
+
+.sku-table {
+ :focus {
+ outline: none;
+ }
+}
+
+.sku-form-item-wrap :deep(.el-form-item__content) {
+ margin-left: 0 !important;
+}
+
+.sku-table :deep(.el-table__cell .cell) {
+ overflow: initial !important;
+}
+
+.attr-table {
+ width: 859px;
+ border: 1px solid #e6e6e6;
+
+ thead tr, tbody tr {
+ border-bottom: 1px solid #e6e6e6;
+ }
+
+ thead th, tbody td {
+ padding: 5px 10px;
+ border-right: 1px solid #e6e6e6;
+ }
+
+ thead th {
+ text-align: left;
+ font-weight: normal;
+ font-size: 14px;
+ color: #666;
+ box-sizing: border-box;
+ }
+}
+
+.fixed-footer {
+ z-index: 4;
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/admin/views/goods/public/js/useGoodsEdit.ts b/niucloud/addon/shop/admin/views/goods/public/js/useGoodsEdit.ts
new file mode 100644
index 000000000..d286cef42
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/goods/public/js/useGoodsEdit.ts
@@ -0,0 +1,1694 @@
+import { reactive, ref, computed, nextTick } from 'vue'
+import { t } from '@/lang'
+import { TabsPaneContext, ElMessage } from 'element-plus'
+import Sortable from 'sortablejs'
+import { range, cloneDeep } from 'lodash-es'
+import { debounce, deepClone } from '@/utils/common'
+import { useRoute, useRouter } from 'vue-router'
+import Test from '@/utils/test'
+import {
+ getGoodsType,
+ getBrandList,
+ getLabelList,
+ getServeList,
+ getSupplierList,
+ getCategoryTree,
+ getAttrList,
+ goodsVerify,
+ getGoodsInfoTemplate
+} from '@/addon/shop/api/goods'
+import { getPosterList } from '@/app/api/poster'
+import { getDiyFormList } from '@/app/api/diy_form'
+
+// 商品添加/编辑
+export function useGoodsEdit(params: any = {}) {
+
+ const route = useRoute()
+ const router = useRouter()
+
+ const repeat = ref(false)
+
+ // 表单数据
+ const formData: any = reactive({
+ goods_id: '',
+ goods_type: 'real',
+
+ // 基础信息
+ goods_name: '',
+ sub_title: '',
+ goods_image: '',
+ goods_video: '',
+ goods_category: '',
+ brand_id: '',
+ poster_id: '',
+ diy_detail_id: '',
+ form_id: '',
+ label_ids: [],
+ service_ids: [],
+ supplier_id: '',
+ status: '1',
+ is_gift: 0,
+ sort: '',
+
+ addon_shop_supplier: [],
+
+ // 价格库存
+ spec_type: 'single',
+ price: '',
+ market_price: '',
+ cost_price: '',
+ stock: '',
+ sku_no: '',
+ unit: '',
+ virtual_sale_num: '',
+ member_discount: '',
+ is_limit: 0,
+ limit_type: 1,
+ max_buy: '',
+ min_buy: '',
+
+ // 商品参数
+ attr_ids: [],
+ attr_format: [],
+
+ // 商品详情
+ goods_desc: '',
+ skuCheckAll: false,// 是否全选
+ skuIsIndeterminate: false,// 是否部分选中
+ skuCheckedCities: [],// 选中的规格
+ })
+
+ Object.assign(formData, params.formData);
+
+ formData.goods_id = ref(route.query.goods_id)
+
+ // 追加表单数据
+ const appendFormData = params.appendFormData;
+ Object.assign(formData, appendFormData);
+
+ // 追加刷新商品sku数据
+ const appendRefreshGoodsSkuData = params.appendRefreshGoodsSkuData || {};
+
+ // 追加单规格数据
+ const appendSingleGoodsData = params.appendSingleGoodsData;
+
+ const getFormRules = params.getFormRules;
+
+ const formRefArr: any = reactive({});
+
+ const getFormRef = params.getFormRef;
+
+ const verifyArr: any = reactive([])
+
+ nextTick(() => {
+ let formRef = getFormRef();
+ for (let key in formRef) {
+ formRefArr[key] = formRef[key];
+ }
+
+ if (params.getVerify) {
+ verifyArr.splice(0, verifyArr.length, ...params.getVerify())
+ }
+
+ });
+
+ const editApi = params.editApi;
+ const addApi = params.addApi;
+
+ const activeName: any = ref('basic')
+ const tabHandleClick = (tab: TabsPaneContext, event: Event) => {
+ // console.log(tab, event)
+ }
+
+ // 商品类型
+ const goodsType = reactive([])
+
+ // 切换商品类型
+ const changeGoodsType = (data: any) => {
+ router.push(data.path)
+ }
+
+ // 商品类型
+ getGoodsType().then((res) => {
+ const data = res.data
+ if (data) {
+ for (const k in data) {
+ goodsType.push(data[k])
+ }
+ }
+ })
+
+ // 商品分类
+ const goodsCategoryOptions = reactive([])
+ const goodsCategoryProps = {
+ multiple: true
+ }
+
+ const categoryHandleChange = (value: any) => {
+ // console.log(value, goodsEdit.formData.goods_category, goodsEdit.formData.goods_category.toString())
+ }
+
+ // 跳转到商品分类,添加分类
+ const toGoodsCategoryEvent = () => {
+ const url = router.resolve({
+ path: '/shop/goods/category'
+ })
+ window.open(url.href)
+ }
+
+ // 刷新商品分类
+ const refreshGoodsCategory = (bool = false) => {
+ getCategoryTree().then((res) => {
+ const data = res.data
+ if (data) {
+ const goodsCategoryTree: any = []
+ data.forEach((item: any) => {
+ const children: any = []
+ if (item.child_list) {
+ item.child_list.forEach((childItem: any) => {
+ children.push({
+ value: childItem.category_id,
+ label: childItem.category_name
+ })
+ })
+ }
+ goodsCategoryTree.push({
+ value: item.category_id,
+ label: item.category_name,
+ children
+ })
+ })
+ goodsCategoryOptions.splice(0, goodsCategoryOptions.length, ...goodsCategoryTree)
+ if (bool) {
+ ElMessage({
+ message: t('refreshSuccess'),
+ type: 'success'
+ })
+ }
+ }
+ })
+ }
+
+ refreshGoodsCategory()
+
+ // 品牌列表下拉框
+ const brandOptions = reactive([])
+
+ // 跳转到商品品牌,添加品牌
+ const toGoodsBrandEvent = () => {
+ const url = router.resolve({
+ path: '/shop/goods/brand'
+ })
+ window.open(url.href)
+ }
+
+ // 商品品牌
+ // const refreshGoodsBrand = (bool = false) => {
+ // getBrandList({}).then((res) => {
+ // const data = res.data
+ // if (data) {
+ // brandOptions.splice(0, brandOptions.length, ...data)
+ // if (bool) {
+ // ElMessage({
+ // message: t('refreshSuccess'),
+ // type: 'success'
+ // })
+ // }
+ // }
+ // })
+ // }
+ const refreshGoodsBrand = (query='', bool = false) => {
+ getBrandList({brand_name: query}).then((res) => {
+ const data = res.data
+ if (data) {
+ brandOptions.splice(0, brandOptions.length, ...data)
+ if (bool) {
+ ElMessage({
+ message: t('refreshSuccess'),
+ type: 'success'
+ })
+ }
+ }
+ })
+ }
+ // 不能注释,编辑时需要提前加载
+ refreshGoodsBrand()
+
+ // 海报列表下拉框
+ const posterOptions = reactive([])
+
+ // 跳转到海报列表,添加海报
+ const toPosterEvent = () => {
+ const url = router.resolve({
+ path: '/poster/list'
+ })
+ window.open(url.href)
+ }
+
+ // 商品海报
+ const refreshGoodsPoster = (bool = false) => {
+ getPosterList({
+ type: 'shop_goods'
+ }).then((res) => {
+ const data = res.data
+ if (data) {
+ posterOptions.splice(0, posterOptions.length, ...data)
+ if (bool) {
+ ElMessage({
+ message: t('refreshSuccess'),
+ type: 'success'
+ })
+ }
+ }
+ })
+ }
+
+ refreshGoodsPoster()
+
+ // 商品详情列表下拉框
+ const detailTemplateOptions = reactive([])
+
+ // 跳转到微页面,添加商品详情模板
+ const toDetailTemplateEvent = () => {
+ const url = router.resolve({
+ path: '/diy/list'
+ })
+ window.open(url.href)
+ }
+
+ // 刷新微页面
+ const refreshDetailTemplate = (bool = false) => {
+ getGoodsInfoTemplate({
+ type: 'DIY_SHOP_GOODS_DETAIL'
+ }).then((res) => {
+ const data = res.data
+ if (data) {
+ detailTemplateOptions.splice(0, detailTemplateOptions.length, ...data)
+ if (bool) {
+ ElMessage({
+ message: t('refreshSuccess'),
+ type: 'success'
+ })
+ }
+ }
+ })
+ }
+
+ refreshDetailTemplate()
+
+
+ // 万能表单列表下拉框
+ const diyFormOptions = reactive([])
+
+ // 跳转到万能表单列表,添加表单
+ const toDiyFormEvent = () => {
+ const url = router.resolve({
+ path: '/diy_form/list'
+ })
+ window.open(url.href)
+ }
+
+ // 刷新万能表单
+ const refreshDiyForm = (bool = false) => {
+ getDiyFormList({
+ type: 'DIY_FORM_GOODS_DETAIL',
+ status: 1
+ }).then((res) => {
+ const data = res.data
+ if (data) {
+ diyFormOptions.splice(0, diyFormOptions.length, ...data)
+ if (bool) {
+ ElMessage({
+ message: t('refreshSuccess'),
+ type: 'success'
+ })
+ }
+ }
+ })
+ }
+
+ refreshDiyForm()
+
+ // 标签组列表复选框
+ const labelOptions = reactive([])
+
+ // 跳转到商品标签,添加标签
+ const toGoodsLabelEvent = () => {
+ const url = router.resolve({
+ path: '/shop/goods/label'
+ })
+ window.open(url.href)
+ }
+
+ // 商品标签
+ const refreshGoodsLabel = () => {
+ getLabelList({}).then((res) => {
+ const data = res.data
+ if (data) {
+ labelOptions.splice(0, labelOptions.length, ...data)
+ }
+ })
+ }
+
+ refreshGoodsLabel()
+
+ // 商品服务列表复选框
+ const serviceOptions = reactive([])
+
+ // 跳转到商品服务,添加服务
+ const toGoodsServiceEvent = () => {
+ const url = router.resolve({
+ path: '/shop/goods/service'
+ })
+ window.open(url.href)
+ }
+
+ // 商品服务
+ const refreshGoodsService = () => {
+ getServeList({}).then((res) => {
+ const data = res.data
+ if (data) {
+ serviceOptions.splice(0, serviceOptions.length, ...data)
+ }
+ })
+ }
+
+ refreshGoodsService()
+
+ // 供应商列表下拉框
+ const supplierOptions = reactive([])
+
+ // 跳转到供应商
+ const toSupplierEvent = () => {
+ const url = router.resolve({
+ path: '/shop_supplier/supplier'
+ })
+ window.open(url.href)
+ }
+
+ // 供应商
+ const refreshSupplier = () => {
+ getSupplierList({}).then((res) => {
+ const data = res.data
+ if (data) {
+ supplierOptions.splice(0, supplierOptions.length, ...data)
+ }
+ })
+ }
+
+ const goodsSpecFormat: any = reactive([]) // 规格项/规格值
+ const goodsSkuData: any = reactive({}) // 商品SKU规格数据
+ const specData: any = reactive([]) // 商品规格值
+
+ const activeGoodsCount: any = ref(0)
+
+ const isDisabledPrice = () => {
+ if (activeGoodsCount.value > 0) {
+ return true;
+ }
+ return false;
+ }
+
+ const handleGoodsInit = (data: any) => {
+ formData.addon_shop_supplier = data.addon_shop_supplier
+ if (formData.addon_shop_supplier && formData.addon_shop_supplier.status == 1) {
+ refreshSupplier()
+ }
+
+ if (data.default_sort) {
+ formData.sort = data.default_sort;
+ }
+
+ if (formData.goods_id && data.goods_info) {
+
+ // 商品参与营销活动的数量
+ activeGoodsCount.value = data.goods_info.active_goods_count;
+
+ // 基础信息
+ formData.goods_name = data.goods_info.goods_name
+ formData.sub_title = data.goods_info.sub_title
+ formData.goods_type = data.goods_info.goods_type
+ formData.goods_image = data.goods_info.goods_image
+ formData.goods_video = data.goods_info.goods_video
+ formData.goods_category = data.goods_info.goods_category
+ formData.brand_id = data.goods_info.brand_id
+ formData.poster_id = data.goods_info.poster_id
+ formData.form_id = data.goods_info.form_id
+ formData.diy_detail_id = data.goods_info.diy_detail_id
+ formData.label_ids = data.goods_info.label_ids
+ formData.service_ids = data.goods_info.service_ids
+ formData.supplier_id = data.goods_info.supplier_id
+ formData.status = data.goods_info.status
+ formData.sort = data.goods_info.sort
+ formData.is_gift = data.goods_info.is_gift
+
+ /*************** 商品参数-start ****************/
+ formData.attr_format = data.goods_info.attr_format
+ formData.attr_ids = data.goods_info.attr_ids
+
+ attrChange(formData.attr_ids, true)
+ /*************** 商品参数-end ****************/
+
+ // 价格库存
+ formData.spec_type = data.goods_info.spec_type
+ formData.stock = data.goods_info.stock
+
+ if (formData.spec_type == 'single') {
+ // 单规格
+ const skuInfo = data.goods_info.sku_list[0]
+ formData.price = skuInfo.price
+ formData.market_price = skuInfo.market_price
+ formData.cost_price = skuInfo.cost_price
+ formData.sku_no = skuInfo.sku_no
+
+ if (appendSingleGoodsData) Object.assign(formData, appendSingleGoodsData(skuInfo));
+ } else if (formData.spec_type == 'multi') {
+ // 多规格
+ const specList = data.goods_info.spec_list
+ specList.forEach((item: any) => {
+ const values: any = []
+ item.spec_values = item.spec_values.split(',')
+ item.spec_values.forEach((v: any) => {
+ values.push({
+ id: generateRandom(),
+ spec_value_name: v
+ })
+ })
+ goodsSpecFormat.push({
+ id: generateRandom(),
+ spec_id: item.spec_id,
+ goods_id: item.goods_id,
+ spec_name: item.spec_name,
+ values
+ })
+ })
+
+ refreshGoodsSkuData();
+
+ const skuList = data.goods_info.sku_list
+
+ for (let key in goodsSkuData) {
+ for (let i = 0; i < skuList.length; i++) {
+ let item = skuList[i];
+ if (goodsSkuData[key].spec_name == item.sku_spec_format.replace(/,/g, ' ')) {
+ goodsSkuData[key].sku_id = item.sku_id;
+ goodsSkuData[key].sku_image = item.sku_image;
+ goodsSkuData[key].price = item.price;
+ goodsSkuData[key].market_price = item.market_price;
+ goodsSkuData[key].cost_price = item.cost_price;
+
+ for (let field in appendRefreshGoodsSkuData) {
+ goodsSkuData[key][field] = item[field];
+ }
+
+ goodsSkuData[key].stock = item.stock;
+ goodsSkuData[key].sku_id = item.sku_id;
+ goodsSkuData[key].sku_no = item.sku_no;
+ goodsSkuData[key].is_default = item.is_default;
+ break;
+ }
+ }
+ }
+
+ nextTick(() => {
+ refreshSkuTable()
+ bindSpecValue()
+ })
+ }
+
+ formData.member_discount = data.goods_info.member_discount
+
+ formData.unit = data.goods_info.unit
+ formData.virtual_sale_num = data.goods_info.virtual_sale_num
+ formData.is_limit = data.goods_info.is_limit
+ formData.limit_type = data.goods_info.limit_type
+ formData.max_buy = data.goods_info.max_buy
+ formData.min_buy = data.goods_info.min_buy
+
+ // 商品详情
+ formData.goods_desc = data.goods_info.goods_desc
+ }
+ }
+
+ // 绑定拖拽规格值事件
+ const bindSpecValue = () => {
+ // 商品正在参与营销活动,禁止操作
+ if (isDisabledPrice()) {
+ return
+ }
+ if (!getFormRef().specValueRef) return
+
+ for (let i = 0; i < getFormRef().specValueRef.length; i++) {
+ const item = getFormRef().specValueRef[i]
+ const sortable = Sortable.create(item, {
+ group: 'draggable-element-' + i,
+ animation: 200,
+ // 结束拖拽
+ onEnd: event => {
+ const temp = goodsSpecFormat[i].values[event.oldIndex!]
+ goodsSpecFormat[i].values.splice(event.oldIndex!, 1)
+ goodsSpecFormat[i].values.splice(event.newIndex!, 0, temp)
+
+ nextTick(() => {
+ sortable.sort(
+ range(goodsSpecFormat[i].values.length).map(value => {
+ return value.toString()
+ })
+ )
+
+ // 渲染商品规格数据、表格
+ refreshGoodsSkuData()
+ refreshSkuTable()
+ })
+ }
+ })
+ }
+ }
+
+ // 生成随机数
+ const generateRandom = (len: number = 5) => {
+ return Number(Math.random().toString().substr(3, len) + Date.now()).toString(36)
+ }
+
+ // 添加规格项
+ const addSpec = () => {
+ // 商品正在参与营销活动,禁止操作
+ if (isDisabledPrice()) {
+ ElMessage({
+ type: 'warning',
+ message: `${ t('participateInActiveDisableTips') }`
+ })
+ return
+ }
+ if (goodsSpecFormat.length > 4) {
+ ElMessage({
+ type: 'warning',
+ message: `${ t('maxAddSpecTips') }`
+ })
+ return
+ }
+ goodsSpecFormat.push({
+ id: generateRandom(),
+ spec_name: '',
+ values: [
+ {
+ id: generateRandom(),
+ spec_value_name: ''
+ }
+ ]
+ })
+ }
+
+ // 删除规格项
+ const deleteSpec = (index: number) => {
+ // 商品正在参与营销活动,禁止操作
+ if (isDisabledPrice()) {
+ ElMessage({
+ type: 'warning',
+ message: `${ t('participateInActiveDisableTips') }`
+ })
+ return
+ }
+ goodsSpecFormat.splice(index, 1)
+ // 渲染商品规格数据、表格、统计库存变化
+ refreshGoodsSkuData()
+ refreshSkuTable()
+ specStockSum()
+ }
+
+ // 添加规格值
+ const addSpecValue = (index: number) => {
+ // 商品正在参与营销活动,禁止操作
+ if (isDisabledPrice()) {
+ ElMessage({
+ type: 'warning',
+ message: `${ t('participateInActiveDisableTips') }`
+ })
+ return
+ }
+ goodsSpecFormat[index].values.push({
+ id: generateRandom(),
+ spec_value_name: ''
+ })
+ bindSpecValue()
+ }
+
+ // 监听规格值变化
+ const specValueNameInputListener = debounce((value) => {
+ // 渲染商品规格数据、表格
+ refreshGoodsSkuData()
+ refreshSkuTable()
+
+ })
+
+ // 删除规格值
+ const deleteSpecValue = (index: number, specIndex: number) => {
+ // 商品正在参与营销活动,禁止操作
+ if (isDisabledPrice()) {
+ ElMessage({
+ type: 'warning',
+ message: `${ t('participateInActiveDisableTips') }`
+ })
+ return
+ }
+ goodsSpecFormat[index].values.splice(specIndex, 1)
+ // 渲染商品规格数据、表格、统计库存变化
+ refreshGoodsSkuData()
+ refreshSkuTable()
+ specStockSum()
+ }
+
+ // 设置默认规格
+ const specValueIsDefaultChangeListener = (value: any, key: any) => {
+ for (const k in goodsSkuData) {
+ if (k == key) {
+ goodsSkuData[k].is_default = value
+ } else {
+ goodsSkuData[k].is_default = 0
+ }
+ }
+ }
+
+ // 监听规格库存变化,统计总库存
+ const specStockSum = debounce(() => {
+ let stock = 0
+ for (const k in goodsSkuData) {
+ if (goodsSkuData[k].stock) stock += parseInt(goodsSkuData[k].stock)
+ }
+ formData.stock = stock
+ })
+
+ // 刷新商品规格数据
+ const refreshGoodsSkuData = () => {
+ const arr = goodsSpecFormat
+ const tempGoodsSkuData = cloneDeep(goodsSkuData)// 记录原始数据,后续用作对比
+ let skuData: any = {}
+ let tempIndex = 0;
+ for (const spec of arr) {
+ let item_prop_arr: any = {}
+ if (Object.keys(skuData).length > 0) {
+ for (const ele_2 in skuData) {
+ for (let ele_3 of spec.values) {
+ let sku_spec = cloneDeep(skuData[ele_2].sku_spec)// 防止对象引用
+ sku_spec.push(ele_3)
+ item_prop_arr['sku_' + tempIndex] = {
+ spec_name: `${ skuData[ele_2].spec_name } ${ ele_3.spec_value_name }`,
+ sku_spec,
+ sku_image: '',
+ price: '',
+ market_price: '',
+ cost_price: '',
+ stock: '',
+ sku_no: '',
+ is_default: 0
+ }
+
+ for (let key in appendRefreshGoodsSkuData) {
+ item_prop_arr['sku_' + tempIndex][key] = appendRefreshGoodsSkuData[key].value;
+ }
+ tempIndex++;
+ }
+ }
+ } else {
+ for (let ele_1 of spec.values) {
+ let spec_name = ele_1.spec_value_name
+ item_prop_arr['sku_' + tempIndex] = {
+ spec_name: spec_name,
+ sku_spec: [ele_1],
+ sku_image: '',
+ price: '',
+ market_price: '',
+ cost_price: '',
+ stock: '',
+ sku_no: '',
+ is_default: 0
+ }
+ for (let key in appendRefreshGoodsSkuData) {
+ item_prop_arr['sku_' + tempIndex][key] = appendRefreshGoodsSkuData[key].value;
+ }
+ tempIndex++;
+ }
+ }
+
+ skuData = Object.keys(item_prop_arr).length > 0 ? item_prop_arr : skuData
+ }
+
+ // 比对已存在的规格项/值,并且赋值
+ for (const tempKey in tempGoodsSkuData) {
+ for (const key in skuData) {
+ const count = matchSkuSpecCount(tempGoodsSkuData[tempKey].sku_spec, skuData[key].sku_spec)
+ if (count === skuData[key].sku_spec.length) {
+ // 匹配成功后,要同步最新的规格项名称、规格值集合
+ const specName = skuData[key].spec_name
+ const skuSpec = skuData[key].sku_spec
+ Object.assign(skuData[key], tempGoodsSkuData[tempKey])
+ skuData[key].spec_name = specName
+ skuData[key].sku_spec = skuSpec
+ break
+ }
+ }
+ }
+
+ for (const item in goodsSkuData) {
+ delete goodsSkuData[item]
+ }
+
+ let firstSpec = ''
+
+ for (const key in skuData) {
+ if (firstSpec == '') {
+ firstSpec = key
+ skuData[key].is_default = 1
+ } else {
+ skuData[key].is_default = 0
+ }
+ goodsSkuData[key] = skuData[key]
+ }
+ formData.skuCheckAll = false;// 是否全选
+ formData.skuIsIndeterminate = false// 是否部分选中
+ formData.skuCheckedCities = []// 选中的规格
+ }
+
+ // 匹配规格值
+ const matchSkuSpecCount = (oVal: any, nVal: any) => {
+ let count = 0// 匹配次数,与规格值相等时为匹配成功
+ for (let i = 0; i < oVal.length; i++) {
+ for (let j = 0; j < nVal.length; j++) {
+ if (oVal[i].id === nVal[j].id) {
+ count++
+ break
+ }
+ }
+ }
+ return count
+ }
+
+ // 刷新商品规格表格
+ const refreshSkuTable = () => {
+ let length = 0
+ // 统计有效规格数量
+ for (let i = 0; i < goodsSpecFormat.length; i++) {
+ if (goodsSpecFormat[i].spec_name != '' && goodsSpecFormat[i].values.length > 0) {
+ length++
+ }
+ }
+
+ let row = 1 // 跨行
+ const tempSpecData = []
+
+ // 规格值单元格合并
+ for (let i = length - 1; i >= 0; i--) {
+ for (let k = 0; k < Object.keys(goodsSkuData).length;) {
+ if (goodsSpecFormat[i].values.length > 0) {
+ for (let ele of goodsSpecFormat[i].values) {
+ tempSpecData.push({
+ index: k,
+ colSpan: i,
+ rowSpan: row,
+ spec_value_name: ele.spec_value_name
+ })
+ k = k + row
+ }
+ } else {
+ k++
+ }
+ }
+ row = row * goodsSpecFormat[i].values.length
+ }
+
+ tempSpecData.reverse()
+ specData.splice(0, specData.length, ...tempSpecData)
+ }
+
+ const batchOperation: any = reactive({
+ spec: '', // 所选规格id,空为全部
+ price: '', // 销售价
+ market_price: '', // 划线价
+ cost_price: '', // 成本价
+ stock: '', // 库存
+ sku_no: '' // 商品编码
+ })
+
+ const appendBatchOperation: any = {};
+ for (let key in appendRefreshGoodsSkuData) {
+ appendBatchOperation[key] = appendRefreshGoodsSkuData[key].value;
+ }
+
+ Object.assign(batchOperation, appendBatchOperation);
+
+ const skuHandleCheckAllChange = (value: any) => {
+ formData.skuIsIndeterminate = false
+ if (value) {
+ formData.skuCheckedCities = Object.keys(goodsSkuData)
+ } else {
+ formData.skuCheckedCities = []
+ }
+ }
+ const handleCheckedCitiesChange = (value: any) => {
+ const checkedCount = value.length
+ formData.skuCheckAll = checkedCount === Object.keys(goodsSkuData).length
+ formData.skuIsIndeterminate = checkedCount > 0 && checkedCount < Object.keys(goodsSkuData).length
+ }
+ // 批量设置确认
+ const saveBatch = () => {
+ if (formData.skuCheckedCities.length == 0) {
+ ElMessage({
+ type: 'warning',
+ message: `${ t('pleaseSelectSku') }`
+ })
+ return
+ }
+ // 验证输入内容
+ if (batchOperation.price && (isNaN(batchOperation.price) || !regExp.digit.test(batchOperation.price))) {
+ ElMessage({
+ type: 'warning',
+ message: `${ t('priceTips') }`
+ })
+ return
+ }
+ if (batchOperation.market_price && (isNaN(batchOperation.market_price) || !regExp.digit.test(batchOperation.market_price))) {
+ ElMessage({
+ type: 'warning',
+ message: `${ t('marketPriceTips') }`
+ })
+ return
+ }
+ if (batchOperation.cost_price && (isNaN(batchOperation.cost_price) || !regExp.digit.test(batchOperation.cost_price))) {
+ ElMessage({
+ type: 'warning',
+ message: `${ t('costPriceTips') }`
+ })
+ return
+ }
+ if (batchOperation.stock && (isNaN(batchOperation.stock) || !regExp.number.test(batchOperation.stock))) {
+ ElMessage({
+ type: 'warning',
+ message: `${ t('stockTips') }`
+ })
+ return
+ }
+
+ for (let field in appendRefreshGoodsSkuData) {
+ let reg = regExp[appendRefreshGoodsSkuData[field].regExp]
+ let message = appendRefreshGoodsSkuData[field].message
+
+ if (batchOperation[field] && (isNaN(batchOperation[field]) || !reg.test(batchOperation[field]))) {
+ ElMessage({
+ type: 'warning',
+ message: message
+ })
+ return
+ }
+ }
+
+ // 设置全部规格
+ formData.skuCheckedCities.forEach((key: any) => {
+ if (batchOperation.price) goodsSkuData[key].price = batchOperation.price
+ if (batchOperation.market_price) goodsSkuData[key].market_price = batchOperation.market_price
+ if (batchOperation.cost_price) goodsSkuData[key].cost_price = batchOperation.cost_price
+ if (batchOperation.stock) goodsSkuData[key].stock = batchOperation.stock
+
+ for (let field in appendRefreshGoodsSkuData) {
+ if (batchOperation[field]) goodsSkuData[key][field] = batchOperation[field]
+ }
+
+ if (batchOperation.sku_no) goodsSkuData[key].sku_no = batchOperation.sku_no
+ })
+
+ // 保存完清空
+ batchOperation.price = ''
+ batchOperation.market_price = ''
+ batchOperation.cost_price = ''
+ batchOperation.stock = ''
+ batchOperation.sku_no = ''
+
+ for (let field in appendRefreshGoodsSkuData) {
+ batchOperation[field] = '';
+ }
+ }
+
+ // 正则表达式
+ const regExp: any = {
+ required: /[\S]+/,
+ number: /^\d{0,10}$/,
+ digit: /^\d{0,10}(.?\d{0,2})$/,
+ special: /^\d{0,10}(.?\d{0,3})$/
+ }
+
+ // 表单验证规则
+ const formRules = computed(() => {
+ let rules = {
+ goods_name: [
+ {
+ required: true,
+ trigger: 'blur',
+ validator: (rule: any, value: any, callback: any) => {
+ if (value === '') {
+ callback(new Error(t('goodsNamePlaceholder')))
+ }
+ if (value.length > 60) {
+ callback(new Error(t('goodsNameMaxLengthTips')))
+ } else {
+ callback()
+ }
+ }
+ }
+ ],
+ sub_title: [
+ {
+ trigger: 'blur',
+ validator: (rule: any, value: any, callback: any) => {
+ if (value.length > 100) {
+ callback(new Error(t('subTitleMaxLengthTips')))
+ } else {
+ callback()
+ }
+ }
+ }
+ ],
+ goods_image: [
+ { required: true, message: t('goodsImagePlaceholder'), trigger: 'blur' }
+ ],
+ goods_category: [
+ { required: true, message: t('goodsCategoryPlaceholder'), trigger: 'blur' }
+ ],
+ sort: [
+ {
+ trigger: 'blur',
+ validator: (rule: any, value: any, callback: any) => {
+ if (isNaN(value) || !regExp.number.test(value)) {
+ callback(new Error(t('sortTips')))
+ } else {
+ callback()
+ }
+ }
+ }
+ ],
+ // unit: [
+ // {required: true, message: t('unitPlaceholder'), trigger: 'blur'}
+ // ],
+ // 单规格
+ price: [
+ {
+ trigger: 'blur',
+ validator: (rule: any, value: any, callback: any) => {
+ if (formData.spec_type == 'single') {
+ if (value === '') {
+ callback(new Error(t('pricePlaceholder')))
+ } else if (isNaN(value) || !regExp.digit.test(value)) {
+ callback(new Error(t('priceTips')))
+ } else if (value < 0) {
+ callback(new Error(t('priceNotZeroTips')))
+ } else {
+ callback()
+ }
+ } else {
+ callback()
+ }
+ }
+ }
+ ],
+ market_price: [
+ {
+ trigger: 'blur',
+ validator: (rule: any, value: any, callback: any) => {
+ if (formData.spec_type == 'single') {
+ if (isNaN(value) || !regExp.digit.test(value)) {
+ callback(new Error(t('marketPriceTips')))
+ } else if (value < 0) {
+ callback(new Error(t('marketPriceNotZeroTips')))
+ } else {
+ callback()
+ }
+ } else {
+ callback()
+ }
+ }
+ }
+ ],
+ cost_price: [
+ {
+ trigger: 'blur',
+ validator: (rule: any, value: any, callback: any) => {
+ if (formData.spec_type == 'single') {
+ if (isNaN(value) || !regExp.digit.test(value)) {
+ callback(new Error(t('costPriceTips')))
+ } else if (value < 0) {
+ callback(new Error(t('costPriceNotZeroTips')))
+ } else {
+ callback()
+ }
+ } else {
+ callback()
+ }
+ }
+ }
+ ],
+ stock: [
+ {
+ trigger: 'blur',
+ validator: (rule: any, value: any, callback: any) => {
+ if (formData.spec_type == 'single') {
+ if (value === '') {
+ callback(new Error(t('stockPlaceholder')))
+ } else if (isNaN(value) || !regExp.number.test(value)) {
+ callback(new Error(t('stockTips')))
+ } else if (value < 0) {
+ callback(new Error(t('stockNotZeroTips')))
+ } else {
+ callback()
+ }
+ } else {
+ callback()
+ }
+ }
+ }
+ ],
+ virtual_sale_num: [
+ {
+ trigger: 'blur',
+ validator: (rule: any, value: any, callback: any) => {
+ if (formData.spec_type == 'single') {
+ if (isNaN(value) || !regExp.number.test(value)) {
+ callback(new Error(t('virtualSaleNumTips')))
+ } else if (value < 0) {
+ callback(new Error(t('virtualSaleNumNotZeroTips')))
+ } else {
+ callback()
+ }
+ } else {
+ callback()
+ }
+ }
+ }
+ ],
+ // 多规格
+ spec_type: [
+ {
+ trigger: 'blur',
+ validator: (rule: any, value: any, callback: any) => {
+ if (formData.spec_type == 'multi') {
+ if (Object.keys(goodsSkuData).length == 0) {
+ callback(new Error(t('pleaseEditSpecPlaceholder')))
+ }
+ }
+ callback()
+ }
+ }
+ ],
+ max_buy: [
+ {
+ trigger: 'blur',
+ validator: (rule: any, value: any, callback: any) => {
+ if (value === '') {
+ callback(new Error(t('maxBuyPlaceholder')))
+ } else if (isNaN(value) || !regExp.number.test(value)) {
+ callback(new Error(t('maxBuyTips')))
+ } else if (value < 1) {
+ callback(new Error(t('maxBuyNotZeroTips')))
+ } else {
+ callback()
+ }
+ }
+ }
+ ],
+ min_buy: [
+ {
+ trigger: 'blur',
+ validator: (rule: any, value: any, callback: any) => {
+ if (isNaN(value) || !regExp.number.test(value)) {
+ callback(new Error(t('minBuyFormatErrorTips')))
+ } else if (value < 0) {
+ callback(new Error(t('minBuyNotZeroTips')))
+ } else if (formData.is_limit == 1 && value > Number(formData.max_buy)) {
+ callback(new Error(t('minBuyGreaterThanMaxBuyTips')))
+ } else {
+ callback()
+ }
+ }
+ }
+ ],
+ goods_desc: [
+ {
+ required: true,
+ trigger: ['blur', 'change'],
+ validator: (rule: any, value: any, callback: any) => {
+ if (value === '') {
+ callback(new Error(t('goodsDescPlaceholder')))
+ } else if (value.length < 5 || value.length > 50000) {
+ callback(new Error(t('goodsDescMaxTips')))
+ return false
+ } else {
+ callback()
+ }
+ }
+ }
+ ]
+ };
+
+ if (getFormRules) {
+ Object.assign(rules, getFormRules(formData, regExp));
+ }
+
+ return rules;
+ })
+
+ // 多规格,销售价 验证规则
+ const skuPriceRules = () => {
+ return [{
+ trigger: 'blur',
+ validator: (rule: any, value: any, callback: any) => {
+ if (formData.spec_type == 'multi') {
+ if (value.length == 0) {
+ callback(t('pricePlaceholder'))
+ } else if (isNaN(value) || !regExp.digit.test(value)) {
+ callback(t('priceTips'))
+ } else if (value < 0) {
+ callback(t('priceNotZeroTips'))
+ } else {
+ callback();
+ }
+ } else {
+ callback();
+ }
+
+ }
+ }]
+ };
+
+ // 多规格,划线价 验证规则
+ const skuMarketPriceRules = () => {
+ return [{
+ trigger: 'blur',
+ validator: (rule: any, value: any, callback: any) => {
+ if (formData.spec_type == 'multi') {
+ if (isNaN(value) || !regExp.digit.test(value)) {
+ callback(t('marketPriceTips'))
+ } else if (value < 0) {
+ callback(t('marketPriceNotZeroTips'))
+ } else {
+ callback();
+ }
+ } else {
+ callback();
+ }
+ }
+ }]
+ }
+
+ // 多规格,成本价 验证规则
+ const skuCostPriceRules = () => {
+ return [{
+ trigger: 'blur',
+ validator: (rule: any, value: any, callback: any) => {
+ if (formData.spec_type == 'multi') {
+ if (isNaN(value) || !regExp.digit.test(value)) {
+ callback(t('costPriceTips'))
+ } else if (value < 0) {
+ callback(t('costPriceNotZeroTips'))
+ } else {
+ callback();
+ }
+ } else {
+ callback();
+ }
+ }
+ }]
+ }
+
+ // 多规格,库存 验证规则
+ const skuStockRules = () => {
+ return [{
+ trigger: 'blur',
+ validator: (rule: any, value: any, callback: any) => {
+ if (formData.spec_type == 'multi') {
+ if (value.length == 0) {
+ callback(t('stockPlaceholder'))
+ } else if (isNaN(value) || !regExp.number.test(value)) {
+ callback(t('stockTips'))
+ } else if (value < 0) {
+ callback(t('stockNotZeroTips'))
+ } else {
+ callback();
+ }
+
+ } else {
+ callback();
+ }
+
+ }
+ }]
+ }
+
+ const verify = (callback: any) => {
+ let formRef = [
+ {
+ key: 'basic',
+ verify: false,
+ ref: formRefArr.basicFormRef
+ },
+ {
+ key: 'price_stock',
+ verify: false,
+ ref: formRefArr.priceStockFormRef
+ },
+ {
+ key: 'price_stock',
+ verify: false,
+ ref: formRefArr.skuFormRef
+ },
+ {
+ key: 'price_stock',
+ verify: false,
+ ref: formRefArr.priceStockCommonFormRef
+ }
+ ];
+ formRef = formRef.concat(verifyArr);
+
+ // 调整验证顺序 -- 详情验证
+ let obj = {
+ key: 'detail',
+ verify: false,
+ ref: formRefArr.detailFormRef
+ };
+ formRef.push(obj)
+
+ formRef.forEach((el: any, index) => {
+ el.ref.validate((valid: any) => {
+ el.verify = valid
+ })
+ })
+
+ if (formData.spec_type == 'multi') {
+ let specVerify = true
+ let repeatSpecNameArr: any = [];
+ let repeatSpecValueNameArr: any = [];
+ for (let i = 0; i < goodsSpecFormat.length; i++) {
+ const spec = goodsSpecFormat[i]
+ if (Test.require(spec.spec_name)) {
+ specVerify = false
+ ElMessage({ type: 'warning', message: `${ t('specNameRequire') }` })
+ break
+ }
+ if (repeatSpecNameArr.indexOf(spec.spec_name) > -1) {
+ specVerify = false
+ ElMessage({ type: 'warning', message: `${ t('specNameRepeat') }` })
+ break
+ } else {
+ repeatSpecNameArr.push(spec.spec_name);
+ }
+
+ if (spec.values.length) {
+ for (let v = 0; v < spec.values.length; v++) {
+ const value = spec.values[v]
+ if (Test.require(value.spec_value_name)) {
+ specVerify = false
+ ElMessage({ type: 'warning', message: `${ t('specValueRequire') }` })
+ break
+ }
+
+ if (repeatSpecValueNameArr.indexOf(value.spec_value_name) > -1) {
+ specVerify = false
+ ElMessage({ type: 'warning', message: `${ t('specValueNameRepeat') }` })
+ break
+ } else {
+ repeatSpecValueNameArr.push(value.spec_value_name);
+ }
+ }
+ } else {
+ specVerify = false
+ ElMessage({ type: 'warning', message: `${ t('specValueRequire') }` })
+ }
+
+ if (!specVerify) break
+ }
+
+ if (!specVerify) {
+ activeName.value = 'price_stock'
+ return
+ }
+
+ let isHasDefaultSpec = false; // 是否存在默认规格
+ for (const k in goodsSkuData) {
+ if (goodsSkuData[k].is_default) {
+ isHasDefaultSpec = true;
+ }
+ }
+
+ if (!isHasDefaultSpec) {
+ activeName.value = 'price_stock'
+ ElMessage({ type: 'warning', message: `${ t('lackDefaultSpec') }` })
+ return
+ }
+ }
+
+ setTimeout(() => {
+ let verify = true
+ // 检测验证,并且定位tab页面
+ for (let i = 0; i < formRef.length; i++) {
+ if (formRef[i].verify == false) {
+ activeName.value = formRef[i].key
+ verify = false
+ break
+ }
+ }
+ if (verify && callback) callback()
+ }, 10)
+ }
+
+ // 保存数据
+ const save = (callback: any = null) => {
+ verify(() => {
+
+ if (repeat.value) return
+ repeat.value = true
+
+ const api = formData.goods_id ? editApi : addApi
+ const data = cloneDeep(formData)
+
+ if (data.spec_type == 'multi') {
+ data.stock = 0
+ for (const k in goodsSkuData) {
+ if (goodsSkuData[k].stock) data.stock += parseInt(goodsSkuData[k].stock)
+ }
+ }
+
+ const goodsCategory: any = []
+ data.goods_category.forEach((item: any) => {
+ if (typeof item == 'object') {
+ item.forEach((second: any) => {
+ if (goodsCategory.indexOf(second) == -1) {
+ goodsCategory.push(second)
+ }
+ })
+ } else {
+ if (goodsCategory.indexOf(item) == -1) {
+ goodsCategory.push(item)
+ }
+ }
+ })
+
+ data.goods_category = goodsCategory
+ data.goods_sku_data = goodsSkuData
+ data.goods_spec_format = goodsSpecFormat
+
+ /***** 商品参数-start ****/
+ data.attr_format = [];
+ let attrFormat: any = deepClone(attrTableData);
+ attrFormat.forEach((item: any, index: any) => {
+ if (item.attr_value_name && item.select_child_val || item.attr_value_id > 0) {
+ let obj: any = {};
+ obj.attr_id = item.attr_id
+ obj.attr_value_id = item.attr_value_id
+ obj.attr_value_name = item.attr_value_name
+ obj.type = item.type
+ obj.sort = item.sort ? item.sort : 0
+ obj.attr_child_value_id = item.select_child_name
+ obj.attr_child_value_name = item.select_child_val
+ data.attr_format.push(obj);
+ }
+ });
+ data.attr_format.sort((a: any, b: any) => {
+ return b.sort - a.sort
+ });
+ /***** 商品参数-end ****/
+
+ if (callback) {
+ Object.assign(data, callback(data));
+ }
+
+ api(data).then((res: any) => {
+ repeat.value = false
+ router.push('/shop/goods/list')
+ }).catch(() => {
+ repeat.value = false
+ })
+ })
+ }
+
+ const back = () => {
+ router.push('/shop/goods/list')
+ }
+
+ const filterSpecial = (event: any) => {
+ event.target.value = event.target.value.replace(/[^\u4e00-\u9fa5a-zA-Z0-9\s]/g, '')
+ event.target.value = event.target.value.replace(/[`~!@#$%^&*()_\-+=<>?:"{}|,.\/;'\\[\]·~!@#¥%……&*()——\-+={}|《》?:“”【】、;‘’,。、]/g, '')
+ }
+
+ const handleBlur = (e: any) => {
+ formRefArr.detailFormRef?.validateField('goods_desc')
+ }
+
+ const goodsVerifyFn = (data: any) => {
+ if (!data.target.value) return false
+ const obj = {
+ goods_id: formData.goods_id,
+ sku_no: data.target.value
+ }
+ goodsVerify(obj).then((res) => {
+
+ })
+ }
+
+ /******************** 商品参数-start ***************************/
+ const attrOptions = reactive([])
+ const getAttrListFn = () => {
+ getAttrList({}).then((res) => {
+ attrOptions.splice(0, attrOptions.length, ...res.data)
+ })
+ }
+
+ getAttrListFn();
+
+ const attrTableData: any = reactive([])
+
+ const attrChange = (attr_id_arr: any = [], isEdit: any = false) => {
+ if (attr_id_arr.length == 0) {
+ // 清空已选的商品参数模板
+ let temporaryAttrData: any = deepClone(attrTableData);
+ temporaryAttrData = temporaryAttrData.filter((item: any) => item.attr_value_id < 0);
+ attrTableData.splice(0, attrTableData.length, ...temporaryAttrData);
+ }
+
+ // 编辑初始化赋值
+ const editInit = () => {
+ if (isEdit) {
+ attrTableData.forEach((item: any) => {
+ for (let i = 0; i < formData.attr_format.length; i++) {
+ if (formData.attr_format[i].attr_value_id == item.attr_value_id) {
+ item.select_child_name = formData.attr_format[i].attr_child_value_id
+ item.select_child_val = formData.attr_format[i].attr_child_value_name
+ item.sort = formData.attr_format[i].sort
+ break
+ }
+ }
+ })
+
+ for (let i = 0; i < formData.attr_format.length; i++) {
+ if (formData.attr_format[i].attr_value_id < 0) {
+ let item = formData.attr_format[i]
+ let obj: any = {
+ attr_id: item.attr_id,
+ attr_value_id: item.attr_value_id,
+ attr_value_name: item.attr_value_name,
+ sort: item.sort ? item.sort : 0,
+ type: "text",
+ select_child_name: item.attr_child_value_id,
+ select_child_val: item.attr_child_value_name
+ };
+ attrTableData.push(obj);
+ }
+ }
+
+ }
+ }
+
+ if (attr_id_arr.length) {
+ getAttrList({
+ attr_id_arr
+ }).then((res) => {
+ let data = res.data;
+ if (data && Object.keys(data).length) {
+ let temporaryData: any = deepClone(attrTableData);
+ temporaryData = temporaryData.filter((item: any) => {
+ if (item.attr_value_id > 0) {
+ return attr_id_arr.indexOf(item.attr_id) != -1
+ } else {
+ return true; // 保留自定义添加的商品参数模板
+ }
+ });
+
+ let formAttrIdArray = temporaryData.map((obj: any) => obj.attr_value_id);
+
+ data.forEach((item: any) => {
+ if (item.attr_value_format) {
+ let attr_value_format = JSON.parse(item.attr_value_format)
+
+ // 过滤已添加的商品参数模板
+ if (formAttrIdArray.length) {
+ formAttrIdArray.forEach((id: any) => {
+ attr_value_format = attr_value_format.filter((child: any) => child.attr_value_id != id)
+ })
+ }
+
+ // 初始化
+ attr_value_format.filter((child: any) => {
+ child.attr_id = item.attr_id
+ child.select_child_name = child.type == "checkbox" ? [] : ''
+ child.select_child_val = child.type == "checkbox" ? [] : ''
+ });
+
+ attr_value_format.sort((a: any, b: any) => {
+ return b.sort - a.sort
+ });
+
+ temporaryData = temporaryData.concat(attr_value_format);
+ attrTableData.splice(0, attrTableData.length, ...temporaryData);
+ }
+ })
+ editInit();
+ }
+ })
+ } else {
+ editInit();
+ }
+ }
+
+ // 添加商品参数
+ const addAttr = () => {
+ let obj: any = {
+ attr_id: '',
+ attr_value_id: "",
+ attr_value_name: "",
+ child: {
+ id: 1,
+ name: ''
+ },
+ sort: 0,
+ type: "text",
+ select_child_name: '',
+ select_child_val: ''
+ };
+ obj.attr_value_id = -Math.floor((new Date().getSeconds()) + Math.floor(new Date().getMilliseconds()));
+ obj.sort = attrTableData.length + 1;
+ attrTableData.push(obj);
+ }
+
+ // 删除商品参数
+ const delAttr = (index: any) => {
+ attrTableData.splice(index, 1);
+ }
+
+ // 商品参数单选监听
+ const attrRadioChange = (index: any, data: any) => {
+ attrTableData.forEach((item: any, index: any, array: any) => {
+ if (item.type == 'radio') {
+ item.child.forEach((childItem: any, childIndex: any) => {
+ if (childItem.id == data) {
+ array[index].select_child_name = childItem.id;
+ array[index].select_child_val = childItem.name;
+ }
+ });
+ }
+ return item;
+ });
+ }
+
+ // 商品参数多选监听
+ const attrCheckboxChange = (index: any, data: any) => {
+ attrTableData[index].select_child_val = []
+ attrTableData[index].child.forEach((childItem: any, childIndex: any) => {
+ if (data.indexOf(childItem.id) > -1) {
+ attrTableData[index].select_child_val.push(childItem.name);
+ }
+ });
+ }
+
+ return {
+ formData,
+
+ activeName,
+ tabHandleClick,
+
+ goodsType,
+ changeGoodsType,
+
+ goodsCategoryOptions,
+ goodsCategoryProps,
+ categoryHandleChange,
+ toGoodsCategoryEvent,
+ refreshGoodsCategory,
+
+ brandOptions,
+ toGoodsBrandEvent,
+ refreshGoodsBrand,
+
+ posterOptions,
+ toPosterEvent,
+ refreshGoodsPoster,
+
+ detailTemplateOptions,
+ toDetailTemplateEvent,
+ refreshDetailTemplate,
+
+ diyFormOptions,
+ toDiyFormEvent,
+ refreshDiyForm,
+
+ labelOptions,
+ toGoodsLabelEvent,
+ refreshGoodsLabel,
+
+ serviceOptions,
+ toGoodsServiceEvent,
+ refreshGoodsService,
+
+ supplierOptions,
+ toSupplierEvent,
+ refreshSupplier,
+
+ goodsSpecFormat,
+ goodsSkuData,
+ specData,
+
+ generateRandom,
+
+ isDisabledPrice,
+ addSpec,
+ deleteSpec,
+ addSpecValue,
+ specValueNameInputListener,
+ deleteSpecValue,
+ specValueIsDefaultChangeListener,
+ specStockSum,
+
+ batchOperation,
+ skuHandleCheckAllChange,
+ handleCheckedCitiesChange,
+ saveBatch,
+
+ regExp,
+
+ formRules,
+ skuPriceRules,
+ skuMarketPriceRules,
+ skuCostPriceRules,
+ skuStockRules,
+
+ handleGoodsInit,
+ save,
+ back,
+ filterSpecial,
+ handleBlur,
+
+ attrOptions,
+ attrChange,
+ getAttrListFn,
+ attrTableData,
+ addAttr,
+ delAttr,
+ attrRadioChange,
+ attrCheckboxChange,
+ goodsVerifyFn
+ }
+}
diff --git a/niucloud/addon/shop/admin/views/goods/real_edit.vue b/niucloud/addon/shop/admin/views/goods/real_edit.vue
new file mode 100644
index 000000000..5b408dab1
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/goods/real_edit.vue
@@ -0,0 +1,920 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{{ item.name }}
+
({{ item.desc }})
+
+
+ ✓
+
+
+
+
+
+
+
{{ item.name }}
+
({{ item.desc }})
+
+
+ ✓
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{{ t('goodsVideoTipTile') }}
+
{{ t('goodsVideoTipOne') }}
+
{{ t('goodsVideoTipTwo') }}
+
{{ t('goodsVideoTipThree') }}
+
{{ t('goodsVideoTipFour') }}
+
{{ t('goodsVideoTipFive') }}
+
+
+
+
+
+
+ {{ t('refresh') }}
+ {{ t('addGoodsCategory') }}
+
+
+
+
+
+
+
+
+ {{ t('refresh') }}
+ {{ t('addGoodsBrand') }}
+
+
+
+
+
+ {{ item.label_name }}
+
+
+ {{ t('refresh') }}
+ {{ t('addGoodsLabel') }}
+
+
+
+
+ {{ item.service_name }}
+
+
+ {{ t('refresh') }}
+ {{ t('addGoodsService') }}
+
+
+
+
+
+
+
+
+ {{ t('refresh') }}
+ {{ t('addSupplier') }}
+
+
+
+
+ {{ t('statusOn') }}
+ {{ t('statusOff') }}
+
+
+
+
+
+ {{ t('yes') }}
+ {{ t('no') }}
+
+
{{ t('giftTips') }}
+
+
+
+
+
+
+
+
+ {{ goodsEdit.formData.unit ? goodsEdit.formData.unit : '件' }}
+
+
{{ t('virtualSaleNumDesc') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('singleSpec') }}
+ {{ t('multiSpec') }}
+
+
{{ t('participateInActiveDisableTips') }}
+
+
+
+
+
+
+ {{ t('yuan') }}
+
+
+
+
+
+ {{ t('yuan') }}
+
+
+
+
+
+ {{ t('yuan') }}
+
+
+
+
+ kg
+
+
+
+
+ m³
+
+
+
+
+
+ {{ goodsEdit.formData.unit ? goodsEdit.formData.unit : t('defaultUnit') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('nonparticipation') }}
+ {{ t('discount') }}
+ {{ t('fixedPrice') }}
+
+
{{t('discountHint')}}
+
{{t('fixedPriceHint')}}
+
+
+
+
+
+
+
+
+
{{ t('isLimitTips') }}
+
+
+
+
+
+ {{ t('singleTime') }}
+ {{ t('singlePerson') }}
+
+
{{ t('limitTypeTips') }}
+
+
+
+
+
+ {{ goodsEdit.formData.unit ? goodsEdit.formData.unit : t('defaultUnit') }}
+
+
{{ t('maxBuyWarnTips') }}
+
+
+
+
+
+ {{ goodsEdit.formData.unit ? goodsEdit.formData.unit : t('defaultUnit') }}
+
+
{{ t('minBuyTips') }}
+
+
+
+
+
+
+
+
+
+
+
+ {{ item.name }}
+
+
请先在配置设置中设置配送方式
+
+
+
+
+
+
+
+
+
+ {{ t('selectTemplate') }}
+ {{ t('fixedShipping') }}
+
+
+
+
+ {{ t('yuan') }}
+
+
+
+
+
+
+
+ {{ t('refresh') }}
+ {{ t('addDeliveryTemplateId') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{{t('goodsArgumentsTempHint')}}
+
+
+
+
+
+
+
+
+
+ | {{t('argumentsName')}} |
+ {{t('argumentsValue')}} |
+
+
+ {{t('sort')}}
+
+
+
+
+ |
+ {{t('operation')}} |
+
+
+
+
+
+ | {{item.attr_value_name}} |
+
+
+ |
+
+
+
+
+ {{ childItem.name }}
+
+
+
+
+ {{ childItem.name }}
+
+
+ |
+
+
+ |
+
+ {{t('delAttr')}}
+ |
+
+
+
+ | {{t('noData')}} |
+
+
+
+
{{t('addGoodsArguments')}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('refresh') }}
+ {{t('addDetailTemp')}}
+
+
+ {{t('detailTempTip')}}
+
+
+
+
+
+ {{ t('refresh') }}
+ {{ t('addGoodsPoster') }}
+
+
+ {{ t('posterTips') }}
+
+
+
+
+
+ {{ t('refresh') }}
+ {{ t('addDiyForm') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/goods/recycle.vue b/niucloud/addon/shop/admin/views/goods/recycle.vue
new file mode 100644
index 000000000..eb904d710
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/goods/recycle.vue
@@ -0,0 +1,354 @@
+
+
+
+
+
+ {{ pageName }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('search') }}
+ {{ t('reset') }}
+
+
+
+
+
+
+
+
+ {{ t('batchRecycle') }}
+
+
+
+
+ {{ !goodsTable.loading ? t('emptyData') : '' }}
+
+
+
+
+
+
+
+
![]()
+
+
+ {{ row.goods_name }}
+ {{ row.goods_type_name }}
+
+
+
+
+
+
+
+ ¥{{ row.goodsSku.price }}
+
+
+
+
+
+
+
+ {{ t('statusOn') }}
+ {{ t('statusOff') }}
+
+
+
+
+
+ {{ row.create_time }}
+
+
+
+
+
+ {{ t('recycle') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/goods/search_config.vue b/niucloud/addon/shop/admin/views/goods/search_config.vue
new file mode 100644
index 000000000..bd4524fbc
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/goods/search_config.vue
@@ -0,0 +1,318 @@
+
+
+
+
+
+
+
+ {{ t('defaultSearch') }}
+
+
+
+
+
{{ t('defaultWordTips') }}
+
+
+
+ {{ t('hotSearch') }}
+
+
+
+
+
{{ t('addSearch') }}
+
+
+
+
+
+
+
+
+
+
{{ t('enableTips') }}
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('sortTypeTips') }}
+
+
+
+
+
+
+
+
+
+
{{ t('sortColumnTips') }}
+
+
+
+
+
+
{{ t('defaultSortTips') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/goods/service.vue b/niucloud/addon/shop/admin/views/goods/service.vue
new file mode 100644
index 000000000..658a8faed
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/goods/service.vue
@@ -0,0 +1,157 @@
+
+
+
+
+
+ {{pageName}}
+
+ {{ t('addServe') }}
+
+
+
+
+
+
+
+
+
+
+ {{ t('search') }}
+ {{ t('reset') }}
+
+
+
+
+
+
+
+ {{ !serveTable.loading ? t('emptyData') : '' }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('edit') }}
+ {{ t('delete') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/goods/virtual_edit.vue b/niucloud/addon/shop/admin/views/goods/virtual_edit.vue
new file mode 100644
index 000000000..aa8e3ad59
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/goods/virtual_edit.vue
@@ -0,0 +1,747 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{{ item.name }}
+
({{ item.desc }})
+
+
+ ✓
+
+
+
+
+
+
+
{{ item.name }}
+
({{ item.desc }})
+
+
+ ✓
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{{ t('goodsVideoTipTile') }}
+
{{ t('goodsVideoTipOne') }}
+
{{ t('goodsVideoTipTwo') }}
+
{{ t('goodsVideoTipThree') }}
+
{{ t('goodsVideoTipFour') }}
+
{{ t('goodsVideoTipFive') }}
+
+
+
+
+
+
+ {{ t('refresh') }}
+ {{ t('addGoodsCategory') }}
+
+
+
+
+
+
+
+
+ {{ t('refresh') }}
+ {{ t('addGoodsBrand') }}
+
+
+
+
+
+ {{ item.label_name }}
+
+
+ {{ t('refresh') }}
+ {{ t('addGoodsLabel') }}
+
+
+
+
+ {{ item.service_name }}
+
+
+ {{ t('refresh') }}
+ {{ t('addGoodsService') }}
+
+
+
+
+
+
+
+
+ {{ t('refresh') }}
+ {{ t('addSupplier') }}
+
+
+
+
+ {{ t('statusOn') }}
+ {{ t('statusOff') }}
+
+
+
+
+
+ {{ t('yes') }}
+ {{ t('no') }}
+
+
{{ t('giftTips') }}
+
+
+
+
+
+
+
+
+ {{ goodsEdit.formData.unit ? goodsEdit.formData.unit : '件' }}
+
+
{{ t('virtualSaleNumDesc') }}
+
+
+
+
+ {{ t('autoDeliverGoods') }}
+ {{ t('handDeliverGoods') }}
+
+
+
+
+
+ {{ t('autoTakeGoods') }}
+ {{ t('handTakeGoods') }}
+ {{ t('verifyTakeGoods') }}
+
+
{{ t('virtualSetTips') }}
+
+
+
+
+ {{ t('verifyVirtualIndateOne') }}
+ {{ t('verifyVirtualIndateTwo') }}
+ {{ t('verifyVirtualIndateThree') }}
+
+
+
+
+
+ {{t('sky')}}
+
+
+
+
+
+
{{t('verifyHint')}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('singleSpec') }}
+ {{ t('multiSpec') }}
+
+
{{ t('participateInActiveDisableTips') }}
+
+
+
+
+
+
+ {{ t('yuan') }}
+
+
+
+
+
+ {{ t('yuan') }}
+
+
+
+
+
+ {{ t('yuan') }}
+
+
+
+
+ {{ goodsEdit.formData.unit ? goodsEdit.formData.unit : t('defaultUnit') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('nonparticipation') }}
+ {{ t('discount') }}
+ {{ t('fixedPrice') }}
+
+
{{t('discountHint')}}
+
{{t('fixedPriceHint')}}
+
+
+
+
+
+
+
+
+
{{ t('isLimitTips') }}
+
+
+
+
+
+ {{ t('singleTime') }}
+ {{ t('singlePerson') }}
+
+
{{ t('limitTypeTips') }}
+
+
+
+
+
+ {{ goodsEdit.formData.unit ? goodsEdit.formData.unit : t('defaultUnit') }}
+
+
{{ t('maxBuyWarnTips') }}
+
+
+
+
+
+ {{ goodsEdit.formData.unit ? goodsEdit.formData.unit : t('defaultUnit') }}
+
+
{{ t('minBuyTips') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
{{t('goodsArgumentsTempHint')}}
+
+
+
+
+
+
+
+
+
+ | {{t('argumentsName')}} |
+ {{t('argumentsValue')}} |
+
+
+ {{t('sort')}}
+
+
+
+
+ |
+ {{t('operation')}} |
+
+
+
+
+
+ | {{item.attr_value_name}} |
+
+
+ |
+
+
+
+
+ {{ childItem.name }}
+
+
+
+
+ {{ childItem.name }}
+
+
+ |
+
+
+ |
+
+ {{t('delAttr')}}
+ |
+
+
+
+ | {{t('noData')}} |
+
+
+
+
{{t('addGoodsArguments')}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('refresh') }}
+ {{t('addDetailTemp')}}
+
+
+ {{t('detailTempTip')}}
+
+
+
+
+
+ {{ t('refresh') }}
+ {{ t('addGoodsPoster') }}
+
+
+ {{ t('posterTips') }}
+
+
+
+
+
+ {{ t('refresh') }}
+ {{ t('addDiyForm') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/index/index.vue b/niucloud/addon/shop/admin/views/index/index.vue
new file mode 100644
index 000000000..43638a4f5
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/index/index.vue
@@ -0,0 +1,375 @@
+
+
+
+
+
+
+ {{t('updateTime')}}
+ {{ time }}
+
+
+
+
+
+
+
+
+ {{t('todayOrderCount')}}
+
+
+
+
+
+
+
+
+
+
+ {{t('yesterday')}}
+ {{statYesterday.order_num}}
+
+
+
+
+
+
+
+
+
+
+
+
+ {{t('todayOrderSale')}}
+
+
+
+
+
+
+
+
+
+
+ {{t('yesterday')}}
+ {{statYesterday.sale_money}}
+
+
+
+
+
+
+
+
+
+
+
+
+ {{t('todayAddMemberCount')}}
+
+
+
+
+
+
+
+
+
+
+ {{t('yesterday')}}
+ {{statYesterday.refund_money}}
+
+
+
+
+
+
+
+
+
+
+
+
+ {{t('todayBrowseCount')}}
+
+
+
+
+
+
+
+
+
+
+ {{t('yesterday')}}
+ {{statYesterday.access_sum}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{t('waitPayOrder')}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{t('waitDeliveryOrder')}}
+
+
+
+
+
+
+ {{t('waitTakeOrder')}}
+
+
+
+
+
+
+ 退款订单
+
+
+
+
+
+
+ {{t('saleGoodsNum')}}
+
+
+
+
+
+
+ {{t('warehouseGoodsNum')}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/marketing/coupon/add.vue b/niucloud/addon/shop/admin/views/marketing/coupon/add.vue
new file mode 100644
index 000000000..347aa47e4
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/marketing/coupon/add.vue
@@ -0,0 +1,446 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 元
+
+
+
+
+
+
+ 通用券
+ 品类券
+ 商品券
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+

+
+
+ {{row.sku_name ? row.goods_name + " " + row.sku_name: row.goods_name}}
+ {{row.goods_type_name}}
+
+
+
+
+
+
+
+ ¥{{ row.price }}
+
+
+
+
+ {{ row.stock }}
+
+
+
+
+
+ {{ t("delete") }}
+
+
+
+
+
+
+
+
+ {{ t('reduction') }}
+ {{ t('noThreshold') }}
+
+
+
+
+ 最低满
+
+
+
+ 元可用
+
+
+
+
+
+ {{ t('days') }}
+ {{ t('times') }}
+
+
+
+
+ 领劵后立即生效,有效期
+
+
+
+ 天
+
+
+
+ 领劵后立即生效,使用时间截止至
+
+
+
+
+
+
+
+
+
+
+ {{ t('user') }}
+ {{ t('grant') }}
+
+
+ 开启手动领取后,会员可以直接在优惠券列表以及优惠券推广中直接领取
+
+
+
+
+
+ {{ t('limitedTime') }}
+ {{ t('unlimitedTime') }}
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('limit') }}
+ {{ t('unlimited') }}
+
+
+
+
+
+
+ 张
+
+
+ 最多发放100000张
+
+
+
+
+
+ 张
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/marketing/coupon/components/coupon-collection.vue b/niucloud/addon/shop/admin/views/marketing/coupon/components/coupon-collection.vue
new file mode 100644
index 000000000..6ceff3533
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/marketing/coupon/components/coupon-collection.vue
@@ -0,0 +1,199 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('search') }}
+ {{ t('reset') }}
+
+
+
+
+
+
+
+ {{ !tableData.loading ? t('emptyData') : '' }}
+
+
+
+
+
+
+ {{ row.member.nickname }}
+ {{ row.member.mobile }}
+
+
+
+
+
+
+
+
+
+ {{ row.use_time || '--' }}
+
+
+
+
+ {{ row.create_time }}至{{ row.expire_time }}
+
+
+
+
+ {{t('showOrder') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/marketing/coupon/components/coupon-select-content.vue b/niucloud/addon/shop/admin/views/marketing/coupon/components/coupon-select-content.vue
new file mode 100644
index 000000000..41eed8a80
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/marketing/coupon/components/coupon-select-content.vue
@@ -0,0 +1,164 @@
+
+
+
+
+
+
+
+ {{ t('search') }}
+ {{ t('reset') }}
+
+
+
+
+ {{ !tableData.loading ? t('emptyData') : '' }}
+
+
+
+
+
+
+
+
+
+
+ ¥{{row.price}}
+
+
+
+
+ 无门槛
+ 满{{ row.min_condition_money }}元可用
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/marketing/coupon/components/coupon-send-popop.vue b/niucloud/addon/shop/admin/views/marketing/coupon/components/coupon-send-popop.vue
new file mode 100644
index 000000000..cb77f7fd0
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/marketing/coupon/components/coupon-send-popop.vue
@@ -0,0 +1,255 @@
+
+
+
+
+
+ {{ couponTitle }}
+
+
+
+
+ {{ t('num') }}
+
+
{{ t('sendNumTip') }}
+
+
+
+
+
+ {{ label }}
+
+
+
+
+
+
+
+
+
+
+
+
![]()
+

+
+
+ {{ row.nickname || '' }}
+
+
+
+
+
+
+
+
+
+ {{ t("delete") }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/marketing/coupon/components/coupon-send-records.vue b/niucloud/addon/shop/admin/views/marketing/coupon/components/coupon-send-records.vue
new file mode 100644
index 000000000..86720d09f
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/marketing/coupon/components/coupon-send-records.vue
@@ -0,0 +1,139 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('search') }}
+ {{ t('reset') }}
+
+
+
+
+
+
+
+ {{ !tableData.loading ? t('emptyData') : '' }}
+
+
+
+ {{row.coupon.title }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/marketing/coupon/components/coupon-spread-popup.vue b/niucloud/addon/shop/admin/views/marketing/coupon/components/coupon-spread-popup.vue
new file mode 100644
index 000000000..613027cd3
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/marketing/coupon/components/coupon-spread-popup.vue
@@ -0,0 +1,107 @@
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/marketing/coupon/components/select-member.vue b/niucloud/addon/shop/admin/views/marketing/coupon/components/select-member.vue
new file mode 100644
index 000000000..2504e57d4
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/marketing/coupon/components/select-member.vue
@@ -0,0 +1,298 @@
+
+
+
+
+ {{ t('选择会员') }}
+
+ {{ t('已选') }}
+ {{ memberIds.length }}
+ {{ t('个') }}
+
+
+
+
+
+
+
+
+
+
+ {{ t('search') }}
+ {{ t('reset') }}
+
+
+
+
+
+ {{ !memberTable.loading ? t('emptyData') : '' }}
+
+
+
+
+
+
+
+
![]()
+

+
+
+ {{ row.nickname || '' }}
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('已选择') }}
+ {{ selectMemberNum }}
+ {{ t('个会员') }}
+
+
{{ t('取消选择') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/marketing/coupon/edit.vue b/niucloud/addon/shop/admin/views/marketing/coupon/edit.vue
new file mode 100644
index 000000000..c5c5a58d6
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/marketing/coupon/edit.vue
@@ -0,0 +1,471 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 通用券
+ 品类券
+ 商品券
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+

+
+
+ {{row.sku_name ? row.goods_name + " " + row.sku_name: row.goods_name}}
+ {{row.goods_type_name}}
+
+
+
+
+
+
+
+ ¥{{ row.price }}
+
+
+
+
+ {{ row.stock }}
+
+
+
+
+ {{ t("delete") }}
+
+
+
+
+
+
+
+
+ {{ t('reduction') }}
+ {{ t('noThreshold') }}
+
+
+
+
+ 最低满
+
+
+
+ 元可用
+
+
+
+
+
+ {{ t('days') }}
+ {{ t('times') }}
+
+
+
+
+ 领劵后立即生效,有效期
+
+
+
+ 天
+
+
+
+ 领劵后立即生效,使用时间截止至
+
+
+
+
+
+
+
+
+
+
+ {{ t('user') }}
+ {{ t('grant') }}
+
+
+ 开启手动领取后,会员可以直接在优惠券列表以及优惠券推广中直接领取
+
+
+
+
+
+ {{ t('limitedTime') }}
+ {{ t('unlimitedTime') }}
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('limit') }}
+ {{ t('unlimited') }}
+
+
+
+
+
+
+ 张
+
+
+
+
+
+
+
+ 张
+
+ 每个会员通过前端直接可领用数量
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/marketing/coupon/list.vue b/niucloud/addon/shop/admin/views/marketing/coupon/list.vue
new file mode 100644
index 000000000..9983132c4
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/marketing/coupon/list.vue
@@ -0,0 +1,390 @@
+
+
+
+
+
+
+ {{ pageName }}
+ {{ t('addCoupon') }}
+
+
+
+
+
+
+
+
+
+
+ {{ t('search') }}
+ {{ t('reset') }}
+
+
+
+
+
+
+
+
+
+
+
+
+ {{t("batchDelete")}}
+ {{t("batchClose")}}
+
+
+
+ {{ !tableData.loading ? t('emptyData') : '' }}
+
+
+
+
+
+
+ ¥{{row.price}}
+
+
+
+
+
+ 是
+ 否
+
+
+
+
+
+ {{ t('count') }}
+
+ {{t('countTips1')}}
{{t('countTips2')}}
{{t('countTips3')}}
{{t('countTips4')}}
+
+
+
+
+
+
+
+
+
+
{{ t('sumCount') }}:{{row.remain_count || 0 }} / {{ row.sum_count || 0 }} 张
+
{{ t('sumCount') }}:{{ t('noLimit') }}
+
{{ t('receiveCount') }}:{{ row.receive_count || 0 }} 张
+
{{ t('giveCount') }}:{{ row.give_count || 0 }} 张
+
{{ t('receiveUseCount') }}:{{ row.receive_use_count || 0 }} 张
+
+
+
+
+
+ 无门槛
+ 满{{ row.min_condition_money }}元可用
+
+
+
+
+
+ 领取之日起{{ row.length || '' }} 天内有效
+ 使用截止时间至{{ row.valid_end_time || ''}}
+
+ --
+
+
+
+
+
+
+ 开始时间:{{row.start_time}}
+ 结束时间:{{row.end_time}}
+
+
不限时
+
+ --
+
+
+
+
+
+ {{ t('spreadGoods') }}
+ {{ t('edit') }}
+ {{t('delete') }}
+ {{ t('close') }}
+ {{ t('receive') }}
+ {{ t('send') }}
+ {{ t('sendRecord') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/marketing/discount/add.vue b/niucloud/addon/shop/admin/views/marketing/discount/add.vue
new file mode 100644
index 000000000..a12188bbb
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/marketing/discount/add.vue
@@ -0,0 +1,815 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{{ t('titleTip') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('emptyData') }}
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+

+
+
+ {{ row.goods_name }}
+ {{ row.goods_type_name }}
+
+
+
+
+
+
+
+ ¥{{ row.goodsSku.price }}
+
+
+
+
+
+
+
+
+
+
+ {{ row.min_discount_rate == row.max_discount_rate ? row.min_discount_rate : row.min_discount_rate + '-' + row.max_discount_rate }}
+ --
+
+
+
+
+
+
+
+
+
+ {{ row.min_reduce_money == row.max_reduce_money ? row.min_reduce_money : row.min_reduce_money + '-' + row.max_reduce_money }}
+ --
+
+
+
+
+
+
+
+
+
+ {{ row.min_specify_price == row.max_specify_price ? row.min_specify_price : row.min_specify_price + '-' + row.max_specify_price }}
+ --
+
+
+
+
+
+ {{ row.discount_type == 'discount' ? t('discounts') : row.discount_type == 'reduce' ? t('reduceMoney') : t('promotional') }}
+ 请在设置中查看
+
+
+
+
+ {{ t('skuDiscountSettings') }}
+ {{ t('delete') }}
+
+
+
+
+
+
+ 已选 {{ multipleSelection.length }} 项
+
+
+
+
+
+
+
+
+
+ {{ t('confirm') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/marketing/discount/components/discount-detail.vue b/niucloud/addon/shop/admin/views/marketing/discount/components/discount-detail.vue
new file mode 100644
index 000000000..c5bd7f470
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/marketing/discount/components/discount-detail.vue
@@ -0,0 +1,407 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{formData.name}}
+
+
+
+
+
+
+ {{formData.remark}}
+
+
+
+
+
+
+ {{formData.status_name}}
+
+
+
+
+
+
+ {{formData.order_money}}
+
+
+
+
+
+
+ {{formData.member_num}}
+
+
+
+
+
+
+ {{formData.order_num}}
+
+
+
+
+
+
+ {{formData.start_time}}
+
+
+
+
+
+
+ {{formData.end_time}}
+
+
+
+
+
+
+ {{formData.create_time}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('search') }}
+
+
+
+
+ {{ !goodsParams.loading ? t('emptyData') : '' }}
+
+
+
+
+
+
+
+
+

+
+
+
+

+
+
+ {{ row.goods_name }}
+
+
+
+
+
+
+ ¥{{ row.price }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('search') }}
+ {{ t('reset') }}
+
+
+
+
+ {{ !orderParams.loading ? t('emptyData') : '' }}
+
+
+
+ {{ row.order_no }}
+
+
+
+
+
+
+
+ {{ row.member.nickname }}
+ {{ row.taker_name }} {{row.taker_mobile }}
+ {{ row.taker_full_address }}
+
+
+
+
+
+ {{ row.pay && row.pay.type_name ? row.pay.type_name : ''}}
+
+
+
+
+ {{ row.order_status_data.name }}
+
+
+
+
+
+
+
+
+
+
+
+ {{ !memberParams.loading ? t('emptyData') : '' }}
+
+
+
+
+
+
+
+
+

+
+
+
+

+
+
+ {{row.member.nickname || row.member.username}}
+ {{row.mobile || ''}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/marketing/discount/components/goods-sku-popup.vue b/niucloud/addon/shop/admin/views/marketing/discount/components/goods-sku-popup.vue
new file mode 100644
index 000000000..dfa09579b
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/marketing/discount/components/goods-sku-popup.vue
@@ -0,0 +1,521 @@
+
+
+
+
+
+
+ {{ t('emptyData') }}
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+

+
+
+ {{ row.sku_name || row.goods?.goods_name }}
+
+
+
+
+
+
+
+
+
+
+
+ {{ row.discount_rate }}
+
+
+
+
+
+
+
+ {{ row.reduce_money }}
+
+
+
+
+
+
+
+ {{ row.specify_price }}
+
+
+
+
+ {{ row.discount_type == 'discount' ? t('discounts') : row.discount_type == 'reduce' ? t('reduceMoney') : t('promotional') }}
+
+
+
+
+ {{ row.is_enabled ? t('noEnabled') : t('enabled') }}
+
+
+
+
+
+
+ 已选{{ multipleSelection.length }}项
+
+
+
+
+
+
+
+
+
+ {{ t('confirm') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/marketing/discount/config.vue b/niucloud/addon/shop/admin/views/marketing/discount/config.vue
new file mode 100644
index 000000000..8cbe35851
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/marketing/discount/config.vue
@@ -0,0 +1,137 @@
+
+
+
+
+
+ {{ pageName }}
+
+
+
+
+
+
{{t('headTitle')}}
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('addConfigList') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/marketing/discount/detail.vue b/niucloud/addon/shop/admin/views/marketing/discount/detail.vue
new file mode 100644
index 000000000..d608d9b50
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/marketing/discount/detail.vue
@@ -0,0 +1,380 @@
+
+
+
+
+
+
+
+
+
+ {{ t('baseInfo') }}
+
+
+
+
+
+ {{formData.active_name}}
+
+
+
+
+
+
+ {{formData.active_desc}}
+
+
+
+
+
+
+ {{formData.active_status_name}}
+
+
+
+
+
+
+ {{formData.active_order_money}}
+
+
+
+
+
+
+ {{formData.active_member_num}}
+
+
+
+
+
+
+ {{formData.active_order_num}}
+
+
+
+
+
+
+ {{formData.start_time}}
+
+
+
+
+
+
+ {{formData.end_time}}
+
+
+
+
+
+
+ {{formData.create_time}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('search') }}
+
+
+
+
+ {{ !goodsParams.loading ? t('emptyData') : '' }}
+
+
+
+
+
+
+
+
+

+
+
+
+

+
+
+ {{ row.goods.goods_name }}
+
+
+
+
+
+
+ ¥{{ row.goodsSku.price }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('search') }}
+ {{ t('reset') }}
+
+
+
+
+ {{ !orderParams.loading ? t('emptyData') : '' }}
+
+
+
+
+
+
+ {{ row.member.nickname }}
+ {{ row.taker_name }} {{row.taker_mobile }}
+ {{ row.taker_full_address }}
+
+
+
+
+
+ {{ row.pay && row.pay.type_name ? row.pay.type_name : ''}}
+
+
+
+
+ {{ row.order_status_data.name }}
+
+
+
+
+
+
+
+
+
+
+
+ {{ !memberParams.loading ? t('emptyData') : '' }}
+
+
+
+
+
+
+
+
+

+
+
+
+

+
+
+ {{row.member.nickname || row.member.username}}
+ {{row.mobile || ''}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/marketing/discount/edit.vue b/niucloud/addon/shop/admin/views/marketing/discount/edit.vue
new file mode 100644
index 000000000..5205d1c6e
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/marketing/discount/edit.vue
@@ -0,0 +1,883 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{{ t('titleTip') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('emptyData')}}
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+

+
+
+ {{ row.goods_name }}
+ {{ row.goods_type_name }}
+
+
+
+
+
+
+
+
+ ¥{{ row.goodsSku.price }}
+
+
+
+
+
+
+
+
+
+ {{ row.min_discount_rate==row.max_discount_rate?row.min_discount_rate:row.min_discount_rate+'-'+row.max_discount_rate }}
+ --
+
+
+
+
+
+
+
+
+
+ {{ row.min_reduce_money==row.max_reduce_money?row.min_reduce_money:row.min_reduce_money+'-'+row.max_reduce_money }}
+ --
+
+
+
+
+
+
+
+
+
+ {{ row.min_specify_price==row.max_specify_price?row.min_specify_price:row.min_specify_price+'-'+row.max_specify_price }}
+ --
+
+
+
+
+
+ {{ row.discount_type=='discount'?t('discounts'):row.discount_type=='reduce'?t('reduceMoney'):t('promotional')}}
+ 请在设置中查看
+
+
+
+
+
+
+ {{t('skuDiscountSettings') }}
+
+ {{t('delete') }}
+
+
+
+
+
+
+
+ 已选 {{ multipleSelection.length }} 项
+
+
+
+
+
+
+
+
+
+ {{ t('confirm') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/marketing/discount/list.vue b/niucloud/addon/shop/admin/views/marketing/discount/list.vue
new file mode 100644
index 000000000..3edbe9515
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/marketing/discount/list.vue
@@ -0,0 +1,282 @@
+
+
+
+
+
+ {{ pageName }}
+
+ {{ t('addDiscount') }}
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('search') }}
+ {{ t('reset') }}
+
+
+
+
+
+
+
+
+
+
+
+
+ {{t("batchDelete")}}
+ {{t("batchClose")}}
+
+
+
+ {{ !tableData.loading ? t('emptyData') : '' }}
+
+
+
+
+
+
+
+
+
+
+
+
开始:{{ row.start_time }}
+
结束:{{ row.end_time }}
+
+
+
+
+
+ {{ t('edit') }}
+ {{ t('detail') }}
+ {{ t('close') }}
+ {{ t('delete') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/marketing/exchange/components/goods-select-content.vue b/niucloud/addon/shop/admin/views/marketing/exchange/components/goods-select-content.vue
new file mode 100644
index 000000000..6b8616d78
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/marketing/exchange/components/goods-select-content.vue
@@ -0,0 +1,182 @@
+
+
+
+
+
+
+
+ {{ t('search') }}
+ {{ t('reset') }}
+
+
+
+
+ {{ !tableData.loading ? t('emptyData') : '' }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+

+
+
+ {{ row.names }}
+
+
+
+
+
+
+ {{ row.point }}{{ t('pointExchangeSelectContentPointUnit') }}
+ {{ row.price }}{{ t('pointExchangeSelectContentPriceUnit') }}
+
+
+
+
+ {{ row.total_exchange_num }}/{{ row.stock }}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/marketing/exchange/components/goods-select-popup.vue b/niucloud/addon/shop/admin/views/marketing/exchange/components/goods-select-popup.vue
new file mode 100644
index 000000000..80258d483
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/marketing/exchange/components/goods-select-popup.vue
@@ -0,0 +1,169 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('search') }}
+ {{ t('reset') }}
+
+
+
+
+
+
+ {{ !tableData.loading ? t('emptyData') : '' }}
+
+
+
+
+
+
+
+
+
+

+
+
+
+

+
+
+ {{ row.names }}
+
+
+
+
+
+
+ {{ row.point }}{{ t('goodsSelectPopupGoodsPointUnit') }}
+ {{ row.price }}{{ t('goodsSelectPopupGoodsPriceUnit') }}
+
+
+
+
+ {{ row.stock }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/marketing/exchange/components/goods-sku-select.vue b/niucloud/addon/shop/admin/views/marketing/exchange/components/goods-sku-select.vue
new file mode 100644
index 000000000..eb7933f50
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/marketing/exchange/components/goods-sku-select.vue
@@ -0,0 +1,101 @@
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+

+
+
+ {{ row.sku_name || row.goods?.goods_name }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/marketing/exchange/goods_add.vue b/niucloud/addon/shop/admin/views/marketing/exchange/goods_add.vue
new file mode 100644
index 000000000..21331b91e
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/marketing/exchange/goods_add.vue
@@ -0,0 +1,846 @@
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('baseInfo') }}
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+

+
+
+
{{ formData.goods_info.goods_name }}
+
{{ formData.goods_info.goods_price }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('redemptionSettings') }}
+
+
+
+
+
+ 已选{{ multipleSelection.length }}项
+
+
+
+
+
+
+
+ {{ t('confirm') }}
+
+
+
+ {{ t('emptyData')}}
+
+
+
+
+
+
+
+
+
+

+
+
+
+

+
+
+ {{ row.sku_name||row.goods?.goods_name }}
+
+
+
+
+
+
+
+
+
+
+
+
+ --
+
+
+
+
+
+ {{ t('limit') }}
+
+
+
+
+
+
+
+
+
+
+
+
+ {{t('limitUnit')}}
+
+
+
+ --
+
+
+
+
+
+
+
+
+
+ {{t('integralUnit')}}
+
+
+
+ --
+ +
+
+
+
+
+ {{t('prickUnit')}}
+
+
+
+
+
+
+
+
+ {{ row.is_enabled?t('noEnabled'):t('enabled') }}
+
+
+
+
+
+
+
+
+ {{ t('redemptionSettings') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{t('integralUnit')}}
+
+
+
+ +
+
+
+
+
+ {{t('prickUnit')}}
+
+
+
+
+
+
+
+
+ {{ t('redemptionSettings') }}
+
+
+
+
+
+
+
+ 可提现余额
+ 不可提现余额
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{t('integralUnit')}}
+
+
+
+ +
+
+
+
+
+ {{t('prickUnit')}}
+
+
+
+
+
+
+
+
+ {{ t('goodsDetail') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/marketing/exchange/goods_edit.vue b/niucloud/addon/shop/admin/views/marketing/exchange/goods_edit.vue
new file mode 100644
index 000000000..df7fb4d5b
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/marketing/exchange/goods_edit.vue
@@ -0,0 +1,802 @@
+
+
+
+
+
+
+
+
+
+ {{ t('baseInfo') }}
+
+
+
+
+
+
+
+
+

+
+
+
+

+
+
+
{{ formData.goods_info.goods_name }}
+
{{ formData.goods_info.goods_price }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('redemptionSettings') }}
+
+
+
+
+
+ 已选{{ multipleSelection.length }}项
+
+
+
+
+
+
+
+ {{ t('confirm') }}
+
+
+
+ {{ t('emptyData')}}
+
+
+
+
+
+
+
+
+
+

+
+
+
+

+
+
+ {{ row.sku_name||row.goods?.goods_name }}
+
+
+
+
+
+
+
+
+
+
+
+
+ --
+
+
+
+
+
+ {{ t('limit') }}
+
+
+
+
+
+
+
+
+
+
+
+
+ {{t('limitUnit')}}
+
+
+
+ --
+
+
+
+
+
+
+
+
+
+ {{t('integralUnit')}}
+
+
+
+ --
+ +
+
+
+
+
+ {{t('prickUnit')}}
+
+
+
+
+
+
+
+
+ {{ row.is_enabled?t('noEnabled'):t('enabled') }}
+
+
+
+
+
+
+
+
+ {{ t('redemptionSettings') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{t('integralUnit')}}
+
+
+
+ +
+
+
+
+
+ {{t('prickUnit')}}
+
+
+
+
+
+
+
+
+ {{ t('redemptionSettings') }}
+
+
+
+
+
+
+
+
+ 可提现余额
+ 不可提现余额
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{t('integralUnit')}}
+
+
+
+ +
+
+
+
+
+ {{t('prickUnit')}}
+
+
+
+
+
+
+
+
+ {{ t('goodsDetail') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/marketing/exchange/goods_list.vue b/niucloud/addon/shop/admin/views/marketing/exchange/goods_list.vue
new file mode 100644
index 000000000..171830db9
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/marketing/exchange/goods_list.vue
@@ -0,0 +1,356 @@
+
+
+
+
+
+ {{ pageName }}
+
+ {{ t('addGoods') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('search') }}
+ {{ t('reset') }}
+
+
+
+
+
+
+
+
+
+
+
+
+ {{t("batchDelete")}}
+ {{t("batchUp")}}
+ {{t("batchDown")}}
+
+
+
+ {{ !tableData.loading ? t('emptyData') : '' }}
+
+
+
+
+
+
+
+
+
+

+
+
+
+

+
+
+ {{ row.names }}
+
+
+
+
+
+
+ {{ row.point }}{{ t('pointUnit') }}
+ {{ row.price }}{{ t('priceUnit') }}
+
+
+
+
+ {{ row.total_exchange_num }}/{{ row.stock }}
+
+
+
+
+ {{ row.create_time }}
+
+
+
+
+
+ {{ t('edit') }}
+ {{ t('spreadGoods') }}
+ {{ t('down') }}
+ {{ t('up') }}
+ {{ t('delete') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/marketing/exchange/order_list.vue b/niucloud/addon/shop/admin/views/marketing/exchange/order_list.vue
new file mode 100644
index 000000000..dcecce28b
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/marketing/exchange/order_list.vue
@@ -0,0 +1,225 @@
+
+
+
+
+
+ {{ pageName }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('search') }}
+ {{ t('reset') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ !orderTable.loading ? t('emptyData') : '' }}
+
+
+
+
+ {{ row.order_no }}
+
+
+
+
+
+
+
![]()
+

+
+
+
{{ item.goods_name }}
+
{{ item.sku_name }}
+
+
+
+
+
+
+
+
+ {{ item.extend.point }}{{ t('point') }}
+ +¥{{ item.extend.price }}
+
+ ¥{{ item.price }}
+ {{ item.num }}{{ t('piece') }}
+
+
+
+
+
+
+ {{ row.point }}{{ t('point') }}
+ +¥{{ row.order_money }}
+
+ ¥{{ row.order_money }}
+
+
+
+
+ {{ row.create_time }}
+
+
+
+
+ {{ row.status_name.name }}
+
+
+
+
+ {{ t('info') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/marketing/goods_rank/components/rank-select-popup.vue b/niucloud/addon/shop/admin/views/marketing/goods_rank/components/rank-select-popup.vue
new file mode 100644
index 000000000..f2ec57222
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/marketing/goods_rank/components/rank-select-popup.vue
@@ -0,0 +1,281 @@
+
+
+
+
+ {{ t('rankSelectPopupSelectRankButton') }}
+
+ {{ t('goodsSelectPopupSelect') }}
+ {{ rankIds.length }}
+ {{ t('goodsSelectPopupPiece') }}
+
+
+
+
+
+
+
+
+
+ {{ t('search') }}
+ {{ t('reset') }}
+
+
+
+
+
+ {{ !rankTable.loading ? t('emptyData') : '' }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('goodsSelectPopupBeforeTip') }}
+ {{ selectRankNum }}
+ {{ t('rankSelectPopupAfterTip') }}
+
+
{{ t('goodsSelectPopupClearGoods') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/marketing/goods_rank/config.vue b/niucloud/addon/shop/admin/views/marketing/goods_rank/config.vue
new file mode 100644
index 000000000..fe9241f5e
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/marketing/goods_rank/config.vue
@@ -0,0 +1,130 @@
+
+
+
+
+
+ {{ pageName }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/marketing/goods_rank/edit.vue b/niucloud/addon/shop/admin/views/marketing/goods_rank/edit.vue
new file mode 100644
index 000000000..f285235a2
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/marketing/goods_rank/edit.vue
@@ -0,0 +1,511 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('rankTypeTips') }}
+
+
+ {{ value }}
+
+
+
+
+
+ {{ value }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+

+
+
+ {{row.sku_name ? row.goods_name + " " + row.sku_name: row.goods_name}}
+ {{row.goods_type_name}}
+
+
+
+
+
+
+
+ ¥{{ row.price }}
+
+
+
+
+
+
+ {{ t('sort') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t("delete") }}
+
+
+
+
+
+
+
+
+ {{ t("refresh")}}
+ {{ t("addCategory") }}
+
+
+
+
+
+
+
+
+ {{ t("refresh")}}
+ {{ t("addBrand") }}
+
+
+
+
+
+ {{ item.label_name}}
+
+
+ {{ t("refresh") }}
+ {{ t("addLabel") }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/marketing/goods_rank/list.vue b/niucloud/addon/shop/admin/views/marketing/goods_rank/list.vue
new file mode 100644
index 000000000..f5ca5b998
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/marketing/goods_rank/list.vue
@@ -0,0 +1,286 @@
+
+
+
+
+ {{ pageName }}
+ {{ t("addRanking") }}
+
+
+
+
+
+
+
+
+
+ {{ t("search") }}
+ {{ t("reset") }}
+
+
+
+
+
+
+
+
+ {{ t("batchDeletion") }}
+
+
+
+ {{ !tableData.loading ? t("emptyData") : "" }}
+
+
+
+
+
+
+
+
+
+ {{ row.status != 0 ? '开启' : '关闭' }}
+
+
+
+
+
+ {{ t('sort') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ row.create_time }}
+
+
+
+
+
+ {{ t("edit") }}
+ {{ t("delete") }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/marketing/index.vue b/niucloud/addon/shop/admin/views/marketing/index.vue
new file mode 100644
index 000000000..07e77f1dd
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/marketing/index.vue
@@ -0,0 +1,97 @@
+
+
+
+
+
+
+
+ {{ item.name }}
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/marketing/manjian/detail.vue b/niucloud/addon/shop/admin/views/marketing/manjian/detail.vue
new file mode 100644
index 000000000..e7a1f76d1
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/marketing/manjian/detail.vue
@@ -0,0 +1,288 @@
+
+
+
+
+
+
+
+
+
+ {{ t('basicInfo') }}
+
+
+
+
+
+
+ {{formData.manjian_name}}
+
+
+
+
+
+
+ {{formData.status_name}}
+
+
+
+
+
+
+ {{formData.total_goods_num}}
+
+
+
+
+
+
+ {{formData.total_coupon_num}}
+
+
+
+
+
+
+ {{formData.total_balance}}
+
+
+
+
+
+
+ {{formData.total_point}}
+
+
+
+
+
+
+ {{formData.total_order_money}}
+
+
+
+
+
+
+ {{formData.total_member_num}}
+
+
+
+
+
+
+ {{formData.total_order_num}}
+
+
+
+
+
+
+ {{formData.start_time}}
+
+
+
+
+
+
+ {{formData.end_time}}
+
+
+
+
+
+
+ {{formData.create_time}}
+
+
+
+
+
+
+
+
+
+ {{ t('activeDetail') }}
+
+
+
+ 满{{ row.limit }}{{ formData.condition_type == 'over_n_yuan' ? '元' : '件' }}
+ -
+
+
+
+
+ {{ row.discount_money }}{{row.discount_type==1 ? '元' : '折'}}
+ -
+
+
+
+
+ {{ row.point }}
+ -
+
+
+
+
+ {{ row.balance }}
+ -
+
+
+
+
+ {{ t('freeShipping')}}
+ -
+
+
+
+
+
+
+
{{ coupon.title }}
+
* {{ coupon.num }}
+
+
+ -
+
+
+
+
+
+
+
{{ goods.goods_name }}
+
* {{ goods.num }}
+
+
+ -
+
+
+
+
+
+
+
+
+
+ {{ !memberParams.loading ? t('emptyData') : '' }}
+
+
+
+
+
+
+
+
+

+
+
+
+

+
+
+ {{row.nickname || row.username}}
+ {{row.mobile || ''}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/marketing/manjian/edit.vue b/niucloud/addon/shop/admin/views/marketing/manjian/edit.vue
new file mode 100644
index 000000000..a163d117c
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/marketing/manjian/edit.vue
@@ -0,0 +1,866 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('overNyuan') }}
+ {{ t('overNgoods') }}
+
+
+
+
+
+ {{t('ladder')}}
+ {{t('cycle')}}
+
+
+ {{ t('ruleTypeTips') }}
+ {{ t('ruleTypeTipsTwo') }}
+
+
+
+
+
+
+
+
+
+
+
+ 满
+
+ {{ formData.condition_type === 'over_n_yuan' ? '元' : '件' }}
+
+
+
+
+
+
+
+
+
+
+
+
{{t('discountMoney')}}
+
+
+
+ {{ t('reduce') }}
+ {{ t('discountRate') }}
+
+
+
+ {{ level.discount_type === 1 ? '减' : '打' }}
+
+
+ {{ level.discount_type === 1 ? '元' : '折' }}
+
+
+
+
+
+
+
+
+
{{t('freeShipping')}}
+
{{t('freeTips')}}
+
+
+
+
+
{{t('givePoint')}}
+
+
+ 送
+
+ 积分
+
+
+
+
+
+
{{t('giveBalance')}}
+
+
+ 送
+
+ 余额
+
+
+
+
+
+
{{t('giveCoupon')}}
+
{{ t('giveCouponTips') }}
+
+
+
+
+
+
+
+
+ {{ row.title }}
+
+
+
+
+ {{ row.type_name }}
+
+
+
+
+ ¥{{ row.price }}
+
+
+
+
+
+
+
+
+
+
+
+ {{ t("delete") }}
+
+
+
+
+
+
+
+
+
+
{{ t("giveGoods") }}
+
{{ t('giveGoodsTips') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+

+
+
+ {{row.sku_name ? row.goods_name + " " + row.sku_name: row.goods_name}}
+ {{row.goods_type_name}}
+
+
+
+
+
+
+
+ ¥{{ row.price }}
+
+
+
+
+ {{ row.stock }}
+
+
+
+
+
+
+
+
+
+
+
+ {{ t("delete") }}
+
+
+
+
+
+
+
+
+
+
+
+
+
{{ t('addActivityLevel') }}
+
+
+
+
+
+ {{t('allMember')}}
+ {{t('selectedMemberLevel')}}
+ {{t('selectedMemberLabel')}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('allGoods') }}
+ {{ t('selectedGoods') }}
+ {{ t('selectedGoodsNot') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+

+
+
+ {{row.sku_name ? row.goods_name + " " + row.sku_name: row.goods_name}}
+ {{row.goods_type_name}}
+
+
+
{{ row.error_msg }}
+
+
{{ t('goodsOffTips') }}
+
+
+
+
+
+
+
+ ¥{{ row.price }}
+
+
+
+
+ {{ t("delete") }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/marketing/manjian/list.vue b/niucloud/addon/shop/admin/views/marketing/manjian/list.vue
new file mode 100644
index 000000000..88f694d0b
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/marketing/manjian/list.vue
@@ -0,0 +1,295 @@
+
+
+
+
+ {{ pageName }}
+ {{ t("addFullDiscountBonus") }}
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t("search") }}
+ {{ t("reset") }}
+
+
+
+
+
+
+
+
+
+
+
+
+ {{t("batchDelete")}}
+ {{t("batchClose")}}
+
+
+
+ {{ !tableData.loading ? t("emptyData") : "" }}
+
+
+
+
+
+
+
+
+
+
+
开始:{{ row.start_time }}
+
结束:{{ row.end_time }}
+
+
+
+
+
+ {{t("edit")}}
+ {{ t('detail') }}
+ {{ t('close') }}
+ {{ t("delete") }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/marketing/newcomer/config.vue b/niucloud/addon/shop/admin/views/marketing/newcomer/config.vue
new file mode 100644
index 000000000..bf11be6a2
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/marketing/newcomer/config.vue
@@ -0,0 +1,495 @@
+
+
+
+
+ {{ pageName }}
+
+
+
+
+ * 新人专享活动旨在通过专属优惠提升新老客户的转化率。达到参与门槛的用户可以享受特定商品的限时新人价优惠。
+ * 每位用户限购1件新人专享商品,超出1件的部分将按正常价购买。
+ * 订单支付成功后,将视为用户已参与过新人专享活动。
+ * 若订单中的单个商品发生退款,用户将无法重新参与新人专享活动,只有当整个订单全部退货后,用户方可重新参与该活动。
+
+
+
+
+ {{ t('basicInfoTab') }}
+
+
+
+
+
+
+ {{ t('neverOrder') }}
+ {{ t('assignTimeOrder') }}
+ {{ t('assignTimeRegister') }}
+
+
+
+
+
+
+ 之前未下过单的会员
+ 之后注册的会员
+
+
+
+
+ {{ t('validityDay') }}
+ {{ t('validityTime') }}
+
+
+
+ {{ t('validityDayTipsLeft') }}
+
+ {if(formData.validity_day>0) formData.validity_day = parseInt(formData.validity_day)}" clearable class="input-width-short" maxlength="3" />
+
+ {{ t('validityDayTipsRight') }}
+ {{ t('validityTimeTipsTwo') }}
+
+
+ {{ t('validityTimeTips') }}
+
+
+
+ {{ t('validityTimeTipsTwo') }}
+
+
+
+
+ {{ t('useDefaultActiveDesc') }}
+
+
+
+
+
+ {{ t('bannerList') }}
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('activityGoods') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+

+
+
+
{{ row.goods_name }}
+
+ {{row.sku_name}}
+ |
+ {{ row.goods_type_name }}
+
+
+
+
+
+
+
+ ¥{{ row.price }}
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('delete') }}
+
+
+
+
+
+ 已选 {{ multipleSelection.length }} 项
+
+
+
+
+ {{ t('confirm') }}
+ {{ t('批量删除') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/marketing/newcomer/order_list.vue b/niucloud/addon/shop/admin/views/marketing/newcomer/order_list.vue
new file mode 100644
index 000000000..94d02292b
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/marketing/newcomer/order_list.vue
@@ -0,0 +1,293 @@
+
+
+
+
+
+ {{ pageName }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('search') }}
+ {{ t('reset') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('orderNo') }}:{{ (item as any).order_no }}
+ {{ t('createTime') }}:{{ (item as any).create_time }}
+
+ {{ t('payType') }}:{{ (item as any).pay.type_name }}
+
+
+
+
+ {{ !orderTable.loading ? t('emptyData') : '' }}
+
+
+
+
+
+
+
+
![]()
+

+
+
+
{{ row.goods_name }}
+
{{ row.sku_name }}
+
+
+
+
+
+
+
+ {{ t('goodsPriceNumber') }}
+
+ {{t('goodsPriceNumberTips')}}
+
+
+
+
+
+
+
+
+ ¥{{ row.price }}
+
+ {{ row.num }}{{ t('piece') }}(第1{{ t('piece') }},¥{{parseFloat(row.extend.newcomer_price).toFixed(2)}}/{{ t('piece') }};第{{row.num>2?'2~'+row.num:'2'}}{{ t('piece') }},¥{{parseFloat(row.price).toFixed(2)}}/{{ t('piece') }})
+ {{ row.num }}{{ t('piece') }}
+
+ {{ row.num }}{{ t('piece') }}
+
+
+
+
+
+ ¥{{ item.order_money }}
+
+
+
+
+ {{ item.status_name.name }}
+
+
+
+
+ {{ t('info') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/member/components/benefits-free-shipping.vue b/niucloud/addon/shop/admin/views/member/components/benefits-free-shipping.vue
new file mode 100644
index 000000000..e4b80c2a9
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/member/components/benefits-free-shipping.vue
@@ -0,0 +1,63 @@
+
+
+
+
+
+ 包邮
+
+
+ 该包邮仅针对物流配送
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/member/components/gift-coupon.vue b/niucloud/addon/shop/admin/views/member/components/gift-coupon.vue
new file mode 100644
index 000000000..1fd7195f5
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/member/components/gift-coupon.vue
@@ -0,0 +1,163 @@
+
+
+
+
+
+ 送优惠券
+
+
+
+
+
+
+ 选择优惠券
+
+
+
+
+
+
+
+
+ ¥{{row.price}}
+
+
+
+
+ 无门槛
+ 满{{ row.min_condition_money }}元可用
+
+
+
+
+
+ 领取之日起{{ row.length || '' }} 天内有效
+ 使用截止时间至{{ row.valid_end_time || ''}}
+
+ --
+
+
+
+
+
+
+
+
+
+ {{ t('delete') }}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/member/components/growth-rule-buygoods.vue b/niucloud/addon/shop/admin/views/member/components/growth-rule-buygoods.vue
new file mode 100644
index 000000000..176e02f2d
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/member/components/growth-rule-buygoods.vue
@@ -0,0 +1,113 @@
+
+
+
+
+
+ 购买商品
+
+
+
+
每消费
+
+
+
+
元,获得
+
+
+
+
成长值
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/member/components/growth-rule-buyorder.vue b/niucloud/addon/shop/admin/views/member/components/growth-rule-buyorder.vue
new file mode 100644
index 000000000..846827acb
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/member/components/growth-rule-buyorder.vue
@@ -0,0 +1,99 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/member/components/point-rule-buygoods.vue b/niucloud/addon/shop/admin/views/member/components/point-rule-buygoods.vue
new file mode 100644
index 000000000..fe7ba6257
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/member/components/point-rule-buygoods.vue
@@ -0,0 +1,113 @@
+
+
+
+
+
+ 购买商品
+
+
+
+
每消费
+
+
+
+
元,获得
+
+
+
+
积分
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/member/components/point-rule-orderdeduction.vue b/niucloud/addon/shop/admin/views/member/components/point-rule-orderdeduction.vue
new file mode 100644
index 000000000..c599a6f47
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/member/components/point-rule-orderdeduction.vue
@@ -0,0 +1,113 @@
+
+
+
+
+
+
+ 积分抵现
+
+
+
每
+
+
+
+
积分,可抵扣
+
+
+
+
元
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/member/components/recharge-detail-coupon.vue b/niucloud/addon/shop/admin/views/member/components/recharge-detail-coupon.vue
new file mode 100644
index 000000000..93b655144
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/member/components/recharge-detail-coupon.vue
@@ -0,0 +1,95 @@
+
+
+
+
+
+
+
+ {{ row.title }}
+
+
+
+
+ {{ row.type_name }}
+
+
+
+
+ ¥{{ row.price }}
+
+
+
+
+ 无门槛
+ 满{{ row.min_condition_money }}元可用
+
+
+
+
+ 领取之日起{{ row.length || '' }} 天内有效
+ 使用截止时间至{{ row.valid_end_time || ''}}
+
+
+
+
+ {{ row.num }}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/member/components/recharge-gift-coupon.vue b/niucloud/addon/shop/admin/views/member/components/recharge-gift-coupon.vue
new file mode 100644
index 000000000..e25915230
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/member/components/recharge-gift-coupon.vue
@@ -0,0 +1,187 @@
+
+
+
+
+
+ {{ t('giveCouponTips') }}
+
+
+
+
+
+ {{ row.title }}
+
+
+
+
+ {{ row.type_name }}
+
+
+
+
+ ¥{{ row.price }}
+
+
+
+
+ 无门槛
+ 满{{ row.min_condition_money }}元可用
+
+
+
+
+ 领取之日起{{ row.length || '' }} 天内有效
+ 使用截止时间至{{ row.valid_end_time || ''}}
+
+
+
+
+
+
+ 张
+
+
+
+
+
+
+ {{ t("delete") }}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/order/batch_delivery.vue b/niucloud/addon/shop/admin/views/order/batch_delivery.vue
new file mode 100644
index 000000000..1ab9ab207
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/order/batch_delivery.vue
@@ -0,0 +1,187 @@
+
+
+
+
+ {{ pageName }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+ {{ item.username }}
+
+
+
+
+
+ {{ t('search') }}
+ {{ t('reset') }}
+ {{ t('importData') }}
+
+
+
+
+
+
+
+ {{ !importFileTableData.loading ? t('emptyData') : '' }}
+
+
+
+
+
+ {{ row?.user?.username }}
+
+
+
+
+
+
+
+
+
+ {{ row.create_time || '' }}
+
+
+
+
+ {{ t('downloadRecord') }}
+ {{ t('causeFailure') }}
+ {{ t('checkCause') }}
+
+
+
+
+
+
+
+
+
+
+ {{ causeFailureContent }}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/order/components/adjust-money.vue b/niucloud/addon/shop/admin/views/order/components/adjust-money.vue
new file mode 100644
index 000000000..76aeecb6d
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/order/components/adjust-money.vue
@@ -0,0 +1,169 @@
+
+
+
+
{{ t('adjustMoneyTips') }}
+
+
+
+ {{ t('adjustMoneyUnit') }}
+
+
+
+
+
+
+
+ {{ row.goods_name }}
+
+
+
+
+
+
+
+
+
+ {{ t('adjustMoneyLabel') }}
+
+
+
+
+
+
+
+ {{ t('adjustMoneyUnit') }}
+
+
+
+
+
+
+
+
+ 实际商品金额
+ = 商品总额 - 优惠金额 + 调价
+
+
+ 订单总额
+ = 实际商品金额 + 运费
+ = 实际商品金额
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/order/components/delivery-action.vue b/niucloud/addon/shop/admin/views/order/components/delivery-action.vue
new file mode 100644
index 000000000..cafbe98cf
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/order/components/delivery-action.vue
@@ -0,0 +1,366 @@
+
+
+
+
+
+
+ 您已开通微信小程序发货信息管理服务,平台会将发货信息以消息的形式推送给购买的微信用户。
+ 注意:每个订单只能更新一次发货信息,请谨慎操作!
+
+
+
+
+
+ {{ item }}
+
+
+
+
+
+ {{ t('manualWriteWay') }}
+ {{ t('electronicSheetWay') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
![]()
+
![]()
+
+
+ {{row.goods_name}}
+ {{row.sku_name}}
+ 赠品
+
+
+
+
+
+
+
+
+
+ {{ row.delivery_info?.express_company_name }}
+
+
+
+
+ {{ row.delivery_info?.express_number }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/order/components/delivery-package.vue b/niucloud/addon/shop/admin/views/order/components/delivery-package.vue
new file mode 100644
index 000000000..38f0ab72d
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/order/components/delivery-package.vue
@@ -0,0 +1,135 @@
+
+
+
+
{{ t('deliveryInfo') }}
+
+
+ {{ t('devliveryTime') }}:{{ packageData.create_time }}
+
+
+
+
+ {{ t('companyName') }}:{{ packageData.company.company_name }}
+
+
+ {{ t('logisticNo') }}:{{ packageData.express_number }}
+
+
+
{{ t('goodsInfo') }}
+
+
+
+
+
+
+
![]()
+
+
+
{{ row.goods_name }}
+
{{ row.sku_name }}
+
+
+
+
+
+
+
+
+
{{ t('logisticInfo') }}
+
+
+
+
+ {{ item.datetime }}{{ item.remark }}
+
+
+
{{ packageData.traces.reason }}
+
+
+
{{ t('notLogistics') }}
+
+
+
{{ t('noLogisticsRequired') }}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/order/components/electronic-sheet-print.vue b/niucloud/addon/shop/admin/views/order/components/electronic-sheet-print.vue
new file mode 100644
index 000000000..55f5f2f7a
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/order/components/electronic-sheet-print.vue
@@ -0,0 +1,439 @@
+
+
+
+
+
+ 注意事项:
+ * 配送方式为物流配送的订单支持打印电子面单
+ * 无需物流、虚拟发货不支持打印电子面单
+ * 请对应物流公司选择面单模板
+ * 批量打印时,只能选择一种面单模板
+ * 单个打印时,如果有多个包裹,会展示商品信息,支持多包裹打印电子面单
+ * 多包裹打印时,请不要重复选择面单模板
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ packageList[currentPackageIndex].company.company_name }}
+
+
+
+ {{ packageList[currentPackageIndex].express_number }}
+
+
+
+
+
+
+
+
![]()
+
+
+
{{ row.goods_name }}
+
{{ row.sku_name }}
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('electronicSheetPrintResult') }}
+
+
+
+
+ {{ row.delivery_id }}
+
+
+
+
+ {{ row.success ? '成功' : '失败' }}
+
+
+
+
+ {{ row.result_code }}
+
+
+
+
+ {{ row.reason }}
+
+
+
+
+ {{ t('electronicSheetPrintOperation') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ row.success ? '成功' : '失败' }}
+
+
+
+
+ {{ row.result_code }}
+
+
+
+
+ {{ row.reason }}
+
+
+
+
+ {{ t('electronicSheetPrintOperation') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/order/components/form-detail.vue b/niucloud/addon/shop/admin/views/order/components/form-detail.vue
new file mode 100644
index 000000000..0abb5dc4e
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/order/components/form-detail.vue
@@ -0,0 +1,54 @@
+
+
+
+
+ 暂无表单数据
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/order/components/import-data.vue b/niucloud/addon/shop/admin/views/order/components/import-data.vue
new file mode 100644
index 000000000..bcf50b07b
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/order/components/import-data.vue
@@ -0,0 +1,93 @@
+
+
+
+
+
+
+ {{t('fullOrderDelivery')}}
+ {{t('openOrderDelivery')}}
+
+ {{t('orderTemplate')}}
+ {{ t('orderGoodsTemplate') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/order/components/invoice-detail.vue b/niucloud/addon/shop/admin/views/order/components/invoice-detail.vue
new file mode 100644
index 000000000..10f3f7272
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/order/components/invoice-detail.vue
@@ -0,0 +1,133 @@
+
+
+
+
+ {{ logData.header_name || '--' }}
+ {{ logData.header_type_name || '--' }}
+ {{ logData.name || '--' }}
+ {{ logData.invoice_number || '--' }}
+ {{ logData.type_name || '--' }}
+ {{ logData.tax_number || '--'}}
+ {{ logData.money || '--' }}
+ {{ logData.invoice_time === 0 ? '--' : logData.invoice_time }}
+
+
+
+
+
+
+
+
+
+
+ {{ logData.bank_name || '--' }}
+ {{ logData.bank_card_number || '--' }}
+ {{ logData.address || '--' }}
+ {{ logData.telephone || '--' }}
+
+
+ {{ logData.create_time || '--' }}
+ {{ logData.remark || '--' }}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/order/components/invoice-dialog.vue b/niucloud/addon/shop/admin/views/order/components/invoice-dialog.vue
new file mode 100644
index 000000000..44347bf84
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/order/components/invoice-dialog.vue
@@ -0,0 +1,82 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/order/components/open-invoice.vue b/niucloud/addon/shop/admin/views/order/components/open-invoice.vue
new file mode 100644
index 000000000..0245d0156
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/order/components/open-invoice.vue
@@ -0,0 +1,225 @@
+
+
+
+
+
+
+
+
+ {{ t('个人') }}
+ {{ t('企业') }}
+
+
+
+
+ {{ t('普票') }}
+ {{ t('专票') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/order/components/order-detail.vue b/niucloud/addon/shop/admin/views/order/components/order-detail.vue
new file mode 100644
index 000000000..325c349e1
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/order/components/order-detail.vue
@@ -0,0 +1,418 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ formData.order_no }}
+
+
+ {{ formData.order_from_name }}
+
+
+ {{ formData.out_trade_no }}
+
+
+ {{ formData.pay.type_name }}
+
+
+
+
+ {{ formData.delivery_type_name }}
+
+
+
+ {{ formData.taker_name }}
+
+
+ {{ formData.taker_mobile }}
+
+
+ {{ formData.taker_full_address }}
+
+
+
+
+ {{ formData.store.store_name }}
+
+
+ {{ formData.store.full_address }}
+
+
+ {{ formData.store.store_mobile }}
+
+
+ {{ formData.store.trade_time }}
+
+
+
+
+
+ {{ formData.member_remark ?? '--' }}
+
+
+ {{ formData.shop_remark ?? '--' }}
+
+
+
+
+
+
+
+ {{ t('orderStatus') }}:
+ {{ formData.status_name.name }}
+
+
+
{{ t('notes') }}
+
{{ t('delivery') }}
+
{{ t('close') }}
+
{{ t('editPrice') }}
+
{{ t('finish') }}
+
{{ t('electronicSheetPrintTitle') }}
+
{{ t('printTicket') }}
+
{{ t('editAddress') }}
+
{{ t('voluntaryRefund') }}
+
+
+ {{ t('package') }}{{ index + 1 }}
+ {{ t('noLogisticsRequired') }}
+
+
+
+
+
{{ t('remind') }}:
+
+
{{ t('remindTips1') }}
+
{{ t('remindTips2') }}
+
{{ t('remindTips3') }}
+
+
+
+
+
+
+
+
+
+
+
![]()
+
+
+
{{ row.goods_name }}
+
{{ row.sku_name }}
+
赠品
+
+
+
+
+
+
+
+ {{ row.extend.point }}{{ t('point') }}
+ +¥{{ row.price }}
+
+ ¥{{ row.price }}
+
+ {{row.num }}{{ t('piece') }}(第1{{ t('piece') }},¥{{ parseFloat(row.extend.newcomer_price).toFixed(2) }}/{{ t('piece') }};第{{ row.num > 2 ? '2~' + row.num : '2' }}{{ t('piece') }},¥{{ parseFloat(row.price).toFixed(2) }}/{{ t('piece') }})
+ {{ row.num }}{{ t('piece') }}
+
+ {{ row.num }}{{ t('piece') }}
+
+
+
+
+
+
+
+
+
{{ t('orderDetailGoodsMoney') }}
+
+ {{ formData.point }}{{ t('point') }}
+ +¥{{ formData.goods_money }}
+
+ ¥{{ formData.goods_money }}
+
+
+
+
{{ t('couponMoney') }}
+
{{ formData.coupon_money }}
+
+
+
{{ t('manjianDiscountMoney') }}
+
{{ formData.manjian_discount_money }}
+
+
+
{{ t('discountMoney') }}
+
{{ formData.discount_money }}
+
+
+
{{ t('orderDetailDeliveryMoney') }}
+
{{ formData.delivery_money }}
+
+
+
{{ t('detailOrderMoney') }}
+
+ {{ formData.point }}{{ t('point') }}
+ +¥{{ formData.order_money }}
+
+ ¥{{ formData.order_money }}
+
+
+
+
+
+
+
+
+
+
{{ items.create_time && items.create_time.split(' ')[0] }}
+
{{ items.create_time && items.create_time.split(' ')[1] }}
+
+
+
+
{{ items.main_type_name }}{{ items.main_name }}
+
+ {{ items.type_name }}
+ {{ items.content }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/order/components/order-edit-address.vue b/niucloud/addon/shop/admin/views/order/components/order-edit-address.vue
new file mode 100644
index 000000000..0d4b2b5d3
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/order/components/order-edit-address.vue
@@ -0,0 +1,549 @@
+
+
+
+
+
+
+ {{ item.name }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ mapMessage }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/order/components/order-export-select.vue b/niucloud/addon/shop/admin/views/order/components/order-export-select.vue
new file mode 100644
index 000000000..b6a7ac538
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/order/components/order-export-select.vue
@@ -0,0 +1,61 @@
+
+
+
+
+
+ {{ t('shopOrder') }}
+ {{ t('shopOrderGoods') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/order/components/order-notes.vue b/niucloud/addon/shop/admin/views/order/components/order-notes.vue
new file mode 100644
index 000000000..923bfc7ad
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/order/components/order-notes.vue
@@ -0,0 +1,93 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/order/components/refund-detail.vue b/niucloud/addon/shop/admin/views/order/components/refund-detail.vue
new file mode 100644
index 000000000..37ca84441
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/order/components/refund-detail.vue
@@ -0,0 +1,540 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ formData.order_main.order_no }}
+
+
+ {{ formData.order_main.order_from_name }}
+
+
+ {{ formData.order_main.out_trade_no }}
+
+
+ {{ formData.pay_refund.type_name }}
+
+
+
+
+ {{ formData.order_main.delivery_type_name }}
+
+
+
+ {{ formData.order_main.taker_name || '--' }}
+
+
+ {{ formData.order_main.taker_mobile || '--' }}
+
+
+ {{ formData.order_main.taker_full_address|| '--' }}
+
+
+
+
+ {{ formData.store.store_name || '--' }}
+
+
+ {{ formData.store.full_address|| '--' }}
+
+
+ {{ formData.store.store_mobile || '--' }}
+
+
+ {{ formData.store.trade_time || '--' }}
+
+
+
+
+
+ {{ formData.order_main.member_remark || '--' }}
+
+
+ {{ formData.order_main.shop_remark || '--' }}
+
+
+
+
+
+
{{ t('afterSales') }}
+
+
+
+
+ {{ formData.order_refund_no }}
+
+
+ {{ formData.refund_type_name }}
+
+
+ {{ formData.create_time }}
+
+
+
+
+ ¥{{ formData.money }}
+ ¥{{ formData.apply_money }}
+
+
+ {{ formData.reason }}
+
+
+
+
+
+
+
+
+
+ {{ formData.remark || '--' }}
+
+
+
+
+
买家退货信息
+
+
+
+
+ {{ formData.delivery.express_company }}
+
+
+
+
+ {{ formData.delivery.express_number }}
+
+
+
+
+ {{ formData.delivery.remark }}
+
+
+
+
+
{{ t('refundStatus') }}
+
+
+ {{ t('refundStatus') }}:
+ {{ formData.status_name }}
+
+
+
{{ t('refuseReason') }}:
+
{{ formData.shop_reason }}
+
+
+ {{ t('agree') }}
+ {{ t('refuse') }}
+ {{ t('confirmDelivery') }}
+ {{ t('refuse') }}
+ {{ t('transferAccounts') }}
+ {{ t('closeRefund') }}
+
+
+
{{ t('remind') }}:
+
+
{{ t('remindTips1') }}
+
{{ t('remindTips2') }}
+
{{ t('remindTips3') }}
+
+
+
+
+
+
+
+
+
+
+
![]()
+
+
+ {{ row.goods_name }}
+ {{ row.sku_name }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ items.create_time.split(' ')[0] }}
+
+
+ {{ items.create_time.split(' ')[1] }}
+
+
+
+
+
+ {{ items.main_type_name }}{{ items.main_name }}
+
+
+ {{ items.type_name }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ¥{{ refuseFormData.apply_money }}
+
+
+
+
+
+ 当前订单需退还{{ formData.gift_balance}}元赠品余额。若用户余额不足,则默认不进行扣除。请联系客户确认退款金额。
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/order/components/shop-active-refund.vue b/niucloud/addon/shop/admin/views/order/components/shop-active-refund.vue
new file mode 100644
index 000000000..908e2ab44
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/order/components/shop-active-refund.vue
@@ -0,0 +1,230 @@
+
+
+
+
+
+ 商家主动退款功能仅作为退款售后业务的补充功能,请勿过度依赖和使用。此功能支持多次退款操作。
+ 如果订单项全部退款,运费将在最后一次退款时一并退还,同时使用的优惠券也将返还给用户,退款金额将原路返还至用户的支付账户。
+
+
+
+
+
+ ¥{{ formData.refund_money }}
+ (运费:¥{{formData.delivery_money}})
+
+
+
+
+
+
+
+
+
+
![]()
+
![]()
+
+
+
+
+ {{row.goods_name}}
+
+ {{ row.goods_name }}
+
+
{{ row.sku_name }}
+
赠品
+
+
+
+
+
+
+
+ ¥{{ (row.refund_money).toFixed(2) }}
+
+
+
+
+
+
+ ¥{{ row.price }}
+
+
+
+
+
+
+ {{ row.num }}{{ t('piece') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/order/config.vue b/niucloud/addon/shop/admin/views/order/config.vue
new file mode 100644
index 000000000..e873134a3
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/order/config.vue
@@ -0,0 +1,320 @@
+
+
+
+
+ {{ pageName }}
+
+
+
+
+
+
{{ t('closeOrderInfo') }}
+
+
+
+
+
+
+
+ {{ t('closeOrderInfoLeft') }}
+
+ {{ t('closeOrderInfoRight') }}
+
+
{{ t('closeOrderInfoBottom') }}
+
+
+
+
+
+
{{ t('confirm') }}
+
+
+
+
+
+
+
+ {{ t('confirmLeft') }}
+
+ {{ t('confirmRight') }}
+
+
{{ t('confirmBottom') }}
+
+
+
+
+
+
{{ t('refund') }}
+
+
+
+
+
+
+
+ {{ t('refundLeft') }}
+
+ {{ t('refundRight') }}
+
+
{{ t('refundBottom') }}
+
+
+
+
+
+ {{ t('diyForm') }}
+
+
+
+
+
+ {{ t('refresh') }}
+ {{ t('addDiyForm') }}
+
+
+
+
+ {{ t('evaluate') }}
+
+ {{ t('isEvaluate') }}
+
+ {{ t('isEvaluateOpen') }}
+ {{ t('isEvaluateClose') }}
+
+
+
+ {{ t('evaluateIsToExamine') }}
+
+ {{ t('isEvaluateOpen') }}
+ {{ t('isEvaluateClose') }}
+
+
+
+ {{ t('evaluateIsShow') }}
+
+ {{ t('isEvaluateOpen') }}
+ {{ t('isEvaluateClose') }}
+
+
+
+
+ {{ t('invoice') }}
+
+ {{ t('isInvoice') }}
+
+ {{ t('isInvoiceClose') }}
+ {{ t('isInvoiceOpen') }}
+
+
+
+
+
{{ t('invoiceContent') }}
+
+
{{ t('insert') }}
+
+
+
+ {{ t('invoiceType') }}
+
+ {{ t('electronicInvoice') }}
+ {{ t('paperInvoice') }}
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/order/detail.vue b/niucloud/addon/shop/admin/views/order/detail.vue
new file mode 100644
index 000000000..5935ce1ed
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/order/detail.vue
@@ -0,0 +1,519 @@
+
+
+
+
+
+
+
+
+ {{ t('orderInfo') }}
+
+
+
+ {{ formData.order_no }}
+
+
+ {{ formData.order_from_name }}
+
+
+ {{ formData.out_trade_no }}
+
+
+
+ {{ formData.pay.type_name }}
+
+
+
+
+ {{ formData.member.nickname }}
+
+
+
+
+ {{ formData.taker_name || '--' }}
+
+
+ {{ formData.taker_mobile || '--' }}
+
+
+ {{ formData.verify_code || '--' }}
+
+
+ {{ formData.verifier_member.nickname }}
+
+
+
+
+
+ {{ formData.pay.pay_type_name }}, 帮付人:
+ {{ formData.pay.pay_member }}
+
+
+
+
+
+ {{ formData.delivery_type_name }} ({{ formData.order_delivery[0].third_delivery_name }})
+
+
+
+ {{ formData.taker_name || '--' }}
+
+
+ {{ formData.taker_mobile || '--' }}
+
+
+ {{ formData.taker_full_address || '--' }}
+
+
+
+
+ {{ formData.buyer_ask_delivery_time }}
+
+
+
+
+ {{ formData.store.store_name || '--' }}
+
+
+ {{ formData.store.full_address || '--' }}
+
+
+ {{ formData.store.store_mobile || '--' }}
+
+
+ {{ formData.store.trade_time }}
+
+
+ {{ formData.buyer_ask_delivery_time }}
+
+
+
+
+
+ {{ formData.member_remark ?? '--' }}
+
+
+ {{ formData.shop_remark ?? '--' }}
+
+
+ {{formData.activity_type=='giftcard'?'礼品卡':formData.activity_type=='exchange'?'积分商城':formData.activity_type=='discount'?'限时折扣':formData.activity_type=='seckill'?'秒杀':formData.activity_type=='pintuan'?'拼团':formData.activity_type=='newcomer_discount'?'新人专享':formData.activity_type=='manjiansong'?'满减送':'商品'}}
+
+
+
+ {{ t('deliveryTransporterInfo') }}
+
+
+
+ {{ formData.order_delivery[0].third_delivery_name}}
+
+
+
+
+ {{ formData.order_delivery[0].third_delivery_info.transporter_name }}
+
+
+
+
+ {{ formData.order_delivery[0].third_delivery_info.transporter_phone }}
+
+
+
+
+ {{ formData.order_delivery[0].third_delivery_info.status_name }}
+
+
+
+ {{ t('orderStatus') }}
+
+
+ {{ t('orderStatus') }}:
+ {{ formData.status_name.name }}
+
+
+
{{ t('notes') }}
+
{{ t('delivery') }}
+
{{ t('close') }}
+
{{ t('editPrice') }}
+
{{ t('finish') }}
+
{{ t('electronicSheetPrintTitle') }}
+
{{ t('printTicket') }}
+
{{ t('editAddress') }}
+
{{ t('voluntaryRefund') }}
+
+
+ {{ t('package') }}{{ index + 1 }}
+ {{ t('noLogisticsRequired') }}
+
+
+
+
+
{{ t('remind') }}:
+
+
{{ t('remindTips1') }}
+
{{ t('remindTips2') }}
+
{{ t('remindTips3') }}
+
+
+
+ {{ t('formDetail') }}
+
+
+ {{ t('goodsDetail') }}
+
+
+
+
+
+
![]()
+
+
+
{{ row.goods_name }}
+
{{ row.sku_name }}
+
赠品
+
顺手买
+
+
+
+
+
+
+
+ {{ row.extend.point }}{{ t('point') }}
+ +¥{{ row.price }}
+
+ ¥{{ parseFloat(row.impulse_buy_info.impulse_buy_price).toFixed(2) }}
+ ¥{{ row.price }}
+
+ {{ row.impulse_buy_info.show_tips }}
+
+
+ {{ row.num }}{{ t('piece') }}(第1{{ t('piece') }},¥{{ parseFloat(row.extend.newcomer_price).toFixed(2) }}/{{ t('piece') }};第{{ row.num > 2 ? '2~' + row.num : '2' }}{{ t('piece') }},¥{{ parseFloat(row.price).toFixed(2) }}/{{ t('piece') }})
+ {{ row.num }}{{ t('piece') }}
+
+ {{ row.num }}{{ t('piece') }}
+
+
+
+
+
+
+ {{ t('formDetail') }}
+
+
+
+
+
+
+
{{ t('goodsMoney') }}
+
+ {{ formData.point }}{{ t('point') }}
+ +¥{{ formData.goods_money }}
+
+ ¥{{ formData.goods_money }}
+
+
+
+
{{ t('couponMoney') }}
+
{{ formData.coupon_money }}
+
+
+
{{ t('manjianDiscountMoney') }}
+
{{ formData.manjian_discount_money }}
+
+
+
{{ t('discountMoney') }}
+
{{ formData.discount_money }}
+
+
+
{{ t('deliveryMoney') }}
+
{{ formData.delivery_money }}
+
+
+
{{ t('orderMoney') }}
+
+ {{ formData.point }}{{ t('point') }}
+ +¥{{ formData.order_money }}
+
+ ¥{{ formData.order_money }}
+
+
+
+
+ {{ t('operateLog') }}
+
+
+
+
{{ items.create_time && items.create_time.split(' ')[0] }}
+
{{ items.create_time && items.create_time.split(' ')[1] }}
+
+
+
+
{{ items.main_type_name }}{{ items.main_name }}
+
+ {{ items.type_name }}
+ {{ items.content }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/order/invoice.vue b/niucloud/addon/shop/admin/views/order/invoice.vue
new file mode 100644
index 000000000..475dac914
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/order/invoice.vue
@@ -0,0 +1,307 @@
+
+
+
+
+
{{ pageName }}
+
+ {{ t('添加发票') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('search') }}
+ {{ t('reset') }}
+ {{ t('export') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t("批量审核") }}
+
+
+
+ {{ !invoiceManagementTableData.loading ? t('emptyData') : '' }}
+
+
+
+
+
+
+
+
+
+ {{ row.create_time || '' }}
+
+
+
+
+ {{ row.invoice_time || '' }}
+
+
+
+
+ {{ row.invoice_type_name}}
+
+
+
+
+ {{ t('detail') }}
+ {{ t('invoice') }}
+ {{ t('审核') }}
+ {{ t('viewOrder') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/order/list.vue b/niucloud/addon/shop/admin/views/order/list.vue
new file mode 100644
index 000000000..e373d78b1
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/order/list.vue
@@ -0,0 +1,704 @@
+
+
+
+
+
+ {{ pageName }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('search') }}
+ {{ t('reset') }}
+ {{ t('export') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('batchPrintElectronicSheet') }}
+
+
+ {{ t('批量删除') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('orderNo') }}:{{ (item as any).order_no }}
+ {{ t('createTime') }}:{{ (item as any).create_time }}
+
+ {{ t('payType') }}:{{ (item as any).pay.type_name }}
+ {{ t('营销') }}:{{ (item as any).activity_type_name }}
+ {{ t('buyerAskDeliveryTime') }}::{{ (item as any).buyer_ask_delivery_time }}
+
+
+
+ {{ t('printTicket') }}
+ {{ t('electronicSheetPrintTitle') }}
+ {{ t('info') }}
+ {{ t('notes') }}
+
+
+
+
+
+
+
+
+
+
![]()
+
![]()
+
+
+
+
+ {{ row.goods_name }}
+
+ {{ row.goods_name }}
+
+
{{ row.sku_name }}
+
赠品
+
+
+
+
+
+
+
+ {{ row.extend.point }}{{ t('point') }}+¥{{ row.price }}
+ ¥{{ parseFloat(row.impulse_buy_info.impulse_buy_price).toFixed(2) }}
+ ¥{{ row.price }}
+ {{ row.num }}{{ t('piece') }}
+
+
+
+
+
+
+ {{ row.status_name }}
+
+
+
+
+
+
+ {{ item.point }}{{ t('point') }}
+ +¥{{ item.order_money }}
+
+ ¥{{ item.order_money }}
+ {{ item.member_id !== item.pay.main_id && item.pay.status == 2 ? item.pay.pay_type_name : '' }}
+
+
+
+
+
+ {{ item.member.nickname }}
+ {{ item.taker_name }} {{ item.taker_mobile }}
+ {{ item.taker_full_address }}
+
+
+
+
+
+ {{ item.delivery_type_name }}
+
+
+
+
+ {{ item.status_name.name }}
+
+
+
+
+
+ {{ t('orderClose') }}
+ {{ t('editPrice') }}
+
+ {{ t('editAddress') }}
+ {{ t('sendOutGoods') }}
+ {{ t('修改发货') }}
+ {{ t('confirmTakeDelivery') }}
+ {{ t('voluntaryRefund') }}
+ {{ t('delete') }}
+
+
+
+
+
+ {{ t('notes') }}:
+ {{ item.shop_remark }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/order/refund.vue b/niucloud/addon/shop/admin/views/order/refund.vue
new file mode 100644
index 000000000..f15e6c057
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/order/refund.vue
@@ -0,0 +1,290 @@
+
+
+
+
+
+ {{ pageName }}
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('search') }}
+ {{ t('reset') }}
+ {{ t('export') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('orderRefundNo') }}:{{ (item as any).order_refund_no }}
+
+
+
+
+
+
+
+
+
+
![]()
+
![]()
+
+
+
+
+ {{ row.goods_name }}
+
+ {{ row.goods_name }}
+
+
{{ row.sku_name }}
+
+
+
+
+
+
+
+ ¥{{ row.goods_money }}
+
+
+
+
+
+
+ ¥{{ parseFloat(row.goods_money - row.discount_money).toFixed(2) }}
+
+
+
+
+
+ {{ item.member.nickname }}
+
+
+
+
+ ¥{{ item.money }}
+ ¥{{ item.apply_money }}
+
+
+
+
+ {{ item.refund_type_name }}
+
+
+
+
+ {{ item.create_time }}
+
+
+
+
+ {{ item.status_name }}
+
+
+
+
+ {{ t('info') }}
+
+
+
+
+ {{ t('notes') }}:
+ {{ item.shop_remark }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/poster/components/edit-goods-image.vue b/niucloud/addon/shop/admin/views/poster/components/edit-goods-image.vue
new file mode 100644
index 000000000..d8fe1eff0
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/poster/components/edit-goods-image.vue
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/poster/components/edit-goods-market-price.vue b/niucloud/addon/shop/admin/views/poster/components/edit-goods-market-price.vue
new file mode 100644
index 000000000..d8fe1eff0
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/poster/components/edit-goods-market-price.vue
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/poster/components/edit-goods-name.vue b/niucloud/addon/shop/admin/views/poster/components/edit-goods-name.vue
new file mode 100644
index 000000000..d8fe1eff0
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/poster/components/edit-goods-name.vue
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/poster/components/edit-goods-price.vue b/niucloud/addon/shop/admin/views/poster/components/edit-goods-price.vue
new file mode 100644
index 000000000..d8fe1eff0
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/poster/components/edit-goods-price.vue
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/poster/components/preview-goods-image.vue b/niucloud/addon/shop/admin/views/poster/components/preview-goods-image.vue
new file mode 100644
index 000000000..d48aab0b3
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/poster/components/preview-goods-image.vue
@@ -0,0 +1,32 @@
+
+
+

+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/poster/components/preview-goods-market-price.vue b/niucloud/addon/shop/admin/views/poster/components/preview-goods-market-price.vue
new file mode 100644
index 000000000..85d0f9ec2
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/poster/components/preview-goods-market-price.vue
@@ -0,0 +1,44 @@
+
+ ¥1999.00
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/poster/components/preview-goods-name.vue b/niucloud/addon/shop/admin/views/poster/components/preview-goods-name.vue
new file mode 100644
index 000000000..0f02a4e25
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/poster/components/preview-goods-name.vue
@@ -0,0 +1,47 @@
+
+ 商品名称
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/poster/components/preview-goods-price.vue b/niucloud/addon/shop/admin/views/poster/components/preview-goods-price.vue
new file mode 100644
index 000000000..3fbbe3a0b
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/poster/components/preview-goods-price.vue
@@ -0,0 +1,48 @@
+
+ ¥980.00
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/printer/components/preview-goods-order.vue b/niucloud/addon/shop/admin/views/printer/components/preview-goods-order.vue
new file mode 100644
index 000000000..0da9185fc
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/printer/components/preview-goods-order.vue
@@ -0,0 +1,128 @@
+
+
+
+
+
{{ data.head_info.ticket_name.value }}
+
+
+
商城名称
+
+
+
+
+
订单编号:20240713456280064905216
+
订单来源:微信小程序
+
订单状态:已完成
+
支付方式:微信支付
+
配送方式:同城配送
+
下单时间:2023-12-12 14:20:20
+
付款时间:2023-12-12 14:20:30
+
商品总额:¥10.00
+
配送金额:¥1.00
+
优惠金额:¥2.00
+
+
实付金额:¥7.00
+
商家备注:新用户优惠
+
+
+
+
+
+
可口可乐碳酸饮料
+
x2
+
¥54.50
+
+
+
+
+
+
+
账户余额:¥2000.00
+
账户积分:300
+
会员手机号:{{ data.buyer_info.buyer_mobile.value == 'yes' ? '152****5131' : '15266665131' }}
+
+
+
收货人:小张
+
联系方式:{{ data.buyer_info.taker_mobile.value == 'yes' ? '152****5131' : '15266665131' }}
+
收货地址:山西省太原市小店区创业街27号时代广场大厦
+
买家备注:微辣,多放孜然,谢谢!
+
+
+
+
+
![]()
+
+
打印时间:2024年7月13日 17:48:39
+
{{ data.bottom_info.bottom_remark.value }}
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/sow_community/components/sow-community-gift-coupon.vue b/niucloud/addon/shop/admin/views/sow_community/components/sow-community-gift-coupon.vue
new file mode 100644
index 000000000..99978832f
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/sow_community/components/sow-community-gift-coupon.vue
@@ -0,0 +1,187 @@
+
+
+
+
+
+ {{ t('giveCouponTips') }}
+
+
+
+
+
+ {{ row.title }}
+
+
+
+
+ {{ row.type_name }}
+
+
+
+
+ ¥{{ row.price }}
+
+
+
+
+ 无门槛
+ 满{{ row.min_condition_money }}元可用
+
+
+
+
+ 领取之日起{{ row.length || '' }} 天内有效
+ 使用截止时间至{{ row.valid_end_time || ''}}
+
+
+
+
+
+
+ 张
+
+
+
+
+
+
+ {{ t("delete") }}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/stat/goods.vue b/niucloud/addon/shop/admin/views/stat/goods.vue
new file mode 100644
index 000000000..8d8d6219d
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/stat/goods.vue
@@ -0,0 +1,564 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('search') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('goodsAccessNum') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('goodsVisitCount') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('cartNum') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('saleNum') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('payNum') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('payMoney') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('refundMoney') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('refundNum') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('search') }}
+ {{ t('reset') }}
+
+
+
+
+
+
+
+ {{ !goodsData.loading ? t('emptyData') : '' }}
+
+
+
+
+
+
+
+
+

+
+
+
+

+
+
+ {{ row.goods_name }}
+ 赠品
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/stat/index.vue b/niucloud/addon/shop/admin/views/stat/index.vue
new file mode 100644
index 000000000..7d4a73cc0
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/stat/index.vue
@@ -0,0 +1,251 @@
+
+
+
+
+ 今日
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 自定义时间选择
+
+
+ 选择时间:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/stat/member.vue b/niucloud/addon/shop/admin/views/stat/member.vue
new file mode 100644
index 000000000..52a651e4b
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/stat/member.vue
@@ -0,0 +1,193 @@
+
+
+
+
+ 今日
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 自定义时间选择
+
+
+ 选择时间:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/stat/order.vue b/niucloud/addon/shop/admin/views/stat/order.vue
new file mode 100644
index 000000000..a6935d38e
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/stat/order.vue
@@ -0,0 +1,302 @@
+
+
+
+
+ 今日
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 自定义时间选择
+
+
+ 选择时间:
+
+
+
+
+
+
+
+
+
+
+
+
+
=
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/admin/views/stat/visit.vue b/niucloud/addon/shop/admin/views/stat/visit.vue
new file mode 100644
index 000000000..773378f70
--- /dev/null
+++ b/niucloud/addon/shop/admin/views/stat/visit.vue
@@ -0,0 +1,254 @@
+
+
+
+
+ 今日
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 自定义时间选择
+
+
+ 选择时间:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/app/adminapi/controller/Stat.php b/niucloud/addon/shop/app/adminapi/controller/Stat.php
new file mode 100644
index 000000000..2b4241550
--- /dev/null
+++ b/niucloud/addon/shop/app/adminapi/controller/Stat.php
@@ -0,0 +1,93 @@
+getStat());
+ }
+
+ /**
+ * 今日
+ * @description 查看统计数据-今日
+ * @return void
+ */
+ public function today() {
+ return success(data: (new StatService())->getStat(date('Y-m-d', time())) );
+ }
+
+ /**
+ * 昨日
+ * @description 查看统计数据-昨日
+ * @return void
+ */
+ public function yesterday() {
+ $yesterday = Carbon::yesterday();
+ return success(data: (new StatService())->getStat(date('Y-m-d', $yesterday->getTimestamp())) );
+ }
+
+ /**
+ * 获取阶段统计数据
+ * @description 查看统计数据-阶段统计数据
+ * @return \think\Response
+ */
+ public function stat() {
+ $data = $this->request->params([
+ ['start_date', date('Y-m-d', strtotime('-6 day')) ],
+ ['end_date', date('Y-m-d', strtotime('+1 day'))]
+ ]);
+ return success(data: (new StatService())->getStatData($data['start_date'], $data['end_date']));
+ }
+
+ /**
+ * 获取统计数据按时段
+ * @description 查看统计数据-统计数据按时段
+ * @return \think\Response
+ */
+ public function hourStat() {
+ $data = $this->request->params([
+ ['date', date('Y-m-d', time()) ],
+ ]);
+ return success(data: (new StatService())->getHourStatData($data['date']));
+ }
+
+ /**
+ * 订单统计
+ * @description 查看统计数据-订单
+ * @return \think\Response
+ */
+ public function order() {
+ return success(data: (new OrderService())->getOrderCount());
+ }
+
+ /**
+ * @description 查看统计数据-商品
+ * @return \think\Response
+ * @throws \think\db\exception\DbException
+ */
+ public function goods()
+ {
+ return success(data: (new GoodsService())->getGoodsCount());
+ }
+}
diff --git a/niucloud/addon/shop/app/adminapi/controller/delivery/Company.php b/niucloud/addon/shop/app/adminapi/controller/delivery/Company.php
new file mode 100644
index 000000000..0dff1acb7
--- /dev/null
+++ b/niucloud/addon/shop/app/adminapi/controller/delivery/Company.php
@@ -0,0 +1,126 @@
+request->params([
+ [ "company_name", "" ],
+ [ 'electronic_sheet_switch', '' ]
+ ]);
+ return success(( new CompanyService() )->getPage($data));
+ }
+
+ /**
+ * 获取物流公司列表
+ * @description 查看物流公司列表-全部
+ * @return \think\Response
+ */
+ public function lists()
+ {
+ $data = $this->request->params([
+ [ "company_name", "" ],
+ [ 'electronic_sheet_switch', '' ]
+ ]);
+ return success(( new CompanyService() )->getList($data));
+ }
+
+ /**
+ * 物流公司详情
+ * @description 查看详情
+ * @param int $id
+ * @return \think\Response
+ */
+ public function info(int $id)
+ {
+ return success(( new CompanyService() )->getInfo($id));
+ }
+
+ /**
+ * 添加物流公司
+ * @description 添加
+ * @return \think\Response
+ */
+ public function add()
+ {
+ $data = $this->request->params([
+ [ "company_name", "" ],
+ [ "logo", "" ],
+ [ "url", "" ],
+ [ "express_no", "" ], // 物流公司编号(用于物流跟踪)
+ [ 'express_no_electronic_sheet', '' ], //快递鸟 物流公司编号(用于电子面单)
+ [ 'electronic_sheet_switch', 0 ], //快递鸟 是否支持电子面单(0:不支持,1:支持)
+ [ 'print_style', '' ], // 电子面单打印模板样式,template_size为空表示默认,json字符串,格式:[{"template_name":"二联150 100*150","template_size":""},{"template_name":"二联180 100*180","template_size":"180"}]
+ [ 'exp_type', '' ], // 物流公司业务类型,json字符串,格式:[{"value":1,"text":"特快专递"},{"value":8,"text":"代收到付"},{"value":9,"text":"快递包裹"}]
+ [ "kd100_express_no", "" ], // 快递100 物流公司编号(用于物流跟踪)
+ [ 'kd100_express_no_electronic_sheet', '' ], // 快递100 物流公司编号(用于电子面单)
+ ]);
+ $this->validate($data, 'addon\shop\app\validate\delivery\Company.add');
+ $id = ( new CompanyService() )->add($data);
+ return success('ADD_SUCCESS', [ 'id' => $id ]);
+ }
+
+ /**
+ * 物流公司编辑
+ * @description 编辑
+ * @param int $id 物流公司id
+ * @return \think\Response
+ */
+ public function edit($id)
+ {
+ $data = $this->request->params([
+ [ "company_name", "" ],
+ [ "logo", "" ],
+ [ "url", "" ],
+ [ "express_no", "" ], // 物流公司编号(用于物流跟踪)
+ [ 'express_no_electronic_sheet', '' ], //快递鸟 物流公司编号(用于电子面单)
+ [ 'electronic_sheet_switch', 0 ], //快递鸟 是否支持电子面单(0:不支持,1:支持)
+ [ 'print_style', '' ], // 电子面单打印模板样式,template_size为空表示默认,json字符串,格式:[{"template_name":"二联150 100*150","template_size":""},{"template_name":"二联180 100*180","template_size":"180"}]
+ [ 'exp_type', '' ], // 物流公司业务类型,json字符串,格式:[{"value":1,"text":"特快专递"},{"value":8,"text":"代收到付"},{"value":9,"text":"快递包裹"}]
+ [ "kd100_express_no", "" ], // 快递100 物流公司编号(用于物流跟踪)
+ [ 'kd100_express_no_electronic_sheet', '' ], // 快递100 物流公司编号(用于电子面单)
+ ]);
+ $this->validate($data, 'addon\shop\app\validate\delivery\Company.edit');
+ ( new CompanyService() )->edit($id, $data);
+ return success('EDIT_SUCCESS');
+ }
+
+ /**
+ * 物流公司删除
+ * @description 删除
+ * @param int $id 物流公司id
+ * @return \think\Response
+ */
+ public function del(int $id)
+ {
+ ( new CompanyService() )->del($id);
+ return success('DELETE_SUCCESS');
+ }
+
+}
diff --git a/niucloud/addon/shop/app/adminapi/controller/delivery/Delivery.php b/niucloud/addon/shop/app/adminapi/controller/delivery/Delivery.php
new file mode 100644
index 000000000..9d587cac0
--- /dev/null
+++ b/niucloud/addon/shop/app/adminapi/controller/delivery/Delivery.php
@@ -0,0 +1,129 @@
+request->params([
+ [ "value", "" ],
+ ]);
+
+ ( new DeliveryService() )->setConfig($data[ 'value' ]);
+ return success('SUCCESS');
+ }
+
+ /**
+ * 配送页信息
+ * @description 获取配送页信息
+ * @return void
+ */
+ public function getDelivery()
+ {
+ return success(( new DeliveryService() )->getDeliveryList());
+ }
+
+ /**
+ * 配送页信息
+ * @description 获取配送页信息配置
+ * @return void
+ */
+ public function getDeliveryList()
+ {
+ return success(( new DeliveryService() )->getDeliveryConfigList());
+ }
+
+ /**
+ * 获取配送员列表
+ * @description 查看配送员列表
+ * @return \think\Response
+ */
+ public function lists()
+ {
+ $data = $this->request->params([
+ [ "deliver_name", "" ],
+ [ "deliver_mobile", "" ]
+ ]);
+ return success(( new DeliverService() )->getPage($data));
+ }
+
+ /**
+ * 配送员详情
+ * @description 查看配送员详情
+ * @param int $id
+ * @return \think\Response
+ */
+ public function info(int $id)
+ {
+ return success(( new DeliverService() )->getInfo($id));
+ }
+
+ /**
+ * 添加配送员
+ * @description 添加配送员
+ * @return \think\Response
+ */
+ public function add()
+ {
+ $data = $this->request->params([
+ [ "deliver_name", "" ],
+ [ "deliver_mobile", "" ],
+ ]);
+ $id = ( new DeliverService() )->add($data);
+ return success('ADD_SUCCESS', [ 'id' => $id ]);
+ }
+
+ /**
+ * 配送员编辑
+ * @description 编辑配送员
+ * @param $id 自提门店id
+ * @return \think\Response
+ */
+ public function edit($id)
+ {
+ $data = $this->request->params([
+ [ "deliver_name", "" ],
+ [ "deliver_mobile", "" ],
+ ]);
+ ( new DeliverService() )->edit($id, $data);
+ return success('EDIT_SUCCESS');
+ }
+
+ /**
+ * 配送员删除
+ * @description 删除配送员
+ * @param $id
+ * @return \think\Response
+ */
+ public function del(int $id)
+ {
+ ( new DeliverService() )->del($id);
+ return success('DELETE_SUCCESS');
+ }
+}
diff --git a/niucloud/addon/shop/app/adminapi/controller/delivery/DeliverySearch.php b/niucloud/addon/shop/app/adminapi/controller/delivery/DeliverySearch.php
new file mode 100644
index 000000000..1d35e0c1a
--- /dev/null
+++ b/niucloud/addon/shop/app/adminapi/controller/delivery/DeliverySearch.php
@@ -0,0 +1,53 @@
+request->params([
+ [ "interface_type", 1 ],
+ [ "kdniao_id", "" ],
+ [ "kdniao_app_key", "" ],
+ [ "kdniao_is_pay", 1 ],
+ [ "kd100_app_key", "" ],
+ [ "kd100_customer", "" ],
+ ]);
+ ( new DeliverySearchConfigService() )->setConfig($data);
+ return success('SUCCESS');
+ }
+
+ /**
+ * 获取配置
+ * @description 查看物流查询配置
+ * @return \think\Response
+ */
+ public function getConfig()
+ {
+ return success(( new DeliverySearchConfigService() )->getConfig());
+ }
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/app/adminapi/controller/delivery/ElectronicSheet.php b/niucloud/addon/shop/app/adminapi/controller/delivery/ElectronicSheet.php
new file mode 100644
index 000000000..b4b5d4aa1
--- /dev/null
+++ b/niucloud/addon/shop/app/adminapi/controller/delivery/ElectronicSheet.php
@@ -0,0 +1,212 @@
+request->params([
+ [ "template_name", "" ],
+ [ "express_company_id", "" ],
+ [ "is_notice", "" ],
+ [ "status", "" ],
+ ]);
+ $field = 'id,template_name,express_company_id,customer_name,pay_type,is_notice,status,is_default,create_time';
+ return success(( new ElectronicSheetService() )->getPage($data, $field));
+ }
+
+ /**
+ * @description 查看电子面单列表
+ * @return \think\Response
+ */
+ public function lists()
+ {
+ $data = $this->request->params([
+ [ "template_name", "" ],
+ [ "express_company_id", "" ],
+ [ "is_notice", "" ],
+ [ "status", "" ],
+ ]);
+ $field = 'id,template_name,express_company_id,customer_name,pay_type,is_notice,status,is_default,create_time';
+ return success(( new ElectronicSheetService() )->getList($data, $field));
+ }
+
+ /**
+ * @description 电子面单详情
+ * @param int $id
+ * @return \think\Response
+ */
+ public function info(int $id)
+ {
+ return success(( new ElectronicSheetService() )->getInfo($id));
+ }
+
+ /**
+ * 添加电子面单
+ * @description 添加电子面单
+ * @return \think\Response
+ */
+ public function add()
+ {
+ $data = $this->request->params([
+ [ "template_name", "" ],
+ [ "express_company_id", 0 ],
+ [ "customer_name", "" ],
+ [ "customer_pwd", "" ],
+ [ "send_site", "" ],
+ [ "send_staff", "" ],
+ [ "month_code", "" ],
+ [ "pay_type", 0 ],
+ [ "is_notice", 0 ],
+ [ "status", 0 ],
+ [ 'exp_type', 0 ],
+ [ "print_style", "" ],
+ [ "is_default", 0 ],
+ ]);
+ $this->validate($data, 'addon\shop\app\validate\delivery\ElectronicSheet.add');
+ $id = ( new ElectronicSheetService() )->add($data);
+ return success('ADD_SUCCESS', [ 'id' => $id ]);
+ }
+
+ /**
+ * 电子面单编辑
+ * @description 编辑电子面单
+ * @param $id 电子面单id
+ * @return \think\Response
+ */
+ public function edit(int $id)
+ {
+ $data = $this->request->params([
+ [ "template_name", "" ],
+ [ "express_company_id", 0 ],
+ [ "customer_name", "" ],
+ [ "customer_pwd", "" ],
+ [ "send_site", "" ],
+ [ "send_staff", "" ],
+ [ "month_code", "" ],
+ [ "pay_type", 0 ],
+ [ "is_notice", 0 ],
+ [ "status", 0 ],
+ [ 'exp_type', 0 ],
+ [ "print_style", "" ],
+ [ "is_default", 0 ],
+ ]);
+ $this->validate($data, 'addon\shop\app\validate\delivery\ElectronicSheet.edit');
+ ( new ElectronicSheetService() )->edit($id, $data);
+ return success('EDIT_SUCCESS');
+ }
+
+ /**
+ * 电子面单删除
+ * @description 删除电子面单
+ * @param $id 电子面单id
+ * @return \think\Response
+ */
+ public function del(int $id)
+ {
+ ( new ElectronicSheetService() )->del($id);
+ return success('DELETE_SUCCESS');
+ }
+
+ /**
+ * 电子面单设置默认模板
+ * @description 电子面单设置默认模板
+ * @param int $id
+ * @return array|\think\Response
+ */
+ public function setDefault(int $id)
+ {
+ ( new ElectronicSheetService() )->setDefault($id);
+ return success('EDIT_SUCCESS');
+ }
+
+ /**
+ * 设置 电子面单配置
+ * @description 设置电子面单配置
+ * @return array|\think\Response
+ */
+ public function setConfig()
+ {
+ $data = $this->request->params([
+ [ "interface_type", "" ],
+ [ "kdniao_id", "" ],
+ [ "kdniao_api_key", "" ],
+ [ 'server_port1', '8000' ],
+ [ 'server_port2', '18000' ],
+ [ 'https_port', '8443' ]
+ ]);
+ ( new ElectronicSheetService() )->setConfig($data);
+ return success();
+ }
+
+ /**
+ * 获取 电子面单设置
+ * @description 查看电子面单设置
+ * @return array|\think\Response
+ */
+ public function getConfig()
+ {
+ return success(( new ElectronicSheetService() )->getConfig());
+ }
+
+ /**
+ * @description 查看邮费支付方式类型
+ * @return array|\think\Response
+ */
+ public function getPayType()
+ {
+ return success(( new ElectronicSheetService() )->getPayType());
+ }
+
+ /**
+ * 打印电子面单
+ * @description 打印电子面单
+ * @return array|\think\Response
+ */
+ public function printElectronicSheet()
+ {
+ $data = $this->request->params([
+ [ 'print_type', 'single' ], // 打印方式,single:单订单,multiple:多订单
+ [ 'order_id', '' ], // 订单id
+ [ 'electronic_sheet_id', 0 ], // 电子面单id
+ [ 'order_goods_ids', '' ],
+ [ 'list', [] ] // 多个包裹,格式:[{ delivery_id : 0, electronic_sheet_id : 0 }]
+// [ 'is_delivery', 0 ], // 是否发货 todo 后续扩展
+ ]);
+ $res = ( new ElectronicSheetService() )->printElectronicSheet($data);
+ if (count($res) == 1) {
+ if ($res[ 0 ][ 'success' ]) {
+ return success($res);
+ } else {
+ return fail('[' . $res[ 0 ][ 'result_code' ] . '] ' . $res[ 0 ][ 'reason' ], [], $res[ 0 ][ 'result_code' ]);
+ }
+ } else {
+ return success($res);
+ }
+
+ }
+
+}
diff --git a/niucloud/addon/shop/app/adminapi/controller/delivery/Local.php b/niucloud/addon/shop/app/adminapi/controller/delivery/Local.php
new file mode 100644
index 000000000..eeb259c18
--- /dev/null
+++ b/niucloud/addon/shop/app/adminapi/controller/delivery/Local.php
@@ -0,0 +1,85 @@
+getLocal());
+ }
+
+ /**
+ * @description 设置配置
+ * @return \think\Response
+ */
+ public function setLocal()
+ {
+ $data = $this->request->params([
+ ['center', []],
+ ['fee_type', ''],
+ ['base_dist', 0],
+ ['base_price', 0],
+ ['grad_dist', 0],
+ ['grad_price', 0],
+ ['weight_start', 0],
+ ['weight_unit', 0],
+ ['weight_price', 0],
+ ['delivery_type', ''],
+ ['area', []],
+
+ ['time_is_open', 0],
+ ['time_type', 0],
+ ['time_week', ''],
+ ['time_interval', 30],
+ ['advance_day', 0],
+ ['most_day', 7],
+ ['start_time', 0],
+ ['end_time', 0],
+ ['delivery_time', ''],
+
+ ['third_party_config', []]
+ ]);
+ return success(data: (new LocalService())->setLocal($data));
+ }
+
+ /**
+ * @description 查看三方配送初始化信息
+ * @return \think\Response
+ */
+ public function getThirdPartyInit()
+ {
+ return success((new LocalService())->getThirdTypeConfig());
+ }
+
+ public function thirdDeliveryCallback($type, $order_no)
+ {
+ $params = $this->request->all();
+ $params['type'] = $type;
+ $params['order_no'] = $order_no;
+ (new LocalService())->thirdDeliveryCallback($params);
+ }
+}
diff --git a/niucloud/addon/shop/app/adminapi/controller/delivery/ShippingTemplate.php b/niucloud/addon/shop/app/adminapi/controller/delivery/ShippingTemplate.php
new file mode 100644
index 000000000..ffae9bf36
--- /dev/null
+++ b/niucloud/addon/shop/app/adminapi/controller/delivery/ShippingTemplate.php
@@ -0,0 +1,105 @@
+request->params([
+ [ 'template_name', '' ],
+ ]);
+ return success(( new ShippingTemplateService() )->getPage($data));
+ }
+
+ /**
+ * 运费模板列表
+ * @description 查看运费模板列表
+ * @return void
+ */
+ public function lists()
+ {
+ $data = $this->request->params([
+ [ 'template_name', '' ],
+ ]);
+ return success(( new ShippingTemplateService() )->getList($data));
+ }
+
+ /**
+ * 运费模板详情
+ * @description 查看运费模板详情
+ * @param int $template_id
+ * @return void
+ */
+ public function info(int $template_id)
+ {
+ return success(( new ShippingTemplateService() )->getInfo($template_id));
+ }
+
+ /**
+ * 添加运费模板
+ * @description 添加运费模板
+ * @return void
+ */
+ public function add()
+ {
+ $data = $this->request->params([
+ [ 'template_name', '' ],
+ [ 'fee_type', '' ],
+ [ 'area', [] ],
+ [ 'no_delivery', 0 ],
+ [ 'is_free_shipping', 0 ]
+ ]);
+ return success('ADD_SUCCESS', ( new ShippingTemplateService() )->add($data));
+ }
+
+ /**
+ * 编辑运费模板
+ * @description 编辑运费模板
+ * @return void
+ */
+ public function edit(int $template_id)
+ {
+ $data = $this->request->params([
+ [ 'template_name', '' ],
+ [ 'fee_type', '' ],
+ [ 'area', [] ],
+ [ 'no_delivery', 0 ],
+ [ 'is_free_shipping', 0 ]
+ ]);
+ return success('EDIT_SUCCESS', ( new ShippingTemplateService() )->edit($template_id, $data));
+ }
+
+ /**
+ * 删除模板
+ * @description 删除运费模板
+ * @param int $template_id
+ * @return \think\Response
+ */
+ public function del(int $template_id)
+ {
+ return success('DELETE_SUCCESS', ( new ShippingTemplateService() )->delete($template_id));
+ }
+}
diff --git a/niucloud/addon/shop/app/adminapi/controller/delivery/Store.php b/niucloud/addon/shop/app/adminapi/controller/delivery/Store.php
new file mode 100644
index 000000000..2c22113f2
--- /dev/null
+++ b/niucloud/addon/shop/app/adminapi/controller/delivery/Store.php
@@ -0,0 +1,148 @@
+getInitInfo());
+ }
+
+ /**
+ * 获取自提门店列表
+ * @description 查看自提门店列表详情
+ * @return \think\Response
+ */
+ public function lists()
+ {
+ $data = $this->request->params([
+ [ "store_name", "" ],
+ [ "create_time", [ "", "" ] ]
+ ]);
+ return success(( new StoreService() )->getPage($data));
+ }
+
+ /**
+ * 自提门店详情
+ * @param int $id
+ * @return \think\Response
+ */
+ public function info(int $id)
+ {
+ return success(( new StoreService() )->getInfo($id));
+ }
+
+
+ /**
+ * 添加自提门店
+ * @description 添加自提门店
+ * @return \think\Response
+ */
+ public function add()
+ {
+ $data = $this->request->params([
+ [ "store_name", "" ],
+ [ "store_desc", "" ],
+ [ "store_logo", "" ],
+ [ "store_mobile", 0 ],
+ [ "province_name", "" ],
+ [ "city_name", "" ],
+ [ "district_name", "" ],
+ [ "address", "" ],
+ [ "full_address", "" ],
+ [ "longitude", "" ],
+ [ "latitude", "" ],
+ [ "trade_time", "" ],
+ [ "time_type", "" ],//类型
+ [ "time_week", [] ],//周数组
+ [ "time_interval", "" ],//间隔时间段 单位分钟
+ [ "trade_time_json", [] ],//营业时间
+ ]);
+ $this->validate($data, 'addon\shop\app\validate\delivery\Store.add');
+ $id = ( new StoreService() )->add($data);
+ return success('ADD_SUCCESS', [ 'id' => $id ]);
+ }
+
+ /**
+ * 自提门店编辑
+ * @description 编辑自提门店
+ * @param $id 自提门店id
+ * @return \think\Response
+ */
+ public function edit($id)
+ {
+ $data = $this->request->params([
+ [ "store_name", "" ],
+ [ "store_desc", "" ],
+ [ "store_logo", "" ],
+ [ "store_mobile", 0 ],
+ [ "address", "" ],
+ [ "full_address", "" ],
+ [ "longitude", "" ],
+ [ "latitude", "" ],
+ [ "trade_time", "" ],
+ [ "time_week", [] ],//周数组
+ [ "time_interval", "" ],//间隔时间段 单位分钟
+ [ "trade_time_json", "" ],//营业时间
+ ]);
+ $address = $this->request->params([
+ [ "province_name", "" ],
+ [ "city_name", "" ],
+ [ "district_name", "" ],
+ ]);
+ $this->validate($data, 'addon\shop\app\validate\delivery\Store.edit');
+ ( new StoreService() )->edit($id, $data, $address);
+ return success('EDIT_SUCCESS');
+ }
+
+ /**
+ * 自提门店删除
+ * @description 删除自提门店
+ * @param $id 自提门店id
+ * @return \think\Response
+ */
+ public function del(int $id)
+ {
+ ( new StoreService() )->del($id);
+ return success('DELETE_SUCCESS');
+ }
+
+ /**
+ * @description 查看自提门店列表-全部
+ * @return \think\Response
+ */
+ public function getList()
+ {
+ $data = $this->request->params([
+ [ "store_name", "" ],
+ [ "create_time", [ "", "" ] ]
+ ]);
+ return success(( new StoreService() )->getList($data));
+ }
+
+}
diff --git a/niucloud/addon/shop/app/adminapi/controller/goods/Attr.php b/niucloud/addon/shop/app/adminapi/controller/goods/Attr.php
new file mode 100644
index 000000000..41a2fc3d5
--- /dev/null
+++ b/niucloud/addon/shop/app/adminapi/controller/goods/Attr.php
@@ -0,0 +1,158 @@
+request->params([
+ [ "attr_name", "" ],
+ [ 'order', '' ],
+ [ 'sort', '' ]
+ ]);
+ return success(( new AttrService() )->getPage($data));
+ }
+
+ /**
+ * 获取商品参数分页列表
+ * @description 查看商品参数列表-全部
+ * @return \think\Response
+ */
+ public function lists()
+ {
+ $data = $this->request->params([
+ [ 'attr_id_arr', [] ],
+ [ "attr_name", "" ],
+ [ 'order', '' ],
+ [ 'sort', '' ]
+ ]);
+ return success(( new AttrService() )->getList($data));
+ }
+
+ /**
+ * 商品参数详情
+ * @description 查看商品参数详情
+ * @param int $id
+ * @return \think\Response
+ */
+ public function info(int $id)
+ {
+ return success(( new AttrService() )->getInfo($id));
+ }
+
+ /**
+ * 添加商品参数
+ * @description 添加商品参数
+ * @return \think\Response
+ */
+ public function add()
+ {
+ $data = $this->request->params([
+ [ "attr_name", "" ],
+ [ "attr_value_format", "" ],
+ [ "sort", 0 ]
+ ]);
+ $this->validate($data, 'addon\shop\app\validate\goods\Attr.add');
+ $id = ( new AttrService() )->add($data);
+ return success('ADD_SUCCESS', [ 'id' => $id ]);
+ }
+
+ /**
+ * 商品参数编辑
+ * @description 编辑商品参数模板
+ * @param $id 商品参数id
+ * @return \think\Response
+ */
+ public function edit(int $id)
+ {
+ $data = $this->request->params([
+ [ "attr_name", "" ],
+ [ "sort", 0 ]
+ ]);
+ $this->validate($data, 'addon\shop\app\validate\goods\Attr.edit');
+ ( new AttrService() )->edit($id, $data);
+ return success('EDIT_SUCCESS');
+ }
+
+ /**
+ * 商品参数删除
+ * @description 删除商品参数模板
+ * @param int $id 商品参数id
+ * @return \think\Response
+ */
+ public function del(int $id)
+ {
+ ( new AttrService() )->del($id);
+ return success('DELETE_SUCCESS');
+ }
+
+ /**
+ * 修改商品排序号
+ * @description 修改商品参数排序
+ * @return \think\Response
+ */
+ public function modifySort()
+ {
+ $data = $this->request->params([
+ [ 'attr_id', '' ],
+ [ 'sort', '' ],
+ ]);
+ ( new AttrService() )->modifySort($data);
+ return success('SUCCESS');
+ }
+
+ /**
+ * 修改商品参数名称
+ * @description 修改商品参数名称
+ * @return \think\Response
+ */
+ public function modifyAttrName()
+ {
+ $data = $this->request->params([
+ [ 'attr_id', '' ],
+ [ 'attr_name', '' ],
+ ]);
+ ( new AttrService() )->modifyAttrName($data);
+ return success('SUCCESS');
+ }
+
+ /**
+ * 修改商品参数值
+ * @description 修改商品参数值
+ * @return \think\Response
+ */
+ public function modifyAttrValueFormat()
+ {
+ $data = $this->request->params([
+ [ 'attr_id', '' ],
+ [ 'attr_value_format', '' ],
+ ]);
+ ( new AttrService() )->modifyAttrValueFormat($data);
+ return success('SUCCESS');
+ }
+
+}
diff --git a/niucloud/addon/shop/app/adminapi/controller/goods/Brand.php b/niucloud/addon/shop/app/adminapi/controller/goods/Brand.php
new file mode 100644
index 000000000..54b0eda6b
--- /dev/null
+++ b/niucloud/addon/shop/app/adminapi/controller/goods/Brand.php
@@ -0,0 +1,125 @@
+request->params([
+ [ "brand_name","" ],
+ [ 'order', '' ],
+ [ 'sort', '' ]
+ ]);
+ return success((new BrandService())->getPage($data));
+ }
+
+ /**
+ * 获取商品品牌列表
+ * @description 查看商品列表-全部
+ * @return \think\Response
+ */
+ public function lists(){
+ $data = $this->request->params([
+ ["brand_name",""]
+ ]);
+ return success((new BrandService())->getList($data));
+ }
+
+ /**
+ * 商品品牌详情
+ * @description 查看详情
+ * @param int $id
+ * @return \think\Response
+ */
+ public function info(int $id){
+ return success((new BrandService())->getInfo($id));
+ }
+
+ /**
+ * 添加商品品牌
+ * @description 添加商品品牌
+ * @return \think\Response
+ */
+ public function add(){
+ $data = $this->request->params([
+ ["brand_name",""],
+ ["logo",""],
+ ["desc",""],
+ ["sort",0],
+ ["color_json",""],
+ ]);
+ $this->validate($data, 'addon\shop\app\validate\goods\Brand.add');
+ $id = (new BrandService())->add($data);
+ return success('ADD_SUCCESS', ['id' => $id]);
+ }
+
+ /**
+ * 商品品牌编辑
+ * @description 编辑商品品牌
+ * @param $id 商品品牌id
+ * @return \think\Response
+ */
+ public function edit($id){
+ $data = $this->request->params([
+ ["brand_name",""],
+ ["logo",""],
+ ["desc",""],
+ ["sort",0],
+ ["color_json",""],
+ ]);
+ $this->validate($data, 'addon\shop\app\validate\goods\Brand.edit');
+ (new BrandService())->edit($id, $data);
+ return success('EDIT_SUCCESS');
+ }
+
+ /**
+ * 商品品牌删除
+ * @description 删除商品品牌
+ * @param $id 商品品牌id
+ * @return \think\Response
+ */
+ public function del(int $id){
+ (new BrandService())->del($id);
+ return success('DELETE_SUCCESS');
+ }
+
+ /**
+ * 修改排序
+ * @description 编辑品牌排序
+ * @return \think\Response
+ */
+ public function modifySort()
+ {
+ $data = $this->request->params([
+ [ 'brand_id', '' ],
+ [ 'sort', '' ],
+ ]);
+ ( new BrandService() )->modifySort($data);
+ return success('SUCCESS');
+ }
+
+}
diff --git a/niucloud/addon/shop/app/adminapi/controller/goods/Category.php b/niucloud/addon/shop/app/adminapi/controller/goods/Category.php
new file mode 100644
index 000000000..ff5231b2d
--- /dev/null
+++ b/niucloud/addon/shop/app/adminapi/controller/goods/Category.php
@@ -0,0 +1,176 @@
+request->params([
+ [ "category_name", "" ]
+ ]);
+ return success(( new CategoryService() )->getPage($data));
+ }
+
+ /**
+ * 获取商品分类列表
+ * @description 查看商品分类列表-全部
+ * @return \think\Response
+ */
+ public function lists()
+ {
+ $data = $this->request->params([
+ [ "category_name", "" ],
+ [ 'level', '' ]
+ ]);
+ return success(( new CategoryService() )->getList($data));
+ }
+
+ /**
+ * 获取商品分类树结构
+ * @description 查看商品分类树结构-树结构
+ * @return \think\Response
+ */
+ public function tree()
+ {
+ return success(( new CategoryService() )->getTree());
+ }
+
+ /**
+ * 商品分类详情
+ * @description 查看商品分类详情
+ * @param int $id
+ * @return \think\Response
+ */
+ public function info(int $id)
+ {
+ return success(( new CategoryService() )->getInfo($id));
+ }
+
+ /**
+ * 添加商品分类
+ * @description 添加商品分类
+ * @return \think\Response
+ */
+ public function add()
+ {
+ $data = $this->request->params([
+ [ "category_name", "" ],
+ [ "image", "" ],
+ [ "pid", 0 ],
+ [ "is_show", 0 ],
+ [ "sort", 0 ]
+ ]);
+ $this->validate($data, 'addon\shop\app\validate\goods\Category.add');
+ $id = ( new CategoryService() )->add($data);
+ return success('ADD_SUCCESS', [ 'id' => $id ]);
+ }
+
+ /**
+ * 商品分类编辑
+ * @description 编辑商品分类
+ * @param $id 商品分类id
+ * @return \think\Response
+ */
+ public function edit($id)
+ {
+ $data = $this->request->params([
+ [ "category_name", "" ],
+ [ "image", "" ],
+ [ "pid", 0 ],
+ [ "is_show", 0 ],
+ [ "sort", '' ]
+ ]);
+ $this->validate($data, 'addon\shop\app\validate\goods\Category.edit');
+ ( new CategoryService() )->edit($id, $data);
+ return success('EDIT_SUCCESS');
+ }
+
+ /**
+ * 商品分类删除
+ * @description 删除商品分类
+ * @param $id 商品分类id
+ * @return \think\Response
+ */
+ public function del(int $id)
+ {
+ ( new CategoryService() )->del($id);
+ return success('DELETE_SUCCESS');
+ }
+
+ /**
+ * 拖拽修改分类
+ * @description 拖拽修改分类排序
+ */
+ public function editCategory()
+ {
+ $data = $this->request->params([
+ [ "category_sort_array", [] ]
+ ]);
+ ( new CategoryService() )->updateCategory($data);
+ return success('SUCCESS');
+ }
+
+ /**
+ * 设置商品分类配置
+ * @description 设置商品分类配置
+ * @return \think\Response
+ */
+ public function setGoodsCategoryConfig()
+ {
+ $data = $this->request->params([
+ [ "level", "" ],
+ [ "template", "" ],
+ [ "page_title", "" ],
+ [ "search", "" ],
+ [ "goods", "" ],
+ [ "sort", "" ],
+ [ "cart", '' ],
+ ]);
+ ( new CategoryService() )->setGoodsCategoryConfig($data);
+ return success('SUCCESS');
+ }
+
+ /**
+ * 获取商品分类配置
+ * @description 查看商品分类配置
+ * @return \think\Response
+ */
+ public function getGoodsCategoryConfig()
+ {
+ return success(( new CategoryService() )->getGoodsCategoryConfig());
+ }
+
+ /**
+ * 获取商品分类树结构供弹框调用
+ * @description 获取商品分类树结构供弹框调用-树结构
+ * @return \think\Response
+ */
+ public function components()
+ {
+ return success(( new CategoryService() )->getTreeComponents());
+ }
+}
diff --git a/niucloud/addon/shop/app/adminapi/controller/goods/Config.php b/niucloud/addon/shop/app/adminapi/controller/goods/Config.php
new file mode 100644
index 000000000..5af6cc31d
--- /dev/null
+++ b/niucloud/addon/shop/app/adminapi/controller/goods/Config.php
@@ -0,0 +1,98 @@
+getSearchConfig());
+ }
+
+ /**
+ * 设置搜索配置
+ * @description 设置搜索配置
+ * @return \think\Response
+ */
+ public function setSearchConfig()
+ {
+
+ $data = $this->request->params([
+ [ "default_word", "" ],
+ [ "search_words", "" ]
+ ]);
+ ( new ConfigService() )->setSearchConfig($data);
+ return success('SUCCESS');
+ }
+
+ /**
+ * 获取商品唯一编码配置
+ * @description 获取商品唯一编码配置
+ * @return \think\Response
+ */
+ public function getUniqueConfig()
+ {
+
+ return success(( new ConfigService() )->getUniqueConfig());
+ }
+
+ /**
+ * 设置商品唯一编码配置
+ * @description 设置商品唯一编码配置
+ * @return \think\Response
+ */
+ public function setUniqueConfig()
+ {
+ $data = $this->request->params([
+ [ "is_enable", 0 ]
+ ]);
+ ( new ConfigService() )->setUniqueConfig($data);
+ return success('SUCCESS');
+ }
+
+
+ /**
+ * 获取商品排序配置
+ * @description 查看商品排序配置
+ * @return \think\Response
+ */
+ public function getSortConfig()
+ {
+ return success(( new ConfigService() )->getSortConfig());
+ }
+
+ /**
+ * 设置商品排序配置
+ * @description 设置商品排序配置
+ * @return \think\Response
+ */
+ public function setSortConfig()
+ {
+ $data = $this->request->params([
+ [ "sort_type", GoodsDict::SORT_TYPE_ASC ],
+ [ "sort_column", GoodsDict::SORT_COLUMN_SORT ],
+ [ "default_sort", 0 ],
+ ]);
+ ( new ConfigService() )->setSortConfig($data);
+ return success('SUCCESS');
+ }
+}
diff --git a/niucloud/addon/shop/app/adminapi/controller/goods/Evaluate.php b/niucloud/addon/shop/app/adminapi/controller/goods/Evaluate.php
new file mode 100644
index 000000000..3209651b3
--- /dev/null
+++ b/niucloud/addon/shop/app/adminapi/controller/goods/Evaluate.php
@@ -0,0 +1,214 @@
+request->params([
+ [ 'goods_name', '' ],
+ [ 'status', '' ],
+ ]);
+ return success(( new EvaluateService() )->getPage($data));
+ }
+
+ /**
+ * 商品评价详情
+ * @param int $id
+ * @description 查看商品评价详情
+ * @return \think\Response
+ */
+ public function info(int $id)
+ {
+ return success(( new EvaluateService() )->getInfo($id));
+ }
+
+ /**
+ * 添加商品评价
+ * @description 添加商品评价
+ * @return \think\Response
+ */
+ public function add()
+ {
+ $data = $this->request->params([
+ [ "goods_id", 0 ],
+ [ "member_head", "" ],
+ [ "member_name", "" ],
+ [ "content", "" ],
+ [ "images", "" ],
+ [ "is_anonymous", 0 ],
+ [ "scores", 0 ],
+ [ "is_show", 0 ],
+ [ "create_time", 0 ]
+ ]);
+ $this->validate($data, 'addon\shop\app\validate\goods\Evaluate.add');
+ $id = ( new EvaluateService() )->add($data);
+ return success('ADD_SUCCESS', [ 'id' => $id ]);
+ }
+
+ /**
+ * 商品评价删除
+ * @description 删除商品评价
+ * @param $id 商品评价id
+ * @return \think\Response
+ */
+ public function del(int $id)
+ {
+ ( new EvaluateService() )->del($id);
+ return success('DELETE_SUCCESS');
+ }
+
+ /**
+ * 评价审核
+ * @description 审核评价
+ * @param $id
+ */
+ public function evaluateAudit($id)
+ {
+ $data = $this->request->params([
+ [ "is_audit", 0 ],
+ ]);
+ ( new EvaluateService() )->audit($id, $data);
+
+ return success('SUCCESS');
+ }
+
+ /**
+ * 审核通过
+ * @description 审核-通过评价
+ * @param $id
+ * @return \think\Response
+ */
+ public function adopt($id)
+ {
+ ( new EvaluateService() )->auditAdopt($id);
+
+ return success('SUCCESS');
+ }
+
+ /**
+ * 审核拒绝
+ * @description 审核-拒绝通过评价
+ * @param $id
+ * @return \think\Response
+ */
+ public function refuse($id)
+ {
+ ( new EvaluateService() )->auditRefuse($id);
+
+ return success('SUCCESS');
+ }
+
+ /**
+ * 评价回复
+ * @description 回复评价
+ * @param $id
+ */
+ public function evaluateReply($id)
+ {
+ $data = $this->request->params([
+ [ "explain_first", '' ],
+ ]);
+ ( new EvaluateService() )->reply($id, $data);
+
+ return success('SUCCESS');
+ }
+
+ /**
+ * 置顶
+ * @description 置顶评价
+ * @param $id
+ */
+ public function topping($id)
+ {
+ ( new EvaluateService() )->topping($id);
+
+ return success('SUCCESS');
+ }
+
+ /**
+ * 取消置顶
+ * @description 取消置顶评价
+ * @param $id
+ */
+ public function cancelTopping($id)
+ {
+ ( new EvaluateService() )->cancelTopping($id);
+
+ return success('SUCCESS');
+ }
+
+ /**
+ * 获取审核状态
+ * @description 审核状态
+ * @return \think\Response
+ */
+ public function status()
+ {
+ return success(EvaluateDict::getStatus());
+ }
+
+ /**
+ * 批量通过
+ * @description 批量通过
+ */
+ public function batchAdopt()
+ {
+ $data = $this->request->params([
+ [ 'evaluate_ids', [] ],
+ ]);
+ ( new EvaluateService() )->batchAdopt($data['evaluate_ids']);
+ return success('SUCCESS');
+ }
+
+ /**
+ * 批量拒绝
+ * @description 批量拒绝
+ */
+ public function batchRefuse()
+ {
+ $data = $this->request->params([
+ [ 'evaluate_ids', [] ],
+ ]);
+ ( new EvaluateService() )->batchRefuse($data['evaluate_ids']);
+ return success('SUCCESS');
+ }
+
+ /**
+ * 批量删除
+ * @description 批量删除
+ */
+ public function batchDel()
+ {
+ $data = $this->request->params([
+ [ 'evaluate_ids', [] ],
+ ]);
+ ( new EvaluateService() )->batchDel($data['evaluate_ids']);
+ return success('SUCCESS');
+ }
+}
diff --git a/niucloud/addon/shop/app/adminapi/controller/goods/Goods.php b/niucloud/addon/shop/app/adminapi/controller/goods/Goods.php
new file mode 100644
index 000000000..bdc543a55
--- /dev/null
+++ b/niucloud/addon/shop/app/adminapi/controller/goods/Goods.php
@@ -0,0 +1,536 @@
+request->params([
+ ["goods_name", ""],
+ ["goods_category", ''],
+ ["goods_type", ""],
+ ["brand_id", ""],
+ ["label_ids", ""],
+ ["start_sale_num", ""],
+ ["end_sale_num", ""],
+ ["start_price", ""],
+ ["end_price", ""],
+ ["status", ""],
+ ['order', ''],
+ ['sort', '']
+ ]);
+ return success((new GoodsService())->getPage($data));
+ }
+
+ /**
+ * 商品详情
+ * @description 查看商品详情
+ * @param int $id
+ * @return \think\Response
+ */
+ public function info(int $id)
+ {
+ return success((new GoodsService())->getInfo($id));
+ }
+
+ /**
+ * 获取商品添加/编辑数据
+ * @description 获取初始化数据
+ * @return \think\Response
+ */
+ public function init()
+ {
+ $data = $this->request->params([
+ ["goods_id", 0],
+ ]);
+ return success((new GoodsService())->getInit($data));
+ }
+
+ /**
+ * 添加商品
+ * @description 添加商品
+ * @return \think\Response
+ */
+ public function add()
+ {
+ $data = $this->request->params([
+ ["goods_name", ""],
+ ["sub_title", ""],
+ ["goods_type", ""],
+ ["goods_image", ""],
+ ["goods_video", ""],
+ ["goods_category", ''],
+ ["brand_id", 0],
+ ["label_ids", ""],
+ ['service_ids', ''],
+ ['supplier_id', 0],
+ ["status", 0],
+ ["sort", 0],
+ ['attr_ids', []],
+ ['attr_format', ''],
+ ['is_gift', 0],
+
+ // 规格类型,single:单规格,multi:多规格
+ ['spec_type', ''],
+
+ // 单规格数据
+ ["price", 0],
+ ["market_price", 0],
+ ["cost_price", 0],
+ ["price", 0],
+ ["weight", 0],
+ ["volume", 0],
+ ["stock", 0],
+ ["sku_no", ''],
+ ["unit", "件"],
+ ["virtual_sale_num", 0],
+ ["is_limit", 0],
+ ["limit_type", 1],
+ ["max_buy", 0],
+ ["min_buy", 0],
+
+ // 多规格数据
+ ['goods_spec_format', ''],
+ ['goods_sku_data', ''],
+
+ // 配送设置
+ ["delivery_type", ""],
+ ["is_free_shipping", 0],
+ ['fee_type', ''],
+ ['delivery_money', 0],
+ ["delivery_template_id", 0],
+
+ // 商品详情
+ ["goods_desc", "", false],
+
+ ['member_discount', ''], // 会员等级折扣,不参与:空,会员折扣:discount,指定会员价:fixed_price
+ ['poster_id', 0], // 海报id
+ ['form_id', 0], // 万能表单id
+ ['diy_detail_id', 0] // 自定义详情id
+ ]);
+
+ $this->validate($data, 'addon\shop\app\validate\goods\Goods.add');
+ $id = (new GoodsService())->add($data);
+ return success('ADD_SUCCESS', ['id' => $id]);
+ }
+
+ /**
+ * 商品编辑
+ * @description 编辑商品
+ * @param $id
+ * @return \think\Response
+ */
+ public function edit($id)
+ {
+ $data = $this->request->params([
+ ["goods_name", ""],
+ ["sub_title", ""],
+ ["goods_type", ""],
+ ["goods_image", ""],
+ ["goods_video", ""],
+ ["goods_category", ''],
+ ["brand_id", 0],
+ ["label_ids", ""],
+ ['service_ids', ''],
+ ['supplier_id', 0],
+ ["status", 0],
+ ["sort", 0],
+ ['attr_ids', []],
+ ['attr_format', ''],
+ ['is_gift', 0],
+
+ // 规格类型,single:单规格,multi:多规格
+ ['spec_type', ''],
+
+ // 单规格数据
+ ["price", 0],
+ ["market_price", 0],
+ ["cost_price", 0],
+ ["price", 0],
+ ["weight", 0],
+ ["volume", 0],
+ ["stock", 0],
+ ["sku_no", ''],
+ ["unit", "件"],
+ ["virtual_sale_num", 0],
+ ["is_limit", 0],
+ ["limit_type", 1],
+ ["max_buy", 0],
+ ["min_buy", 0],
+
+ // 多规格数据
+ ['goods_spec_format', ''],
+ ['goods_sku_data', ''],
+
+ // 配送设置
+ ["delivery_type", ""],
+ ["is_free_shipping", 0],
+ ['fee_type', ''],
+ ['delivery_money', 0],
+ ["delivery_template_id", 0],
+
+ // 商品详情
+ ["goods_desc", "", false],
+
+ ['member_discount', ''], // 会员等级折扣,不参与:空,会员折扣:discount,指定会员价:fixed_price
+
+ ['poster_id', 0], // 海报id
+ ['form_id', 0], // 万能表单id
+ ['diy_detail_id', 0] // 自定义详情id
+ ]);
+ $this->validate($data, 'addon\shop\app\validate\goods\Goods.edit');
+ $res = (new GoodsService())->edit($id, $data);
+ return success('EDIT_SUCCESS');
+ }
+
+ /**
+ * 商品删除
+ * @description 删除商品
+ * @return \think\Response
+ */
+ public function del()
+ {
+ $data = $this->request->params([
+ ['is_all', 0],
+ ['where', []],
+ ['goods_ids', ''],//is_all == 1时 goods_ids 为未选中的ID
+ ]);
+ (new GoodsService())->del($data);
+ return success('DELETE_SUCCESS');
+ }
+
+ /**
+ * 商品恢复
+ * @description 恢复商品
+ * @return \think\Response
+ */
+ public function recycle()
+ {
+ $data = $this->request->params([
+ ['goods_ids', ''],
+ ]);
+ (new GoodsService())->recycle($data['goods_ids']);
+ return success('SUCCESS');
+ }
+
+ /**
+ * 获取商品类型
+ * @description 获取商品类型
+ * @return \think\Response
+ */
+ public function type()
+ {
+ return success((new GoodsService())->getType());
+ }
+
+ /**
+ * 修改商品排序号
+ * @description 修改商品排序号
+ * @return \think\Response
+ */
+ public function editSort()
+ {
+ $data = $this->request->params([
+ ['goods_id', ''],
+ ['sort', ''],
+ ]);
+ (new GoodsService())->editSort($data);
+ return success('SUCCESS');
+ }
+
+ /**
+ * 修改商品上下架状态
+ * @description 修改商品上下架状态
+ * @return \think\Response
+ */
+ public function editStatus()
+ {
+ $data = $this->request->params([
+ ['is_all', 0],
+ ['where', []],
+ ['goods_ids', ''],
+ ['status', ''],
+ ]);
+ (new GoodsService())->editStatus($data);
+ return success('SUCCESS');
+ }
+
+ /**
+ * 修改商品上下架状态(单商品)
+ * @description 修改商品上下架状态(单商品)
+ * @return \think\Response
+ */
+ public function editSingleStatus()
+ {
+ $data = $this->request->params([
+ ['goods_id', 0],
+ ['status', 0],
+ ]);
+ (new GoodsService())->editSingleStatus($data);
+ return success('SUCCESS');
+ }
+
+ /**
+ * 复制商品
+ * @description 复制商品
+ * @param int $goods_id
+ * @return \think\Response
+ */
+ public function copy(int $goods_id)
+ {
+ (new GoodsService())->copy($goods_id);
+ return success('SUCCESS');
+ }
+
+ /**
+ * 获取回收站商品分页列表
+ * @description 查看回收站商品分页列表
+ * @return \think\Response
+ */
+ public function recyclePages()
+ {
+ $data = $this->request->params([
+ ["goods_name", ""],
+ ["goods_category", ''],
+ ["goods_type", ""],
+ ['order', ''],
+ ['sort', '']
+ ]);
+ return success((new GoodsService())->getRecyclePage($data));
+ }
+
+ /**
+ * 商品选择分页列表(按照单商品)
+ * @description 获取商品选择分页列表(按照单商品)
+ * @return \think\Response
+ */
+ public function select()
+ {
+ $data = $this->request->params([
+ ['keyword', ''], // 搜索关键词
+ ["goods_category", ""], // 商品分类
+ ["goods_type", ""], // 商品分类
+ ["select_type", "all"], // 商品分类
+ ["start_price", ""],
+ ["end_price", ""],
+ ['goods_ids', []], // 已选商品id集合
+ ['sku_ids', []], // 已选商品规格id集合
+ ['verify_goods_ids', []], // 检测商品id集合是否存在,移除不存在的商品id,纠正数据准确性
+ ['verify_sku_ids', []], // 检测商品规格id集合是否存在,移除不存在的商品规格id,纠正数据准确性
+ ['is_gift', 0] // 是否查询赠品(0:不查赠品 1:查询赠品)
+ ]);
+
+ return success((new GoodsService())->getSelectPage($data));
+ }
+
+ /**
+ * 商品选择分页列表(带sku)
+ * @return \think\Response
+ */
+ public function selectGoodsSku()
+ {
+ $data = $this->request->params([
+ ['keyword', ''], // 搜索关键词
+ ["goods_category", ""], // 商品分类
+ ["goods_type", ""], // 商品分类
+ ['goods_ids', ''], // 已选商品id集合
+ ['verify_goods_ids', ''], // 检测商品id集合是否存在,移除不存在的商品id,纠正数据准确性
+ ['verify_sku_ids', []], // 检测商品规格id集合是否存在,移除不存在的商品规格id,纠正数据准确性
+ ['is_gift', 0] // 是否查询赠品(0:不查赠品 1:查询赠品)
+ ]);
+
+ return success((new GoodsService())->getSelectSku($data));
+ }
+
+ /**
+ * 商品选择分页列表(代客下单专用)
+ * @description 获取商品选择分页列表(代客下单专用)
+ * @return \think\Response
+ */
+ public function buyGoodsSelect()
+ {
+ $data = $this->request->params([
+ ['keyword', ''], // 搜索关键词
+ ["goods_category", ""], // 商品分类
+ ["goods_type", ""], // 商品分类
+ ["member_id", 0], // 会员id
+ ]);
+
+ return success((new GoodsService())->getBuyGoodsSelect($data));
+ }
+
+ /**
+ * 已选商品分页列表(代客下单专用)
+ * @description 获取已选商品分页列表(代客下单专用)
+ * @return \think\Response
+ */
+ public function buyGoodsSelected()
+ {
+ $data = $this->request->params([
+ ['sku_ids', []],
+ ['member_id', 0],
+ ]);
+
+ return success((new GoodsService())->getBuyGoodsSelected($data));
+ }
+
+ /**
+ * 获取商品规格信息,切换规格(代客下单专用)
+ * @description 获取商品规格信息,切换规格(代客下单专用)
+ */
+ public function buySkuSelect()
+ {
+ $data = $this->request->params([
+ ['sku_id', 0],
+ ['member_id', 0],
+ ]);
+ return success((new GoodsService())->getBuySkuSelect($data));
+ }
+
+ /**
+ * 查询商品SKU规格列表
+ * @description 查询商品SKU规格列表
+ * @return \think\Response
+ */
+ public function sku()
+ {
+ $data = $this->request->params([
+ ['goods_id', '']
+ ]);
+
+ return success((new GoodsService())->getSkuList($data));
+ }
+
+ /**
+ * 编辑商品规格列表库存
+ * @description 编辑商品规格列表库存
+ * @return \think\Response
+ */
+ public function editGoodsListStock()
+ {
+ $data = $this->request->params([
+ ['goods_id', 0],
+ ['sku_list', '']
+ ]);
+ (new GoodsService())->editGoodsListStock($data);
+ return success('EDIT_SUCCESS');
+ }
+
+ /**
+ * 编辑商品规格列表价格
+ * @description 编辑商品规格列表库存
+ * @return \think\Response
+ */
+ public function editGoodsListPrice()
+ {
+ $data = $this->request->params([
+ ['goods_id', 0],
+ ['sku_list', '']
+ ]);
+ (new GoodsService())->editGoodsListPrice($data);
+ return success('EDIT_SUCCESS');
+ }
+
+ /**
+ * 编辑商品规格列表会员价格
+ * @description 编辑商品规格列表会员价格
+ * @return \think\Response
+ */
+ public function editGoodsListMemberPrice()
+ {
+ $data = $this->request->params([
+ ['goods_id', 0],
+ ['member_discount', ''], // 会员等级折扣,不参与:空,会员折扣:discount,指定会员价:fixed_price
+ ['sku_list', '']
+ ]);
+ (new GoodsService())->editGoodsListMemberPrice($data);
+ return success('EDIT_SUCCESS');
+ }
+
+ /**
+ * 查询商品参与营销活动的数量
+ * @description 查询商品参与营销活动的数量
+ * @return \think\Response
+ */
+ public function getActiveGoodsCount()
+ {
+ $data = $this->request->params([
+ ['goods_id', '']
+ ]);
+
+ return success(data: (new GoodsService())->getActiveGoodsCount($data['goods_id']));
+ }
+
+ /**
+ * 批量设置商品
+ * @description 批量设置商品
+ * @return \think\Response
+ */
+ public function batchSet()
+ {
+ $data = $this->request->params([
+ ['is_all', 0],
+ ['goods_ids', []],
+ ['set_value', []],
+ ['set_type', ''],
+ ['where', []],
+
+ ]);
+ (new GoodsService())->batchSet($data);
+ return success('EDIT_SUCCESS');
+ }
+
+ /**
+ * 获取批量设置类型
+ * @description 获取批量设置类型
+ * @return \think\Response
+ */
+ public function getBatchSetDict()
+ {
+ return success((new GoodsService())->getBatchSetDict());
+ }
+
+ /**
+ * 验证商品编码是否重复
+ * @description 验证商品编码是否重复
+ * @return \think\Response
+ */
+ public function verifySkuNo()
+ {
+ $params = $this->request->params(
+ [
+ ['sku_no', ''],
+ ['goods_id', 0]
+ ]);
+ (new ConfigService())->verifySkuNo($params);
+ return success('SUCCESS');
+ }
+
+}
diff --git a/niucloud/addon/shop/app/adminapi/controller/goods/Label.php b/niucloud/addon/shop/app/adminapi/controller/goods/Label.php
new file mode 100644
index 000000000..60bfbbf67
--- /dev/null
+++ b/niucloud/addon/shop/app/adminapi/controller/goods/Label.php
@@ -0,0 +1,169 @@
+request->params([
+ [ "label_name", "" ],
+ [ 'group_id', 0 ],
+ [ 'order', '' ],
+ [ 'sort', '' ]
+ ]);
+ return success(( new LabelService() )->getPage($data));
+ }
+
+ /**
+ * 获取商品标签列表
+ * @description 获取商品标签列表-全部
+ * @return \think\Response
+ */
+ public function lists()
+ {
+ $data = $this->request->params([
+ [ "label_name", "" ]
+ ]);
+ return success(( new LabelService() )->getList($data));
+ }
+
+ /**
+ * 商品标签详情
+ * @description 查看商品标签详情
+ * @param int $id
+ * @return \think\Response
+ */
+ public function info(int $id)
+ {
+ return success(( new LabelService() )->getInfo($id));
+ }
+
+ /**
+ * 添加商品标签
+ * @description 添加商品标签
+ * @return \think\Response
+ */
+ public function add()
+ {
+ $data = $this->request->params([
+ [ "label_name", "" ],
+ [ 'group_id', 0 ],
+ [ 'style_type', '' ],
+ [ 'color_json', '' ],
+ [ 'icon', '' ],
+ [ 'status', '' ],
+ [ "memo", "" ],
+ [ "sort", 0 ],
+ ]);
+
+ $this->validate($data, 'addon\shop\app\validate\goods\Label.add');
+ $id = ( new LabelService() )->add($data);
+ return success('ADD_SUCCESS', [ 'id' => $id ]);
+ }
+
+ /**
+ * 商品标签编辑
+ * @description 编辑商品标签
+ * @param $id `商品标签id`
+ * @return \think\Response
+ */
+ public function edit($id)
+ {
+ $data = $this->request->params([
+ [ "label_name", "" ],
+ [ 'group_id', 0 ],
+ [ 'style_type', '' ],
+ [ 'color_json', '' ],
+ [ 'icon', '' ],
+ [ 'status', '' ],
+ [ "memo", "" ],
+ [ "sort", 0 ],
+
+ ]);
+ $this->validate($data, 'addon\shop\app\validate\goods\Label.edit');
+ ( new LabelService() )->edit($id, $data);
+ return success('EDIT_SUCCESS');
+ }
+
+ /**
+ * 商品标签删除
+ * @description 删除商品标签
+ * @param $id 商品标签id
+ * @return \think\Response
+ */
+ public function del(int $id)
+ {
+ ( new LabelService() )->del($id);
+ return success('DELETE_SUCCESS');
+ }
+
+ /**
+ * 修改排序
+ * @description 修改商品标签排序
+ * @return \think\Response
+ */
+ public function modifySort()
+ {
+ $data = $this->request->params([
+ [ 'label_id', '' ],
+ [ 'sort', '' ],
+ ]);
+ ( new LabelService() )->modifySort($data);
+ return success('SUCCESS');
+ }
+
+ /**
+ * 修改状态
+ * @description 添加商品标签状态
+ * @return \think\Response
+ */
+ public function modifyStatus()
+ {
+ $data = $this->request->params([
+ [ 'label_id', '' ],
+ [ 'status', '' ],
+ ]);
+ ( new LabelService() )->modifyStatus($data);
+ return success('SUCCESS');
+ }
+
+ /**
+ * 复制分类
+ * @description 复制商品标签
+ * @param int $id
+ * @return \think\Response
+ * @throws \think\db\exception\DataNotFoundException
+ * @throws \think\db\exception\DbException
+ * @throws \think\db\exception\ModelNotFoundException
+ */
+ public function copy(int $id)
+ {
+ (new LabelService())->copy($id);
+ return success('SUCCESS');
+ }
+
+}
diff --git a/niucloud/addon/shop/app/adminapi/controller/goods/LabelGroup.php b/niucloud/addon/shop/app/adminapi/controller/goods/LabelGroup.php
new file mode 100644
index 000000000..c369423ab
--- /dev/null
+++ b/niucloud/addon/shop/app/adminapi/controller/goods/LabelGroup.php
@@ -0,0 +1,124 @@
+request->params([
+ [ "group_name", "" ],
+ [ 'order', '' ],
+ [ 'sort', '' ]
+ ]);
+ return success(( new LabelGroupService() )->getPage($data));
+ }
+
+ /**
+ * 获取商品标签分组列表
+ * @description 获取商品标签分组列表-全部
+ * @return \think\Response
+ */
+ public function lists()
+ {
+ $data = $this->request->params([
+ [ "group_name", "" ]
+ ]);
+ return success(( new LabelGroupService() )->getList($data));
+ }
+
+ /**
+ * 商品标签分组详情
+ * @description 查看商品标签分组详情
+ * @param int $id
+ * @return \think\Response
+ */
+ public function info(int $id)
+ {
+ return success(( new LabelGroupService() )->getInfo($id));
+ }
+
+ /**
+ * 添加商品标签分组
+ * @description 添加商品标签分组
+ * @return \think\Response
+ */
+ public function add()
+ {
+ $data = $this->request->params([
+ [ "group_name", "" ],
+ [ "sort", 0 ],
+ ]);
+ $this->validate($data, 'addon\shop\app\validate\goods\LabelGroup.add');
+ $id = ( new LabelGroupService() )->add($data);
+ return success('ADD_SUCCESS', [ 'id' => $id ]);
+ }
+
+ /**
+ * 商品标签分组编辑
+ * @description 编辑商品标签分组
+ * @param $id 商品标签分组id
+ * @return \think\Response
+ */
+ public function edit($id)
+ {
+ $data = $this->request->params([
+ [ "group_name", "" ],
+ [ "sort", 0 ],
+ ]);
+ $this->validate($data, 'addon\shop\app\validate\goods\LabelGroup.edit');
+ ( new LabelGroupService() )->edit($id, $data);
+ return success('EDIT_SUCCESS');
+ }
+
+ /**
+ * 商品标签分组删除
+ * @description 删除商品标签分组
+ * @param $id 商品标签分组id
+ * @return \think\Response
+ */
+ public function del(int $id)
+ {
+ ( new LabelGroupService() )->del($id);
+ return success('DELETE_SUCCESS');
+ }
+
+ /**
+ * 修改排序
+ * @description 修改商品标签分组排序
+ * @return \think\Response
+ */
+ public function modifySort()
+ {
+ $data = $this->request->params([
+ [ 'group_id', '' ],
+ [ 'sort', '' ],
+ ]);
+ ( new LabelGroupService() )->modifySort($data);
+ return success('SUCCESS');
+ }
+
+}
diff --git a/niucloud/addon/shop/app/adminapi/controller/goods/Rank.php b/niucloud/addon/shop/app/adminapi/controller/goods/Rank.php
new file mode 100644
index 000000000..da7389a21
--- /dev/null
+++ b/niucloud/addon/shop/app/adminapi/controller/goods/Rank.php
@@ -0,0 +1,214 @@
+request->params([
+// [ "rank_name", "" ],
+ [ "rank_images", "" ],
+// [ "rank_remark", "" ],
+ [ "no_color", "" ],
+ [ "select_color", "" ],
+ [ "select_bg_color_start", "" ],
+ [ "select_bg_color_end", "" ],
+ ]);
+ ( new RankService() )->setGoodsRankConfig($data);
+ return success('SUCCESS');
+ }
+
+ /**
+ * 获取商品排行配置
+ * @description 查看商品排行配置
+ * @return \think\Response
+ */
+ public function getRankConfig()
+ {
+ return success(( new RankService() )->getGoodsRankConfig());
+ }
+
+ /**
+ * 获取商品排行榜分页列表
+ * @description 查看商品排行榜列表-分页
+ * @return \think\Response
+ */
+ public function pages()
+ {
+ $data = $this->request->params([
+ [ "name", "" ],
+ [ "rank_type", "" ],
+ [ 'order', '' ],
+ [ 'sort', '' ]
+ ]);
+ return success(( new RankService() )->getPage($data));
+ }
+
+ /**
+ * 添加商品排行榜
+ * @description 添加商品排行榜
+ * @return \think\Response
+ */
+ public function add()
+ {
+ $data = $this->request->params([
+ [ "name", "" ],
+ [ "rank_type", '' ],
+ [ "goods_source", '' ],
+ [ "rule_type", '' ],
+ [ "goods_json", [] ],
+ [ "category_ids", [] ],
+ [ "brand_ids", [] ],
+ [ "label_ids", [] ],
+ [ "sort", 0 ],
+ [ "status", 1 ],
+ ]);
+ $this->validate($data, 'addon\shop\app\validate\goods\Rank.add');
+ $id = ( new RankService() )->add($data);
+ return success('ADD_SUCCESS', [ 'id' => $id ]);
+ }
+
+ /**
+ * 编辑商品排行榜
+ * @description 编辑商品排行榜
+ * @param int $id 排行榜id
+ * @return \think\Response
+ */
+ public function edit($id)
+ {
+ $data = $this->request->params([
+ [ "name", "" ],
+ [ "rank_type", '' ],
+ [ "goods_source", '' ],
+ [ "rule_type", '' ],
+ [ "goods_json", [] ],
+ [ "category_ids", [] ],
+ [ "brand_ids", [] ],
+ [ "label_ids", [] ],
+ [ "sort", 0 ],
+ [ "status", 1 ],
+ ]);
+ $this->validate($data, 'addon\shop\app\validate\goods\Rank.edit');
+ ( new RankService() )->edit($id, $data);
+ return success('EDIT_SUCCESS', [ 'id' => $id ]);
+ }
+
+ /**
+ * 商品排行榜详情
+ * @description 查看商品排行榜详情
+ * @param int $id
+ * @return \think\Response
+ */
+ public function info(int $id)
+ {
+ return success(( new RankService() )->getInfo($id));
+ }
+
+ /**
+ * 删除
+ * @description 删除商品排行榜
+ * @param int $id 排行榜id
+ * @return \think\Response
+ */
+ public function del(int $id)
+ {
+ ( new RankService() )->del($id);
+ return success('DELETE_SUCCESS');
+ }
+
+ /**
+ * 商品排行榜选项列表
+ * @description 商品排行榜选项列表
+ * @param int $id
+ * @return \think\Response
+ */
+ public function getOptionData()
+ {
+ return success(( new RankService() )->getOptionData());
+ }
+
+ /**
+ * 修改榜单排序号
+ * @description 修改榜单排序号
+ * @return \think\Response
+ */
+ public function editSort()
+ {
+ $data = $this->request->params([
+ [ "rank_id", "" ],
+ [ "sort", 0 ],
+ ]);
+ ( new RankService() )->editSort($data);
+ return success('EDIT_SUCCESS');
+ }
+
+ /**
+ * 批量删除
+ * @description 批量删除商品排行榜
+ * @param int $id
+ * @return \think\Response
+ */
+ public function batchDelete()
+ {
+ $data = $this->request->params([
+ [ "rank_id", [] ],
+ ]);
+ ( new RankService() )->batchDelete($data);
+ return success('DELETE_SUCCESS');
+ }
+
+ /**
+ * 获取排行榜分页列表(用于弹框选择)
+ * @description 获取排行榜分页列表
+ * @return \think\Response
+ */
+ public function select()
+ {
+ $data = $this->request->params([
+ [ "name", "" ],
+ [ "rank_type", "" ],
+ [ "verify_rank_ids", [] ],
+ ]);
+ return success(( new RankService() )->getSelectPage($data));
+ }
+
+ /**
+ * 修改状态
+ * @description 修改商品排行榜状态
+ * @return \think\Response
+ */
+ public function modifyStatus()
+ {
+ $data = $this->request->params([
+ [ 'rank_id', '' ],
+ [ 'status', '' ],
+ ]);
+ ( new RankService() )->modifyStatus($data);
+ return success('SUCCESS');
+ }
+
+}
diff --git a/niucloud/addon/shop/app/adminapi/controller/goods/Service.php b/niucloud/addon/shop/app/adminapi/controller/goods/Service.php
new file mode 100644
index 000000000..46a033948
--- /dev/null
+++ b/niucloud/addon/shop/app/adminapi/controller/goods/Service.php
@@ -0,0 +1,109 @@
+request->params([
+ [ "service_name", "" ]
+ ]);
+ return success(( new ServiceService() )->getPage($data));
+ }
+
+ /**
+ * 获取商品服务列表
+ * @description 查看商品服务列表-全部
+ * @return \think\Response
+ */
+ public function lists()
+ {
+ $data = $this->request->params([
+ [ "service_name", "" ]
+ ]);
+ return success(( new ServiceService() )->getList($data));
+ }
+
+ /**
+ * 商品服务详情
+ * @description 查看商品服务详情
+ * @param int $id
+ * @return \think\Response
+ */
+ public function info(int $id)
+ {
+ return success(( new ServiceService() )->getInfo($id));
+ }
+
+ /**
+ * 添加商品服务
+ * @description 添加商品服务
+ * @return \think\Response
+ */
+ public function add()
+ {
+ $data = $this->request->params([
+ [ "service_name", "" ],
+ [ "image", "" ],
+ [ "desc", "" ],
+ ]);
+ $this->validate($data, 'addon\shop\app\validate\goods\Service.add');
+ $id = ( new ServiceService() )->add($data);
+ return success('ADD_SUCCESS', [ 'id' => $id ]);
+ }
+
+ /**
+ * 商品服务编辑
+ * @description 编辑服务编辑
+ * @param $id 商品服务id
+ * @return \think\Response
+ */
+ public function edit($id)
+ {
+ $data = $this->request->params([
+ [ "service_name", "" ],
+ [ "image", "" ],
+ [ "desc", "" ],
+ ]);
+ $this->validate($data, 'addon\shop\app\validate\goods\Service.edit');
+ ( new ServiceService() )->edit($id, $data);
+ return success('EDIT_SUCCESS');
+ }
+
+ /**
+ * 商品服务删除
+ * @description 删除服务编辑
+ * @param $id 商品服务id
+ * @return \think\Response
+ */
+ public function del(int $id)
+ {
+ ( new ServiceService() )->del($id);
+ return success('DELETE_SUCCESS');
+ }
+
+}
diff --git a/niucloud/addon/shop/app/adminapi/controller/goods/Statistics.php b/niucloud/addon/shop/app/adminapi/controller/goods/Statistics.php
new file mode 100644
index 000000000..a5217c347
--- /dev/null
+++ b/niucloud/addon/shop/app/adminapi/controller/goods/Statistics.php
@@ -0,0 +1,96 @@
+request->params([
+ [ "date", "" ],
+ ]);
+ return success(( new StatisticsService() )->getBasic($data));
+ }
+
+ /**
+ * 获取商品统计图表信息
+ * @description 查看商品统计图表信息
+ * @return \think\Response
+ */
+ public function getTrend()
+ {
+ $data = $this->request->params([
+ [ "date", "" ],
+ ]);
+ return success(( new StatisticsService() )->getTrend($data));
+ }
+
+ /**
+ * 获取商品排行榜信息
+ * @description 查看商品排行榜信息
+ * @return \think\Response
+ */
+ public function getRank()
+ {
+ $data = $this->request->params([
+ [ "category_ids", []],
+ [ "type", "access_num"],
+ [ "date", "" ],
+ [ "goods_name", "" ],
+ ]);
+ return success(( new StatisticsService() )->getRank($data));
+ }
+
+ /**
+ * 获取商品排行榜统计类型
+ * @description 获取商品排行榜统计类型
+ * @return \think\Response
+ */
+ public function getType()
+ {
+ $data = $this->request->params([
+ ]);
+ return success(( new StatisticsService() )->getType($data));
+ }
+
+ /**
+ * 同步商品统计信息
+ * @description 同步商品统计信息
+ * @return \think\Response
+ */
+ public function syncStatGoods()
+ {
+ $data = $this->request->params([
+ [ "date", [] ],
+ ]);
+ return success(( new StatisticsService() )->syncStatGoods($data['date']));
+ }
+
+
+
+
+
+}
diff --git a/niucloud/addon/shop/app/adminapi/controller/goods/VirtualGoods.php b/niucloud/addon/shop/app/adminapi/controller/goods/VirtualGoods.php
new file mode 100644
index 000000000..0c75fb066
--- /dev/null
+++ b/niucloud/addon/shop/app/adminapi/controller/goods/VirtualGoods.php
@@ -0,0 +1,168 @@
+request->params([
+ [ "goods_id", 0 ],
+ ]);
+ return success(( new VirtualGoodsService() )->getInit($data));
+ }
+
+ /**
+ * 添加商品
+ * @description 添加虚拟商品
+ * @return \think\Response
+ */
+ public function add()
+ {
+ $data = $this->request->params([
+ [ "goods_name", "" ],
+ [ "sub_title", "" ],
+ [ "goods_type", "" ],
+ [ "goods_image", "" ],
+ [ "goods_video", "" ],
+ [ "goods_category", '' ],
+ [ "brand_id", 0 ],
+ [ "label_ids", "" ],
+ [ 'service_ids', '' ],
+ [ 'supplier_id', 0 ],
+ [ "status", 0 ],
+ [ "sort", 0 ],
+ [ 'attr_ids', 0 ],
+ [ 'attr_format', '' ],
+ [ 'is_gift', 0 ],
+
+ // 规格类型,single:单规格,multi:多规格
+ [ 'spec_type', '' ],
+
+ // 单规格数据
+ [ "price", 0 ],
+ [ "market_price", 0 ],
+ [ "cost_price", 0 ],
+ [ "price", 0 ],
+ [ "stock", 0 ],
+ [ "sku_no", '' ],
+ [ "unit", "件" ],
+ [ "virtual_sale_num", 0 ],
+ [ "is_limit", 0 ],
+ [ "limit_type", 1 ],
+ [ "max_buy", 0 ],
+ [ "min_buy", 0 ],
+
+ // 多规格数据
+ [ 'goods_spec_format', '' ],
+ [ 'goods_sku_data', '' ],
+
+ // 收发货设置
+ [ 'virtual_auto_delivery', 0 ], // 虚拟商品是否自动发货
+ [ 'virtual_receive_type', 'artificial' ], // 虚拟商品收货方式,auto:自动收货,artificial:买家确认收货,verify:到店核销
+ [ 'virtual_verify_type', 0 ], // 虚拟商品核销有效期类型,0:不限,1:购买后几日有效,2:指定过期日期
+ [ 'virtual_indate', 0 ], // 虚拟到期时间
+
+ // 商品详情
+ [ "goods_desc", "" ],
+
+ [ 'member_discount', '' ], // 会员等级折扣,不参与:空,会员折扣:discount,指定会员价:fixed_price
+ [ 'poster_id', 0 ], // 海报id
+ ['form_id', 0], // 万能表单id
+ ['diy_detail_id', 0] // 自定义详情id
+ ]);
+
+ $this->validate($data, 'addon\shop\app\validate\goods\Goods.add');
+ $id = ( new VirtualGoodsService() )->add($data);
+ return success('ADD_SUCCESS', [ 'id' => $id ]);
+ }
+
+ /**
+ * 商品编辑
+ * @description 编辑虚拟商品
+ * @param $id 商品id
+ * @return \think\Response
+ */
+ public function edit($id)
+ {
+ $data = $this->request->params([
+ [ "goods_name", "" ],
+ [ "sub_title", "" ],
+ [ "goods_type", "" ],
+ [ "goods_image", "" ],
+ [ "goods_video", "" ],
+ [ "goods_category", '' ],
+ [ "brand_id", 0 ],
+ [ "label_ids", "" ],
+ [ 'service_ids', '' ],
+ [ 'supplier_id', 0 ],
+ [ "status", 0 ],
+ [ "sort", 0 ],
+ [ 'attr_ids', 0 ],
+ [ 'attr_format', '' ],
+ [ 'is_gift', 0 ],
+
+ // 规格类型,single:单规格,multi:多规格
+ [ 'spec_type', '' ],
+
+ // 单规格数据
+ [ "price", 0 ],
+ [ "market_price", 0 ],
+ [ "cost_price", 0 ],
+ [ "price", 0 ],
+ [ "stock", 0 ],
+ [ "sku_no", '' ],
+ [ "unit", "件" ],
+ [ "virtual_sale_num", 0 ],
+ [ "is_limit", 0 ],
+ [ "limit_type", 1 ],
+ [ "max_buy", 0 ],
+ [ "min_buy", 0 ],
+
+ // 多规格数据
+ [ 'goods_spec_format', '' ],
+ [ 'goods_sku_data', '' ],
+
+ // 收发货设置
+ [ 'virtual_auto_delivery', 0 ], // 虚拟商品是否自动发货
+ [ 'virtual_receive_type', 'artificial' ], // 虚拟商品收货方式,auto:自动收货,artificial:买家确认收货,verify:到店核销
+ [ 'virtual_verify_type', 0 ], // 虚拟商品核销有效期类型,0:不限,1:购买后几日有效,2:指定过期日期
+ [ 'virtual_indate', 0 ], // 虚拟到期时间
+
+ // 商品详情
+ [ "goods_desc", "" ],
+
+ [ 'member_discount', '' ], // 会员等级折扣,不参与:空,会员折扣:discount,指定会员价:fixed_price
+ [ 'poster_id', 0 ], // 海报id
+ ['form_id', 0], // 万能表单id
+ ['diy_detail_id', 0] // 自定义详情id
+ ]);
+ $this->validate($data, 'addon\shop\app\validate\goods\Goods.edit');
+ $res = ( new VirtualGoodsService() )->edit($id, $data);
+ return success('EDIT_SUCCESS');
+ }
+
+}
diff --git a/niucloud/addon/shop/app/adminapi/controller/marketing/Coupon.php b/niucloud/addon/shop/app/adminapi/controller/marketing/Coupon.php
new file mode 100644
index 000000000..76be4d68e
--- /dev/null
+++ b/niucloud/addon/shop/app/adminapi/controller/marketing/Coupon.php
@@ -0,0 +1,254 @@
+request->params([]);
+ return success(( new CouponService() )->getInit());
+ }
+
+ /**
+ * 获取商品优惠券列表
+ * @description 查看优惠券列表-分页
+ * @return \think\Response
+ */
+ public function lists()
+ {
+ $data = $this->request->params([
+ [ "title", "" ],
+ [ "status", "" ]
+ ]);
+ return success(( new CouponService() )->getPage($data));
+ }
+
+ /**
+ * 商品优惠券详情
+ * @description 查看优惠券详情
+ * @param int $id
+ * @return \think\Response
+ */
+ public function info(int $id)
+ {
+ return success(( new CouponService() )->getInfo($id));
+ }
+
+ /**
+ * 添加商品优惠券
+ * @description 添加商品优惠券
+ * @return \think\Response
+ */
+ public function add()
+ {
+ $data = $this->request->params([
+ [ "title", '' ],
+ [ "receive_time", "" ],
+ [ "remain_count", 0 ],
+ [ "limit", '' ],
+ [ "limit_count", '' ],
+ [ "price", 1 ],
+ [ "min_condition_money", '' ],
+ [ "type", 1 ],
+ [ "receive_type", '' ],
+ [ "valid_type", '' ],
+ [ "length", '' ],
+ [ "valid_time", '' ],
+ [ "goods_ids", [] ],
+ [ "goods_category_ids", "" ],
+ [ 'receive_type_time', '' ],
+ [ 'threshold', '' ]
+ ]);
+ $id = ( new CouponService() )->add($data);
+ return success('ADD_SUCCESS', [ 'id' => $id ]);
+ }
+
+ /**
+ * 商品优惠券编辑
+ * @description 编辑商品优惠券
+ * @param $id 商品优惠券id
+ * @return \think\Response
+ */
+ public function edit($id)
+ {
+ $data = $this->request->params([
+ [ "title", '' ],
+ [ "receive_time", "" ],
+ [ "remain_count", 0 ],
+ [ "limit", '' ],
+ [ "limit_count", '' ],
+ [ "price", 1 ],
+ [ "min_condition_money", '' ],
+ [ "type", 1 ],
+ [ "receive_type", '' ],
+ [ "valid_type", '' ],
+ [ "length", '' ],
+ [ "valid_time", '' ],
+ [ "goods_ids", [] ],
+ [ "goods_category_ids", "" ],
+ [ 'receive_type_time', '' ],
+ [ 'threshold', '' ]
+ ]);
+ ( new CouponService() )->edit($id, $data);
+ return success('EDIT_SUCCESS');
+ }
+
+ /**
+ * 商品优惠券删除
+ * @description 删除商品优惠券
+ * @param $id 商品优惠券id
+ * @return \think\Response
+ */
+ public function del()
+ {
+ $data = $this->request->params([
+ [ 'ids', [] ],
+ ]);
+ ( new CouponService() )->del($data['ids']);
+ return success('DELETE_SUCCESS');
+ }
+
+ /**
+ * 会员领取详情
+ * @description 查看会员领取优惠券详情
+ */
+ public function getMemberCoupon()
+ {
+ $data = $this->request->params([
+ [ 'id', '' ],
+ [ 'keywords', '' ]
+ ]);
+ return success(( new CouponService() )->getMemberCoupon($data));
+ }
+
+ /**
+ * 领取状态编辑
+ * @description 修改优惠券状态
+ */
+ public function setCouponStatus($status)
+ {
+ $data = $this->request->params([
+ [ 'id', '' ],
+ ]);
+ ( new CouponService() )->setStatus($data[ 'id' ], $status);
+ return success('EDIT_SUCCESS');
+ }
+
+ /**
+ * 优惠券选择分页列表
+ * @description 获取优惠券列表-1全部
+ * @return \think\Response
+ */
+ public function select()
+ {
+ $data = $this->request->params([
+ [ "title", "" ],
+ [ "verify_coupon_ids", "" ]
+ ]);
+ return success(( new CouponService() )->getSelectPage($data));
+ }
+
+ /**
+ * 查询选中的优惠券
+ * @description 查询选中的优惠券
+ * @return \think\Response
+ */
+ public function getSelectedLists()
+ {
+ $data = $this->request->params([
+ [ "coupon_id", '' ],
+ ]);
+ return success(( new CouponService() )->getSelectedList($data[ 'coupon_id' ]));
+ }
+
+ /**
+ * 优惠券关闭
+ * @description 批量关闭优惠券
+ */
+ public function couponInvalid()
+ {
+ $data = $this->request->params([
+ [ "ids", [] ],
+ ]);
+ ( new CouponService() )->couponInvalid($data['ids']);
+ return success('SUCCESS');
+ }
+
+ /**
+ * 获取优惠券状态
+ * @description 获取优惠券状态字典
+ */
+ public function getCouponStatus()
+ {
+ return success(data:CouponDict::getStatus());
+ }
+
+ /**
+ * 获取发送优惠券范围初始化数据
+ * @description 获取发送优惠券范围初始化数据
+ * @return \think\Response
+ */
+ public function getSendRangeInit()
+ {
+ return success([
+ 'range_type_list'=>CouponDict::getSendCouponRangeType(),
+ ]);
+ }
+
+ /**
+ * 获取发送记录分页列表
+ * @description 查看发送记录列表-分页
+ * @return \think\Response
+ */
+
+ public function getSendPages($coupon_id)
+ {
+ $data = $this->request->params([
+ [ "range_type", '' ],
+ ['create_time', []],
+ ]);
+ return success(( new CouponService() )->getSendReordsPageList($coupon_id,$data));
+ }
+
+ /**
+ * 发放优惠券
+ * @description 发放优惠券
+ * @param $coupon_id
+ * @return \think\Response
+ */
+ public function sendCoupon($coupon_id)
+ {
+ $data = $this->request->params([
+ [ "range_type", '' ],
+ [ "range_param", '' ],
+ [ "send_num", '' ],
+ ]);
+ ( new CouponService() )->sendCoupon($coupon_id,$data);
+ return success("SUCCESS");
+ }
+
+}
diff --git a/niucloud/addon/shop/app/adminapi/controller/marketing/Discount.php b/niucloud/addon/shop/app/adminapi/controller/marketing/Discount.php
new file mode 100644
index 000000000..9abdd67e5
--- /dev/null
+++ b/niucloud/addon/shop/app/adminapi/controller/marketing/Discount.php
@@ -0,0 +1,264 @@
+request->params([
+ [ "name", "" ],
+ [ "status", "" ],
+ [ "active_id", [] ],
+ ]);
+ return success(( new DiscountService() )->getPage($data));
+ }
+
+ /**
+ * 详情-基础信息
+ * @description 查看限时折扣详情
+ * @param int $discount_id
+ * @return \think\Response
+ */
+ public function info(int $discount_id)
+ {
+ return success(( new DiscountService() )->getInfo($discount_id));
+ }
+
+ /**
+ * 详情
+ * @description 查看限时折扣详情
+ * @param int $discount_id
+ * @return \think\Response
+ */
+ public function detail(int $discount_id)
+ {
+ return success(( new DiscountService() )->getDetail($discount_id));
+ }
+
+ /**
+ * 添加限时折扣
+ * @description 添加限时折扣
+ * @return \think\Response
+ */
+ public function add()
+ {
+ $data = $this->request->params([
+ [ "name", '' ],
+ [ "remark", "" ],
+ [ "start_time", '' ],
+ [ "end_time", '' ],
+ [ "goods_list", [] ],
+ ]);
+
+ $id = ( new DiscountService() )->add($data);
+ return success('ADD_SUCCESS', [ 'id' => $id ]);
+ }
+
+ /**
+ * 限时折扣编辑
+ * @description 编辑限时折扣
+ * @param int $discount_id
+ * @return \think\Response
+ */
+ public function edit(int $discount_id)
+ {
+ $data = $this->request->params([
+ [ "name", '' ],
+ [ "remark", "" ],
+ [ "start_time", '' ],
+ [ "end_time", '' ],
+ [ "goods_list", [] ],
+ ]);
+
+ ( new DiscountService() )->edit($discount_id, $data);
+ return success('EDIT_SUCCESS');
+ }
+
+ /**
+ * 限时折扣商品校验
+ * @description 限时折扣商品校验
+ * @return \think\Response
+ */
+ public function checkGoods()
+ {
+ $data = $this->request->params([
+ [ "start_time", '' ],//开始时间
+ [ "end_time", '' ],//结束时间
+ [ "goods_ids", [] ],//校验的商品id
+ [ "discount_id", 0 ],//限时折扣活动id
+ ]);
+
+ return success('SUCCESS', data:( new DiscountService() )->checkGoodsData($data));
+ }
+
+ /**
+ * 获取活动状态
+ * @description 获取限时折扣活动状态字典
+ * @return \think\Response
+ */
+ public function status()
+ {
+ return success(ActiveDict::getStatus());
+ }
+
+ /**
+ * 删除活动
+ * @description 删除限时折扣
+ * @param int $discount_id
+ * @return \think\Response
+ */
+ public function del(int $discount_id)
+ {
+ ( new DiscountService() )->del($discount_id);
+ return success('DELETE_SUCCESS');
+ }
+
+ /**
+ * 活动关闭
+ * @description 关闭限时折扣
+ * @param int $discount_id
+ * @return \think\Response
+ */
+ public function close(int $discount_id)
+ {
+ ( new DiscountService() )->discountClose($discount_id);
+ return success('SUCCESS');
+ }
+
+ /**
+ * 获取限时活动状态
+ */
+ public function discountStatus()
+ {
+ return success(DiscountDict::getStatus());
+ }
+
+ /**
+ * 批量删除活动
+ * @description 批量删除限时折扣
+ * @return \think\Response
+ */
+ public function batchDelete()
+ {
+ $data = $this->request->params([
+ [ 'ids', [] ],
+ ]);
+ ( new DiscountService() )->batchDel($data['ids']);
+ return success('SUCCESS');
+ }
+
+ /**
+ * 批量关闭活动
+ * @description 批量关闭限时折扣
+ * @return \think\Response
+ */
+ public function batchClose()
+ {
+ $data = $this->request->params([
+ [ 'ids', [] ],
+ ]);
+ ( new DiscountService() )->batchClose($data['ids']);
+ return success('SUCCESS');
+ }
+
+ /**
+ * 参与订单
+ * @description 查看限时折扣订单
+ * @param int $active_id
+ * @return \think\Response
+ */
+ public function order(int $active_id)
+ {
+ $data = $this->request->params([
+ [ 'status', '' ],
+ [ 'create_time', [] ],
+ [ 'pay_time', [] ],
+ [ 'search_type', 'order_no' ],
+ [ 'search_name', '' ],
+ ]);
+
+ return success(( new DiscountService() )->order($active_id, $data));
+ }
+
+ /**
+ * 参与会员
+ * @description 查看限时折扣会员
+ * @param int $active_id
+ * @return \think\Response
+ * @throws \think\db\exception\DbException
+ */
+ public function member(int $active_id)
+ {
+ $data = $this->request->params([
+ [ 'keyword', '' ],
+ ]);
+
+ return success(( new DiscountService() )->member($active_id, $data));
+ }
+
+ /**
+ * 参与商品
+ * @description 查看限时折扣商品
+ * @param int $active_id
+ * @return \think\Response
+ * @throws \think\db\exception\DbException
+ */
+ public function goods(int $active_id)
+ {
+ $data = $this->request->params([
+ [ 'keyword', '' ],
+ ]);
+
+ return success(( new DiscountService() )->goods($active_id, $data));
+ }
+
+ /**
+ * 获取轮播图配置
+ * @description 获取轮播图配置
+ * @return void
+ */
+ public function banner()
+ {
+ return success(( new DiscountService() )->getDiscountBannerConfig());
+ }
+
+ /**
+ * 设置轮播图配置
+ * @description 设置轮播图配置
+ * @return \think\Response
+ */
+ public function setBanner()
+ {
+ $data = $this->request->params([
+ [ 'list', [] ],
+ ]);
+ $res = ( new DiscountService() )->setConfig('SHOP_DISCOUNT_BANNER_CONFIG', $data[ 'list' ]);
+ return success('SUCCESS', $res);
+ }
+
+}
diff --git a/niucloud/addon/shop/app/adminapi/controller/marketing/Exchange.php b/niucloud/addon/shop/app/adminapi/controller/marketing/Exchange.php
new file mode 100644
index 000000000..3283b0fcc
--- /dev/null
+++ b/niucloud/addon/shop/app/adminapi/controller/marketing/Exchange.php
@@ -0,0 +1,220 @@
+request->params([
+ [ "names", "" ],
+ [ "status", "" ],
+ [ "create_time", "" ],
+ [ "active_id", [] ],
+ ]);
+ return success(( new ExchangeService() )->getPage($data));
+ }
+
+ /**
+ * 积分商品分页列表(用于弹框选择)
+ * @description 积分商城列表-全部
+ * @return \think\Response
+ */
+ public function select()
+ {
+ $data = $this->request->params([
+ [ "names", "" ],
+ [ "create_time", "" ],
+ [ 'verify_goods_ids', [] ], // 检测id集合是否存在,移除不存在的id,纠正数据准确性
+ ]);
+ return success(( new ExchangeService() )->getSelectPage($data));
+ }
+
+ /**
+ * 获取活动商品类型
+ * @description 积分商城商品类型
+ * @return \think\Response
+ */
+ public function type()
+ {
+ return success(ExchangeDict::getType());
+ }
+
+ /**
+ * 获取积分商城状态
+ * @description 积分商城状态字典
+ */
+ public function status()
+ {
+ return success(ExchangeDict::getStatus());
+ }
+
+ /**
+ * 添加积分商城
+ * @description 添加积分商城活动
+ * @return \think\Response
+ */
+ public function add()
+ {
+ $data = $this->request->params([
+ [ "type", '' ],
+ [ "names", "" ],
+ [ "title", '' ],
+ [ "image", '' ],
+ [ "product_detail", '{}' ],
+ [ "point", '' ],
+ [ "price", '' ],
+ [ "limit_num", '' ],
+ [ "content", '' ],
+ [ "sort", '' ],
+ [ "stock", '' ],
+ ]);
+ $id = ( new ExchangeService() )->add($data);
+ return success('ADD_SUCCESS', [ 'id' => $id ]);
+ }
+
+ /**
+ * 详情
+ * @description 查看积分商城详情
+ * @param int $id
+ * @return \think\Response
+ */
+ public function detail(int $id)
+ {
+ return success(( new ExchangeService() )->getDetail($id));
+ }
+
+ /**
+ * 积分商城编辑
+ * @description 编辑积分商城活动
+ * @param int $id
+ * @return \think\Response
+ */
+ public function edit(int $id)
+ {
+ $data = $this->request->params([
+ [ "type", '' ],
+ [ "names", "" ],
+ [ "title", '' ],
+ [ "image", '' ],
+ [ "product_detail", '{}' ],
+ [ "point", '' ],
+ [ "price", '' ],
+ [ "limit_num", '' ],
+ [ "content", '' ],
+ [ "sort", '' ],
+ [ "stock", '' ],
+ ]);
+ ( new ExchangeService() )->edit($id, $data);
+ return success('EDIT_SUCCESS');
+ }
+
+ /**
+ * 修改上架状态
+ * @description 修改积分商城上下架
+ * @param int $id
+ * @return \think\Response
+ */
+ public function editStatus(int $id)
+ {
+ $data = $this->request->params([
+ [ 'status', '' ],
+ ]);
+ ( new ExchangeService() )->editStatus($data, $id);
+ return success('SUCCESS');
+ }
+
+ /**
+ * 删除活动
+ * @description 删除积分商城活动
+ * @param int $id
+ * @return \think\Response
+ */
+ public function del(int $id)
+ {
+ ( new ExchangeService() )->del($id);
+ return success('DELETE_SUCCESS');
+ }
+
+ /**
+ * 批量删除活动
+ * @description 批量删除积分商城活动
+ * @return \think\Response
+ */
+ public function batchDelete()
+ {
+ $data = $this->request->params([
+ [ 'ids', [] ],
+ ]);
+ ( new ExchangeService() )->batchDelete($data['ids']);
+ return success('SUCCESS');
+ }
+
+ /**
+ * 批量下架活动
+ * @description 批量下架积分商城活动
+ * @return \think\Response
+ */
+ public function batchDown()
+ {
+ $data = $this->request->params([
+ [ 'ids', [] ],
+ ]);
+ ( new ExchangeService() )->batchDown($data['ids']);
+ return success('SUCCESS');
+ }
+
+ /**
+ * 批量上架架活动
+ * @description 批量下架积分商城活动
+ * @return \think\Response
+ */
+ public function batchUp()
+ {
+ $data = $this->request->params([
+ [ 'ids', [] ],
+ ]);
+ ( new ExchangeService() )->batchUp($data['ids']);
+ return success('SUCCESS');
+ }
+
+ /**
+ * 修改排序
+ * @description 修改积分商城活动排序
+ * @param int $id
+ * @return \think\Response
+ */
+ public function modifySort(int $id)
+ {
+ $data = $this->request->params([
+ [ 'sort', '' ],
+ ]);
+ ( new ExchangeService() )->modifySort($data, $id);
+ return success('SUCCESS');
+ }
+
+}
diff --git a/niucloud/addon/shop/app/adminapi/controller/marketing/Index.php b/niucloud/addon/shop/app/adminapi/controller/marketing/Index.php
new file mode 100644
index 000000000..6a66fdca5
--- /dev/null
+++ b/niucloud/addon/shop/app/adminapi/controller/marketing/Index.php
@@ -0,0 +1,33 @@
+request->params([
+ ['addon', ''],
+ ]);
+ return success((new MarketingService())->index($data));
+ }
+
+}
diff --git a/niucloud/addon/shop/app/adminapi/controller/marketing/Manjian.php b/niucloud/addon/shop/app/adminapi/controller/marketing/Manjian.php
new file mode 100644
index 000000000..9f94e327c
--- /dev/null
+++ b/niucloud/addon/shop/app/adminapi/controller/marketing/Manjian.php
@@ -0,0 +1,223 @@
+request->params([
+ [ "manjian_name", "" ],
+ [ "status", "" ],
+ [ "create_time", [] ],
+ [ "active_id", [] ],
+ ]);
+ return success(( new ManjianService() )->getPage($data));
+ }
+
+ /**
+ * 满减送关闭
+ * @description 关闭满减活动
+ * @return \think\Response
+ */
+ public function closeManjian($id)
+ {
+ ( new ManjianService() )->closeManjian($id);
+ return success('SUCCESS');
+ }
+
+ /**
+ * 满减送删除
+ * @description 删除满减活动
+ * @return \think\Response
+ */
+ public function del($id)
+ {
+ ( new ManjianService() )->del($id);
+ return success('DELETE_SUCCESS');
+ }
+
+ /**
+ * 满减送详情
+ * @description 查看满减活动详情
+ * @param int $id
+ * @return \think\Response
+ */
+ public function info($id)
+ {
+ return success(( new ManjianService() )->info($id));
+ }
+
+ /**
+ * 参与会员
+ * @description 查看满减活动参与会员
+ * @param int $id
+ * @return \think\Response
+ * @throws \think\db\exception\DbException
+ */
+ public function member(int $id)
+ {
+ $data = $this->request->params([
+ [ 'keyword', '' ],
+ ]);
+
+ return success(( new ManjianService() )->member($id, $data));
+ }
+
+ /**
+ * 添加满减送
+ * @description 添加满减活动
+ * @return \think\Response
+ */
+ public function add()
+ {
+ $data = $this->request->params([
+ [ "manjian_name", '' ],//名称
+ [ "condition_type", '' ],//条件类型
+ [ "goods_type", '' ],//参与商品
+ [ "join_member_type", '' ],//参与会员
+ [ "rule_type", '' ],//优惠规格
+ [ "rule_json", '' ],//优惠规则json
+ [ "goods_ids", [] ],//商品id集
+ [ "level_ids", [] ],//会员等级id集
+ [ "label_ids", [] ],//会员标签id集
+ [ "start_time", '' ],//开始时间
+ [ "end_time", '' ],//开始时间
+ [ "remark", '' ],//备注
+ [ "goods_data", [] ],//参与商品json数据
+ ]);
+
+ $res = ( new ManjianService() )->add($data);
+ if ($res[ 'code' ] === 1) {
+ return success('ADD_SUCCESS', $res);
+ } else {
+ return success('ADD_FAIL', $res);
+ }
+
+ }
+
+ /**
+ * 获取满减送编辑数据
+ * @description 获取满减送编辑数据
+ * @return \think\Response
+ */
+ public function init()
+ {
+ $data = $this->request->params([
+ [ "manjian_id", 0 ],
+ ]);
+ return success(( new ManjianService() )->getInit($data));
+ }
+
+ /**
+ * 商品编辑
+ * @description 编辑满减活动
+ * @param $id
+ * @return \think\Response
+ */
+ public function edit($id)
+ {
+ $data = $this->request->params([
+ [ "manjian_name", '' ],//名称
+ [ "condition_type", '' ],//条件类型
+ [ "goods_type", '' ],//参与商品
+ [ "join_member_type", '' ],//参与会员
+ [ "rule_type", '' ],//优惠规格
+ [ "rule_json", [] ],//优惠规则json
+ [ "goods_ids", [] ],//商品id集
+ [ "level_ids", [] ],//会员等级id集
+ [ "label_ids", [] ],//会员标签id集
+ [ "start_time", '' ],//开始时间
+ [ "end_time", '' ],//开始时间
+ [ "remark", '' ],//备注
+ [ "goods_data", [] ],//参与商品json数据
+ ]);
+
+ $res = ( new ManjianService() )->edit($id, $data);
+ if ($res[ 'code' ] === 1) {
+ return success('EDIT_SUCCESS', $res);
+ } else {
+ return success('EDIT_FAIL', $res);
+ }
+ }
+
+ /**
+ * 获取活动状态
+ * @description 获取满减送活动状态字典
+ * @return \think\Response
+ */
+ public function status()
+ {
+ return success(ManjianDict::getStatus());
+ }
+
+ /**
+ * 满减送商品校验
+ * @return \think\Response
+ */
+ public function checkGoods()
+ {
+ $data = $this->request->params([
+ [ "goods_type", '' ],//参与商品类型
+ [ "start_time", '' ],//开始时间
+ [ "end_time", '' ],//结束时间
+ [ "goods_ids", [] ],//校验的商品id
+ [ "manjian_id", 0 ],//满减活动id
+ ]);
+ return success('SUCCESS', data:( new ManjianService() )->checkGoods($data));
+ }
+
+ /**
+ * 批量关闭
+ * @description 批量关闭满减送活动
+ * @return \think\Response
+ */
+ public function batchClose()
+ {
+ $data = $this->request->params([
+ [ "manjian_id", [] ],
+ ]);
+ ( new ManjianService() )->batchClose($data);
+ return success('SUCCESS');
+ }
+
+ /**
+ * 批量删除
+ * @description 批量删除满减送活动
+ * @return \think\Response
+ */
+ public function batchDelete()
+ {
+ $data = $this->request->params([
+ [ "manjian_id", [] ],
+ ]);
+ ( new ManjianService() )->batchDelete($data);
+ return success('DELETE_SUCCESS');
+ }
+
+}
diff --git a/niucloud/addon/shop/app/adminapi/controller/marketing/Newcomer.php b/niucloud/addon/shop/app/adminapi/controller/marketing/Newcomer.php
new file mode 100644
index 000000000..dbf1f6df9
--- /dev/null
+++ b/niucloud/addon/shop/app/adminapi/controller/marketing/Newcomer.php
@@ -0,0 +1,99 @@
+request->params([
+ [ "active_status", '' ], //是否启用 active:开启 close:关闭
+ [ "active_desc", '' ],
+ [ "goods_data", '{}' ],
+ [ "validity_type", 'day' ], //有效期类型,day:x天有效,date:指定过期日期
+ [ "validity_day", 3 ], //有效天数
+ [ "validity_time", 0 ], //有效时间
+ [ "participation_way", 'never_order' ], //参与方式,never_order:从未下过单的会员,assign_time_order:指定时间内未下过单会员,assign_time_register:指定时间内注册的会员
+ [ "appoint_time", 0 ], //指定时间
+ [ "limit_num", 1 ], //限购数量
+ [ "banner_list", [] ], //广告图
+ ]);
+ ( new NewcomerService() )->setConfig($data);
+ return success('SET_SUCCESS');
+ }
+
+ /**
+ * 获取新增专享配置
+ * @description 获取新增专享配置
+ * @return \think\Response
+ */
+ public function getConfig()
+ {
+ return success(( new NewcomerService() )->getConfig());
+ }
+
+ /**
+ * 商品选择分页列表(按照单商品)
+ * @description 商品选择分页列表(按照单商品)
+ * @return \think\Response
+ */
+ public function select()
+ {
+ $data = $this->request->params([
+ [ 'keyword', '' ], // 搜索关键词
+ [ "goods_category", "" ], // 商品分类
+ [ "goods_type", "" ], // 商品分类
+ [ "select_type", "all" ], // 商品分类
+ [ 'goods_ids', [] ], // 已选商品id集合
+ [ 'sku_ids', [] ], // 已选商品规格id集合
+ [ 'verify_goods_ids', [] ], // 检测商品id集合是否存在,移除不存在的商品id,纠正数据准确性
+ [ 'verify_sku_ids', [] ] // 检测商品规格id集合是否存在,移除不存在的商品规格id,纠正数据准确性
+ ]);
+
+ return success(( new NewcomerService() )->getSelectPage($data));
+ }
+
+ /**
+ * 已选商品列表
+ * @description 获取已选商品列表
+ * @return \think\Response
+ */
+ public function selectGoodsSku()
+ {
+ $data = $this->request->params([
+ [ 'keyword', '' ], // 搜索关键词
+ [ "goods_category", "" ], // 商品分类
+ [ "goods_type", "" ], // 商品分类
+ [ 'goods_ids', '' ], // 已选商品id集合
+ [ 'verify_goods_ids', [] ], // 检测商品id集合是否存在,移除不存在的商品id,纠正数据准确性
+ [ 'verify_sku_ids', [] ] // 检测商品规格id集合是否存在,移除不存在的商品规格id,纠正数据准确性
+ ]);
+
+ return success(( new NewcomerService() )->getSelectSku($data));
+ }
+
+}
diff --git a/niucloud/addon/shop/app/adminapi/controller/order/Config.php b/niucloud/addon/shop/app/adminapi/controller/order/Config.php
new file mode 100644
index 000000000..fd7745f8d
--- /dev/null
+++ b/niucloud/addon/shop/app/adminapi/controller/order/Config.php
@@ -0,0 +1,63 @@
+request->params([
+ [ "is_close", 1 ],
+ [ "close_length", "" ],
+ [ "is_finish", "" ],
+ [ "finish_length", 1 ],
+ [ "no_allow_refund", "" ],
+ [ "refund_length", "" ],
+ [ "is_invoice", "" ],
+ [ "invoice_type", "" ],
+ [ "invoice_content", "" ],
+ [ "is_evaluate", 1 ],
+ [ "evaluate_is_to_examine", 1 ],
+ [ "evaluate_is_show", 1 ],
+ [ 'form_id', '' ]
+ ]);
+
+ ( new ConfigService() )->setConfig($data);
+ return success('SUCCESS');
+ }
+
+ /**
+ * 获取交易配置
+ * @description 获取交易配置
+ * @return \think\Response
+ */
+ public function getConfig()
+ {
+ (new Upgrade())->handle();
+ return success(( new ConfigService() )->getConfig());
+ }
+
+}
diff --git a/niucloud/addon/shop/app/adminapi/controller/order/Invoice.php b/niucloud/addon/shop/app/adminapi/controller/order/Invoice.php
new file mode 100644
index 000000000..5763ec122
--- /dev/null
+++ b/niucloud/addon/shop/app/adminapi/controller/order/Invoice.php
@@ -0,0 +1,100 @@
+request->params([
+ ['create_time', []],
+ ['invoice_time', []],
+ ['header_name', ''],
+ ['header_type', 'all'],
+ ['is_invoice', 'all'],
+ ]);
+ return success((new InvoiceService())->getPage($data));
+ }
+
+ /**
+ * 发票信息
+ * @description 查看订单发票信息
+ * @param int $order_id
+ * @return Response
+ */
+ public function info(int $id)
+ {
+ return success((new InvoiceService())->getInfo($id));
+ }
+
+ /**
+ * @description 开具发表
+ * @param int $id
+ * @return Response
+ */
+ public function invoicing(int $id) {
+ $data = $this->request->params([
+ ['remark', ''],
+ ['invoice_number', ''],
+ ['invoice_voucher', ''],
+ ]);
+ return success('SUCCESS', data:(new InvoiceService())->invoicing($id, $data));
+ }
+
+ /**
+ * @description 审核发票
+ * @param int $id
+ * @return Response
+ */
+ public function audit() {
+ $data = $this->request->params([
+ ['ids', []]
+ ]);
+ return success('SUCCESS', data:(new InvoiceService())->audit($data));
+ }
+
+ /**
+ * @description 添加发票
+ * @return Response
+ */
+ public function add()
+ {
+ $data = $this->request->params([
+ ['order_no', ''],
+ ['header_type', ''],
+ ['header_name', ''],
+ ['type', ''],
+ ['name', ''],
+ ['tax_number', ''],
+ ['mobile', ''],
+ ['email', ''],
+ ['telephone', ''],
+ ['address', ''],
+ ['bank_name', ''],
+ ['bank_card_number', ''],
+ ['pay_voucher', ''],
+ ['money', ''],
+ ]);
+ (new InvoiceService())->add($data);
+ return success('SUCCESS');
+ }
+
+}
diff --git a/niucloud/addon/shop/app/adminapi/controller/order/Order.php b/niucloud/addon/shop/app/adminapi/controller/order/Order.php
new file mode 100644
index 000000000..11c1258d9
--- /dev/null
+++ b/niucloud/addon/shop/app/adminapi/controller/order/Order.php
@@ -0,0 +1,342 @@
+request->params([
+ ['search_type', ''],
+ ['search_name', ''],
+ ['status', ''],
+ ['pay_type', ''],
+ ['order_from', ''],
+ ['create_time', []],
+ ['pay_time', []],
+ ['activity_type', ''],
+ ['keyword', ''],
+ ]);
+ return success((new OrderService())->getPage($data));
+ }
+
+ /**
+ * 订单详情
+ * @description 查看订单详情
+ * @param int $order_id
+ * @return Response
+ */
+ public function detail(int $id)
+ {
+ return success((new OrderService())->getDetail($id));
+ }
+
+ /**
+ * 获取订单状态
+ * @description 获取订单状态字典
+ * @return Response
+ */
+ public function getOrderStatus()
+ {
+ return success(OrderDict::getStatus());
+ }
+
+ /**
+ * 获取订单类型
+ * @description 获取订单类型字典
+ * @return Response
+ */
+ public function getOrderType()
+ {
+ return success(OrderDict::getOrderType());
+ }
+
+ /**
+ * 订单关闭
+ * @description 关闭订单
+ * @param $id
+ * @return Response
+ */
+ public function orderClose($id)
+ {
+ (new OrderCloseService())->close($id);
+ return success('SUCCESS');
+ }
+
+ /**
+ * 订单完成
+ * @description 完成订单
+ * @param $id
+ * @return Response
+ */
+ public function orderFinish($id)
+ {
+ (new OrderFinishService())->finish($id);
+ return success();
+ }
+
+ /**
+ * 订单发货
+ * @description 订单发货
+ * @param $id
+ * @return Response
+ */
+ public function orderDelivery()
+ {
+ $data = $this->request->params([
+ ['order_id', 0],
+ ['delivery_ids', []],//修改
+ ['order_goods_ids', []],
+ ['delivery_type', ''],
+ ['delivery_way', ''], // 发货方式,manual_write:手动填写,electronic_sheet:电子面单
+ ['express_company_id', ''],
+ ['express_number', ''],
+ ['electronic_sheet_id', 0], // 电子面单
+ ['local_deliver_id', 0],//配送员
+ ['remark', ''],//配送员
+ ]);
+ return success("DELIVERY_SUCCESS", (new OrderDeliveryService())->delivery($data));
+ }
+
+ /**
+ *
+ * 获取订单配送方式
+ * @description 获取订单配送方式
+ */
+ public function getDeliveryType()
+ {
+ $data = $this->request->params([
+ ['delivery_type', ''],
+ ]);
+ return success(OrderDeliveryDict::getChildType($data['delivery_type']));
+ }
+
+ /**
+ * 商家留言
+ * @description 设置商家留言
+ * @return Response
+ */
+ public function setShopRemark()
+ {
+ $data = $this->request->params([
+ ['order_id', ''],
+ ['shop_remark', ''],
+ ]);
+ (new OrderService())->shopRemark($data);
+ return success("SUCCESS");
+ }
+
+ /**
+ * 订单包裹
+ * @description 查看订单包裹
+ * @return Response
+ */
+ public function getOrderPackage()
+ {
+ $data = $this->request->params([
+ ['id', ''],
+ ['mobile', ''],
+ ]);
+ return success(data: (new OrderDeliveryService())->getDeliveryPackage($data));
+ }
+
+ /**
+ * 订单包裹列表
+ * @description 查看订单包裹列表-分页
+ * @return Response
+ */
+ public function getDeliveryPackageList()
+ {
+ $data = $this->request->params([
+ ['order_id', ''],
+ ]);
+ return success((new OrderDeliveryService())->getDeliveryPackageList($data));
+ }
+
+ /**
+ * 获取支付方式
+ * @description 获取订单支付方式字典
+ * @return Response
+ */
+ public function getPayType()
+ {
+ return success(PayDict::getPayType());
+ }
+
+ /**
+ * 获取订单来源
+ * @description 获取订单来源字典
+ */
+ public function getOrderFrom()
+ {
+ return success((new OrderService())->getOrderFrom());
+ }
+
+ /**
+ * 订单改价
+ * @description 修改订单价格
+ * @return void
+ */
+ public function editPrice()
+ {
+ $data = $this->request->params([
+ ['order_id', 0],
+ ['delivery_money', 0],
+ ['order_goods_data', []],
+ ]);
+ return success(data: (new OrderService())->editPrice($data));
+ }
+
+ /**
+ * 订单配送信息修改
+ * @description 修改订单配送信息
+ */
+ public function editDelivery()
+ {
+ $data = $this->request->params([
+ ['order_id', 0],
+ ['delivery_type', ''],
+ ['take_store_id', 0],
+ ['taker_name', ''],
+ ['taker_mobile', ''],
+ ['taker_province', 0],
+ ['taker_city', 0],
+ ['taker_district', 0],
+ ['taker_address', ''],
+ ['taker_full_address', ''],
+ ['taker_longitude', ''],
+ ['taker_latitude', ''],
+ ['taker_store_id', 0],
+ ]);
+ return success("SUCCESS", (new OrderService())->editDelivery($data));
+ }
+
+ /**
+ * 订单修改配送信息数据获取
+ * @description 修改订单配送信息
+ */
+ public function editDeliveryData()
+ {
+ $data = $this->request->params([
+ ['order_id', 0],
+ ['delivery_type', ''],
+ ['take_store_id', 0],
+ ['taker_name', ''],
+ ['taker_mobile', ''],
+ ['taker_province', 0],
+ ['taker_city', 0],
+ ['taker_district', 0],
+ ['taker_address', ''],
+ ['taker_full_address', ''],
+ ['taker_longitude', ''],
+ ['taker_latitude', ''],
+ ['taker_store_id', 0],
+ ]);
+ return success(data: (new OrderService())->getEditDeliveryData($data));
+ }
+
+ /**
+ *获取订单批量操作记录
+ * @description 查看订单批量操作
+ * @return Response
+ */
+ public function getOrderBatchDeliveryPage()
+ {
+ $data = $this->request->params([
+ ['status', ''],
+ ['type', ''],
+ ['main_id', ''],
+ ['create_time', []],
+ ]);
+ return success((new OrderBatchDeliveryService())->getPage($data));
+ }
+
+ /**
+ * 记录详情
+ * @description 查看批量操作订单配送记录信息
+ * @param $id
+ * @return Response
+ * @throws \think\db\exception\DbException
+ */
+ public function getOrderBatchDeliveryInfo($id)
+ {
+ return success((new OrderBatchDeliveryService())->getInfo($id));
+ }
+
+ /**
+ * 发布导入批量操作
+ * @description 批量订单发货
+ * @return Response
+ */
+ public function addBatchOrderDelivery()
+ {
+ $data = $this->request->params([
+ ['data', []],//['path' => '', 'type' => 'order/order_goods']
+ ]);
+ return success(data: (new OrderBatchDeliveryService())->addBatchOrderDelivery($data));
+ }
+
+ /**
+ * 获取操作类型
+ * @description 获取批量发送类型字典
+ * @return Response
+ */
+ public function getBatchType()
+ {
+ return success(data: OrderBatchDeliveryDict::getType());
+ }
+
+ /**
+ * 获取批量状态
+ * @description 获取订单批量发送状态字典
+ * @return Response
+ */
+ public function getBatchStatus()
+ {
+ return success(data: OrderBatchDeliveryDict::getStatus());
+ }
+
+ /**
+ * @description 删除订单
+ * @return Response
+ */
+ public function delete()
+ {
+ $params = $this->request->params([
+ ['order_ids', []]
+ ]);
+ $order_ids = $params['order_ids'];
+ $res = (new OrderService)->delete($order_ids);
+ return success("DELETE_SUCCESS");
+
+ }
+
+}
diff --git a/niucloud/addon/shop/app/adminapi/controller/refund/Refund.php b/niucloud/addon/shop/app/adminapi/controller/refund/Refund.php
new file mode 100644
index 000000000..bff5cfa71
--- /dev/null
+++ b/niucloud/addon/shop/app/adminapi/controller/refund/Refund.php
@@ -0,0 +1,122 @@
+request->params([
+ [ 'order_refund_no', '' ],
+ [ 'status', '' ],
+ [ 'create_time', [] ],
+ ]);
+ return success(( new RefundService() )->getPage($data));
+ }
+
+ /**
+ * 详情
+ * @description 查看订单退款详情
+ * @param string $order_refund_no
+ * @return Response
+ */
+ public function detail($id)
+ {
+ return success(( new RefundService() )->getDetail($id));
+ }
+
+ /**
+ * 审核退款
+ * @description 操作审核订单退款
+ * @return Response
+ */
+ public function auditApply($order_refund_no)
+ {
+ $data = $this->request->params([
+ [ 'shop_reason', '' ],
+ [ 'is_agree', '' ],
+ [ 'money', 0 ],
+ [ 'refund_address_id', 0 ]
+ ]);
+ $data[ 'order_refund_no' ] = $order_refund_no;
+ ( new RefundActionService() )->auditApply($data);
+ return success();
+ }
+
+ /**
+ * 确认收货
+ * @description 操作确认收货
+ * @return Response
+ */
+ public function auditRefundGoods($order_refund_no)
+ {
+ $data = $this->request->params([
+ [ 'shop_reason', '' ],
+ [ 'is_agree', '' ]
+ ]);
+ $data[ 'order_refund_no' ] = $order_refund_no;
+ ( new RefundActionService() )->auditRefundGoods($data);
+ return success();
+ }
+
+ /**
+ * 商家主动退款
+ * @description 操作订单主动退款
+ * @return Response
+ */
+ public function shopActiveRefund()
+ {
+ $data = $this->request->params([
+ [ 'order_goods_ids', [] ],
+ [ 'shop_active_refund_money', 0 ],
+ [ 'shop_active_refund_remark', '' ],
+ ]);
+ ( new RefundActionService() )->shopActiveRefund($data);
+ return success();
+ }
+
+ /**
+ * 获取订单项可退款金额
+ * @description 查看订单项可退款金额
+ * @return Response
+ */
+ public function getOrderRefundMoney()
+ {
+ $data = $this->request->params([
+ [ 'order_goods_ids', [] ]
+ ]);
+ return success(data: ( new RefundActionService() )->getOrderRefundMoney($data));
+ }
+
+ /**
+ * 关闭售后
+ * @description 操作关闭售后
+ * @return void
+ */
+ public function closeRefund($order_refund_no)
+ {
+ (new RefundActionService())->closeRefund($order_refund_no);
+ return success();
+ }
+
+
+}
diff --git a/niucloud/addon/shop/app/adminapi/controller/shop_address/ShopAddress.php b/niucloud/addon/shop/app/adminapi/controller/shop_address/ShopAddress.php
new file mode 100644
index 000000000..05df82bb3
--- /dev/null
+++ b/niucloud/addon/shop/app/adminapi/controller/shop_address/ShopAddress.php
@@ -0,0 +1,137 @@
+request->params([
+ [ "mobile", "" ],
+ [ "full_address", "" ]
+ ]);
+ return success(( new ShopAddressService() )->getPage($data));
+ }
+
+ /**
+ * 商家地址库详情
+ * @description 查看商家地址库详情
+ * @param int $id
+ * @return \think\Response
+ */
+ public function info(int $id)
+ {
+ return success(( new ShopAddressService() )->getInfo($id));
+ }
+
+ /**
+ * 添加商家地址库
+ * @description 添加商家地址库
+ * @return \think\Response
+ */
+ public function add()
+ {
+ $data = $this->request->params([
+ [ "contact_name", "" ],
+ [ "mobile", "" ],
+ [ "province_id", 0 ],
+ [ "city_id", 0 ],
+ [ "district_id", 0 ],
+ [ "address", "" ],
+ [ "full_address", "" ],
+ [ "lat", "" ],
+ [ "lng", "" ],
+ [ "is_delivery_address", 0 ],
+ [ "is_refund_address", 0 ],
+ [ "is_default_delivery", 0 ],
+ [ "is_default_refund", 0 ]
+ ]);
+ $this->validate($data, 'addon\shop\app\validate\shop_address\ShopAddress.add');
+ $id = ( new ShopAddressService() )->add($data);
+ return success('ADD_SUCCESS', [ 'id' => $id ]);
+ }
+
+ /**
+ * 商家地址库编辑
+ * @description 编辑商家地址库
+ * @param $id 商家地址库id
+ * @return \think\Response
+ */
+ public function edit($id)
+ {
+ $data = $this->request->params([
+ [ "contact_name", "" ],
+ [ "mobile", "" ],
+ [ "province_id", 0 ],
+ [ "city_id", 0 ],
+ [ "district_id", 0 ],
+ [ "address", "" ],
+ [ "full_address", "" ],
+ [ "lat", "" ],
+ [ "lng", "" ],
+ [ "is_delivery_address", 0 ],
+ [ "is_refund_address", 0 ],
+ [ "is_default_delivery", 0 ],
+ [ "is_default_refund", 0 ]
+ ]);
+ $this->validate($data, 'addon\shop\app\validate\shop_address\ShopAddress.edit');
+ ( new ShopAddressService() )->edit($id, $data);
+ return success('EDIT_SUCCESS');
+ }
+
+ /**
+ * 商家地址库删除
+ * @description 删除商家地址库
+ * @param $id 商家地址库id
+ * @return \think\Response
+ */
+ public function del(int $id)
+ {
+ ( new ShopAddressService() )->del($id);
+ return success('DELETE_SUCCESS');
+ }
+
+ /**
+ * @description 获取默认配送地址
+ * @return \think\Response
+ * @throws \think\db\exception\DataNotFoundException
+ * @throws \think\db\exception\DbException
+ * @throws \think\db\exception\ModelNotFoundException
+ */
+ public function defaultDelivery()
+ {
+ return success(data:( new ShopAddressService() )->getDefaultDeliveryAddress());
+ }
+
+ /**
+ * 获取商家地址(不分页)
+ * @description 获取商家地址库列表-不分页
+ */
+ public function getList()
+ {
+ return success(( new ShopAddressService() )->getList());
+ }
+}
diff --git a/niucloud/addon/shop/app/adminapi/route/route.php b/niucloud/addon/shop/app/adminapi/route/route.php
new file mode 100644
index 000000000..df3278b38
--- /dev/null
+++ b/niucloud/addon/shop/app/adminapi/route/route.php
@@ -0,0 +1,809 @@
+middleware([
+ AdminCheckToken::class,
+ AdminCheckRole::class,
+ AdminLog::class
+]);
diff --git a/niucloud/addon/shop/app/api/controller/Config.php b/niucloud/addon/shop/app/api/controller/Config.php
new file mode 100644
index 000000000..adf998caa
--- /dev/null
+++ b/niucloud/addon/shop/app/api/controller/Config.php
@@ -0,0 +1,31 @@
+getInvoiceConfig());
+ }
+
+ /**
+ * 评价设置
+ * @return \think\Response
+ */
+ public function evaluate()
+ {
+ return success(( new ConfigService() )->getEvaluateConfig());
+ }
+}
diff --git a/niucloud/addon/shop/app/api/controller/cart/Cart.php b/niucloud/addon/shop/app/api/controller/cart/Cart.php
new file mode 100644
index 000000000..91e676362
--- /dev/null
+++ b/niucloud/addon/shop/app/api/controller/cart/Cart.php
@@ -0,0 +1,128 @@
+request->params([
+ [ 'goods_id', 0 ],
+ [ 'sku_id', 0 ],
+ [ 'num', 0 ],
+ [ 'market_type', 0 ],
+ [ 'market_type_id', 0 ],
+ [ 'status', 1 ],
+ [ 'invalid_remark', '' ],
+ ]);
+ $this->validate($data, 'addon\shop\app\validate\cart\Cart.add');
+ $id = ( ( new CartService() )->add($data) );
+ return success('ADD_SUCCESS', [ 'id' => $id ]);
+ }
+
+ /**
+ * 编辑购物车
+ * @return \think\Response
+ */
+ public function edit()
+ {
+ $data = $this->request->params([
+ [ 'id', 0 ],
+ [ 'sku_id', 0 ],
+ [ 'num', 0 ],
+ ]);
+ $this->validate($data, 'addon\shop\app\validate\cart\Cart.edit');
+ ( new CartService() )->edit($data);
+ return success('EDIT_SUCCESS');
+ }
+
+ /**
+ * 购物车删除,支持批量
+ * @return \think\Response
+ */
+ public function del()
+ {
+ $data = $this->request->params([
+ [ 'ids', '' ],
+ ]);
+ ( new CartService() )->del($data);
+ return success('DELETE_SUCCESS');
+ }
+
+ /**
+ * 清空购物车
+ * @return \think\Response
+ */
+ public function clear()
+ {
+ ( new CartService() )->clear();
+ return success('DELETE_SUCCESS');
+ }
+
+ /**
+ * 获取购物车列表
+ * @return \think\Response
+ */
+ public function lists()
+ {
+ $data = $this->request->params([]);
+ return success('SUCCESS', ( new CartService() )->getList($data));
+ }
+
+ /**
+ * 获取购物车商品列表
+ * @return \think\Response
+ */
+ public function goodsLists()
+ {
+ $data = $this->request->params([]);
+ return success('SUCCESS',( new CartService() )->getGoodsList($data));
+ }
+
+ /**
+ * 获取购物车数量
+ * @return \think\Response
+ */
+ public function sum()
+ {
+ $data = $this->request->params([
+ [ 'goods_id', 0 ],
+ ]);
+ return success('SUCCESS', ( new CartService() )->getSum($data));
+ }
+
+ /**
+ * 购物车计算
+ */
+ public function calculate()
+ {
+ $data = $this->request->params([
+ [ 'sku_ids', [] ],
+ ]);
+
+ return success('SUCCESS',( new CartService() )->calculate($data));
+ }
+
+}
diff --git a/niucloud/addon/shop/app/api/controller/exchange/Exchange.php b/niucloud/addon/shop/app/api/controller/exchange/Exchange.php
new file mode 100644
index 000000000..7bab89f10
--- /dev/null
+++ b/niucloud/addon/shop/app/api/controller/exchange/Exchange.php
@@ -0,0 +1,77 @@
+request->params([
+ ["names", ""],
+ ["status", 1],
+ ["create_time", ""],
+ ['order', ''], // 排序方式(综合:空,销量:sale_num,价格:price)
+ ['sort', 'desc'], // 升序:asc,降序:desc
+ ['status', 1], // 升序:asc,降序:desc
+ ]);
+ return success((new ExchangeService())->getPage($data));
+ }
+
+ /**
+ * 商品详情
+ * @param int $id
+ * @return Response
+ */
+ public function detail(int $id)
+ {
+ return success((new ExchangeService())->getDetail($id));
+ }
+
+ /**
+ * 获取商品列表供组件调用
+ * @return \think\Response
+ */
+ public function components()
+ {
+ $data = $this->request->params([
+ ['num', 0],
+ ["names", ""],
+ ['ids', ''],
+ ['order', ''], // 排序方式(综合:空,销量:sale_num,价格:price)
+ ['sort', 'desc'], // 升序:asc,降序:desc
+ ['status', 1], // 升序:asc,降序:desc
+ ]);
+ return success((new ExchangeService())->getGoodsComponents($data));
+ }
+
+ /**
+ * 获取积分页面供组件调用
+ * @return \think\Response
+ */
+ public function getPointInfo()
+ {
+ return success((new ExchangeService())->getPointInfo());
+ }
+
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/app/api/controller/exchange/OrderCreate.php b/niucloud/addon/shop/app/api/controller/exchange/OrderCreate.php
new file mode 100644
index 000000000..aecdf1aba
--- /dev/null
+++ b/niucloud/addon/shop/app/api/controller/exchange/OrderCreate.php
@@ -0,0 +1,66 @@
+request->params([
+ ['order_key', []],
+ ['sku_data', []],
+ ['delivery', []],
+ ['discount', []],//优惠
+ ]);
+ return success('SUCCESS', (new OrderCreateService())->calculate($data));
+ }
+
+ /**
+ * 订单创建
+ * @return Response
+ */
+ public function create()
+ {
+ $data = $this->request->params([
+ ['order_key', []],
+ ['delivery', [] ],
+ ['member_remark', ''],//买家留言
+ ['invoice', []],//发票
+ ]);
+ return success('SUCCESS', (new OrderCreateService())->create($data));
+ }
+
+ /**
+ * 获取自提点
+ * @return Response
+ * @throws \think\db\exception\DataNotFoundException
+ * @throws \think\db\exception\DbException
+ * @throws \think\db\exception\ModelNotFoundException
+ */
+ public function getStore()
+ {
+ $data = $this->request->params([
+ ['latlng', []],
+ ]);
+ return success('SUCCESS', (new OrderCreateService())->getStore($data['latlng']));
+ }
+}
diff --git a/niucloud/addon/shop/app/api/controller/goods/Config.php b/niucloud/addon/shop/app/api/controller/goods/Config.php
new file mode 100644
index 000000000..458a7f545
--- /dev/null
+++ b/niucloud/addon/shop/app/api/controller/goods/Config.php
@@ -0,0 +1,26 @@
+getSearchConfig());
+ }
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/app/api/controller/goods/Evaluate.php b/niucloud/addon/shop/app/api/controller/goods/Evaluate.php
new file mode 100644
index 000000000..749249d53
--- /dev/null
+++ b/niucloud/addon/shop/app/api/controller/goods/Evaluate.php
@@ -0,0 +1,97 @@
+request->params([
+ ['goods_id', 0],
+ ['scores', []],
+ ]);
+ return success((new EvaluateService())->getPage($data));
+ }
+
+ /**
+ * 商品评价详情
+ * @param int $id
+ * @return \think\Response
+ */
+ public function info(int $id)
+ {
+ return success((new EvaluateService())->getInfo($id));
+ }
+
+ /**
+ * 添加商品评价
+ * @return \think\Response
+ */
+ public function add()
+ {
+ $data = $this->request->params([
+ ["evaluate_array", []],
+ ]);
+ (new EvaluateService())->add($data);
+ return success('SHOP_GOODS_EVALUATE_SUCCESS');
+ }
+
+ /**
+ * 评价统计
+ * @return \think\Response
+ * @throws \think\db\exception\DbException
+ */
+ public function count()
+ {
+ $data = $this->request->params([
+ ['goods_id', 0],
+ ]);
+ return success((new EvaluateService())->getCount($data['goods_id']));
+ }
+
+ /**
+ * 商品详情展示
+ * @return \think\Response
+ * @throws \think\db\exception\DataNotFoundException
+ * @throws \think\db\exception\DbException
+ * @throws \think\db\exception\ModelNotFoundException
+ */
+ public function lists()
+ {
+ $data = $this->request->params([
+ ['goods_id', 0],
+ ]);
+ return success((new EvaluateService())->getList($data['goods_id']));
+ }
+
+ /**
+ * 评价信息
+ * @param $id
+ */
+ public function getEvaluate($id)
+ {
+ return success((new EvaluateService())->getDetail($id));
+ }
+}
diff --git a/niucloud/addon/shop/app/api/controller/goods/Goods.php b/niucloud/addon/shop/app/api/controller/goods/Goods.php
new file mode 100644
index 000000000..1f862fd1a
--- /dev/null
+++ b/niucloud/addon/shop/app/api/controller/goods/Goods.php
@@ -0,0 +1,96 @@
+request->params([
+ [ 'keyword', '' ], // 搜索关键词
+ [ "goods_category", "" ], // 商品分类
+ [ "brand_id", "" ], // 品牌id
+ [ "label_ids", "" ], // 商品标签
+ [ "start_price", "" ], // 价格开始区间
+ [ "end_price", "" ], // 价格结束区间
+ [ 'order', '' ], // 排序方式(综合:空,销量:sale_num,价格:price)
+ [ 'sort', 'desc' ], // 升序:asc,降序:desc
+ [ 'coupon_id', '' ] // 优惠券id
+ ]);
+
+ return success(( new GoodsService() )->getPage($data));
+ }
+
+ /**
+ * 获取商品详情
+ * @return \think\Response
+ */
+ public function detail()
+ {
+ $data = $this->request->params([
+ [ 'goods_id', 0 ],
+ [ 'sku_id', 0 ],
+ [ 'type', '' ], // 来源营销活动类型,discount:限时折扣,newcomer_discount:新人价
+ ]);
+ return success(( new GoodsService() )->getDetail($data));
+ }
+
+ /**
+ * 获取商品规格信息,切换规格
+ */
+ public function sku()
+ {
+ $data = $this->request->params([
+ [ 'sku_id', 0 ],
+ ]);
+ return success(( new GoodsService() )->getSku($data[ 'sku_id' ]));
+ }
+
+ /**
+ * 获取商品列表供组件调用
+ * @return \think\Response
+ */
+ public function components()
+ {
+ $data = $this->request->params([
+ [ 'num', 0 ],
+ [ 'goods_ids', '' ],
+ [ 'goods_category', 0 ],
+ [ 'order', '' ], // 排序方式(综合:空,销量:sale_num,价格:price)
+ ]);
+
+ return success(( new GoodsService() )->getGoodsComponents($data));
+ }
+
+ /**
+ * 猜你喜欢
+ * @return \think\Response
+ */
+ public function recommend()
+ {
+ return success(( new GoodsService() )->getRecommend());
+ }
+
+}
diff --git a/niucloud/addon/shop/app/api/controller/goods/GoodsBrowse.php b/niucloud/addon/shop/app/api/controller/goods/GoodsBrowse.php
new file mode 100644
index 000000000..5e0e4a611
--- /dev/null
+++ b/niucloud/addon/shop/app/api/controller/goods/GoodsBrowse.php
@@ -0,0 +1,59 @@
+request->params([
+ [ 'date', [] ],
+ ]);
+ return success(( new GoodsBrowseService() )->getMemberGoodsBrowse($data));
+ }
+
+ /**
+ * 增加足迹
+ */
+ public function addGoodsBrowse()
+ {
+ $data = $this->request->params([
+ [ 'goods_id', 0 ],
+ ]);
+ return success(( new GoodsBrowseService() )->addGoodsBrowse($data));
+ }
+
+ /**
+ * 删除足迹
+ */
+ public function deleteGoodsBrowse()
+ {
+ $data = $this->request->params([
+ [ 'goods_ids', [] ],
+ ]);
+ return success(( new GoodsBrowseService() )->deleteGoodsBrowse($data));
+ }
+
+}
diff --git a/niucloud/addon/shop/app/api/controller/goods/GoodsCategory.php b/niucloud/addon/shop/app/api/controller/goods/GoodsCategory.php
new file mode 100644
index 000000000..b6fcab7c1
--- /dev/null
+++ b/niucloud/addon/shop/app/api/controller/goods/GoodsCategory.php
@@ -0,0 +1,54 @@
+getGoodsCategoryConfig());
+ }
+
+ /**
+ * 获取商品分类树结构
+ * @return \think\Response
+ */
+ public function tree()
+ {
+ return success(( new GoodsCategoryService() )->getTree());
+ }
+
+ /**
+ * 获取商品分类列表
+ * @return \think\Response
+ */
+ public function lists()
+ {
+ $data = $this->request->params([
+ [ "pid", "" ],
+ ]);
+ return success(( new GoodsCategoryService() )->getList($data));
+ }
+
+}
diff --git a/niucloud/addon/shop/app/api/controller/goods/GoodsCollect.php b/niucloud/addon/shop/app/api/controller/goods/GoodsCollect.php
new file mode 100644
index 000000000..e45b4314e
--- /dev/null
+++ b/niucloud/addon/shop/app/api/controller/goods/GoodsCollect.php
@@ -0,0 +1,57 @@
+getMemberGoodsCollectList());
+ }
+
+ /**
+ * 商品增加收藏
+ */
+ public function addGoodsCollect()
+ {
+ $data = $this->request->params([
+ [ 'goods_id', 0 ],
+ ]);
+ return success(( new GoodsCollectService() )->addGoodsCollect($data));
+ }
+
+ /**
+ * 商品取消收藏
+ */
+ public function cancelGoodsCollect()
+ {
+ $data = $this->request->params([
+ [ 'goods_ids', [] ],
+ ]);
+ ( new GoodsCollectService() )->cancelGoodsCollect($data);
+ return success('CANCEL_COLLECT_SUCCESS');
+ }
+
+}
diff --git a/niucloud/addon/shop/app/api/controller/goods/GoodsService.php b/niucloud/addon/shop/app/api/controller/goods/GoodsService.php
new file mode 100644
index 000000000..5033cfdd2
--- /dev/null
+++ b/niucloud/addon/shop/app/api/controller/goods/GoodsService.php
@@ -0,0 +1,37 @@
+request->params([
+ [ 'limit', 0 ]
+ ]);
+ return success(( new GoodsServiceService() )->getAll($data));
+ }
+
+}
diff --git a/niucloud/addon/shop/app/api/controller/goods/Rank.php b/niucloud/addon/shop/app/api/controller/goods/Rank.php
new file mode 100644
index 000000000..3dc9155d3
--- /dev/null
+++ b/niucloud/addon/shop/app/api/controller/goods/Rank.php
@@ -0,0 +1,73 @@
+getGoodsRankConfig());
+ }
+
+ /**
+ * 获取榜单列表
+ * @return \think\Response
+ */
+ public function pages()
+ {
+ $data = $this->request->params([
+ [ "name", "" ],
+ ]);
+ return success(( new RankService() )->getPage($data));
+ }
+
+ /**
+ * 获取商品列表
+ * @return \think\Response
+ */
+ public function goods()
+ {
+ $data = $this->request->params([
+ [ 'rank_id', 0 ],
+ [ 'page', 0 ],
+ [ 'limit', 0 ],
+ ]);
+ return success(( new RankService() )->getGoodsPage($data));
+ }
+
+ /**
+ * 获取商品排行榜列表供组件调用
+ * @return \think\Response
+ */
+ public function components()
+ {
+ $data = $this->request->params([
+ [ 'rank_id', 0 ],
+ [ 'limit', 3 ],
+ ]);
+
+ return success(( new RankService() )->getRankComponents($data));
+ }
+
+}
diff --git a/niucloud/addon/shop/app/api/controller/marketing/Coupon.php b/niucloud/addon/shop/app/api/controller/marketing/Coupon.php
new file mode 100644
index 000000000..29f50b98e
--- /dev/null
+++ b/niucloud/addon/shop/app/api/controller/marketing/Coupon.php
@@ -0,0 +1,127 @@
+request->params([
+ [ 'goods_id', '' ],
+ [ 'category_id', '' ],
+ [ 'type', '' ], // 优惠券类型
+ [ 'order', '' ], // 排序方式(综合:空,最新:create_time,价格:price)
+ [ 'sort', 'desc' ], // 升序:asc,降序:desc
+ ]);
+ return success(( new CouponService() )->getPage($data));
+ }
+
+ /**
+ * 优惠券详情
+ * @param int $id
+ * @return Response
+ */
+ public function detail(int $id)
+ {
+ return success(( new CouponService() )->getDetail($id));
+ }
+
+ /**
+ * 优惠券领取
+ */
+ public function receive()
+ {
+ $data = $this->request->params([
+ [ 'coupon_id', '' ],
+ [ 'type', 'receive' ],
+ [ 'number', 1 ],
+ ]);
+ ( new CouponService() )->receive($data);
+ return success('COUPON_RECEIVE_SUCCESS');
+
+ }
+
+ /**
+ * 会员已领取优惠券列表
+ * @return Response
+ */
+ public function memberCouponlists()
+ {
+ $data = $this->request->params([
+ [ 'status', '' ],
+ [ 'type', 'all' ]
+ ]);
+ return success(( new CouponService() )->getMemberPage($data));
+ }
+
+ /**
+ * 会员优惠券按状态查询数量
+ * @return Response
+ */
+ public function memberCouponStatusCount()
+ {
+ return success(data:( new CouponService() )->getCouponCountByStatus());
+ }
+
+ /**
+ * 会员已领取优惠券数量(待使用)
+ * @return Response
+ */
+ public function memberCouponCount()
+ {
+ $data = $this->request->params([
+ [ 'status', '' ]
+ ]);
+ return success(data:( new CouponService() )->getMemberCount($data));
+ }
+
+ /**
+ * 获取优惠券列表供组件调用
+ * @return Response
+ */
+ public function components()
+ {
+ $data = $this->request->params([
+ [ 'num', 0 ],
+ [ 'coupon_ids', '' ]
+ ]);
+ return success(( new CouponService() )->getCouponComponents($data));
+ }
+
+ /**
+ * 获取优惠券二维码
+ * @param int $id
+ * @return Response
+ */
+ public function qrcode(int $id)
+ {
+ return success(data:( new CouponService() )->getQrcode($id));
+ }
+
+ /**
+ * 获取优惠券类型
+ * @return Response
+ */
+ public function getCouponType()
+ {
+ return success(( new CouponService() )->getCouponType());
+ }
+
+}
diff --git a/niucloud/addon/shop/app/api/controller/marketing/Discount.php b/niucloud/addon/shop/app/api/controller/marketing/Discount.php
new file mode 100644
index 000000000..870f1d784
--- /dev/null
+++ b/niucloud/addon/shop/app/api/controller/marketing/Discount.php
@@ -0,0 +1,64 @@
+getDiscountBannerConfig());
+ }
+
+ /**
+ * 获取商品列表
+ * @return \think\Response
+ */
+ public function goods()
+ {
+ $data = $this->request->params([
+ [ 'keyword', '' ], // 搜索关键词
+ [ "goods_category", "" ], // 商品分类
+ [ "brand_id", "" ], // 品牌id
+ [ "label_ids", "" ], // 商品标签
+ [ "start_price", "" ], // 价格开始区间
+ [ "end_price", "" ], // 价格结束区间
+ [ 'order', '' ], // 排序方式(综合:空,销量:sale_num,价格:price)
+ [ 'sort', 'desc' ], // 升序:asc,降序:desc
+ [ 'discount_id', 0 ],
+ ]);
+
+ return success(( new DiscountService() )->getGoodsPage($data));
+ }
+
+ /**
+ * 获取限时折扣列表
+ * @return \think\Response
+ */
+ public function lists()
+ {
+ $data = $this->request->params([
+ [ 'active_name', '' ], // 搜索关键词
+ [ 'limit', 10 ],
+ ]);
+
+ return success(( new DiscountService() )->getList($data));
+ }
+
+}
diff --git a/niucloud/addon/shop/app/api/controller/marketing/Manjian.php b/niucloud/addon/shop/app/api/controller/marketing/Manjian.php
new file mode 100644
index 000000000..557457a8d
--- /dev/null
+++ b/niucloud/addon/shop/app/api/controller/marketing/Manjian.php
@@ -0,0 +1,34 @@
+request->params([
+ [ 'goods_id', 0 ],
+ [ 'sku_id', 0 ]
+ ]);
+ return success(( new ManjianService() )->getManjianInfo($data));
+ }
+
+}
diff --git a/niucloud/addon/shop/app/api/controller/marketing/Newcomer.php b/niucloud/addon/shop/app/api/controller/marketing/Newcomer.php
new file mode 100644
index 000000000..31a7f97ee
--- /dev/null
+++ b/niucloud/addon/shop/app/api/controller/marketing/Newcomer.php
@@ -0,0 +1,62 @@
+request->params([
+ [ 'keyword', '' ], // 搜索关键词
+ [ "goods_category", "" ], // 商品分类
+ [ "brand_id", "" ], // 品牌id
+ [ "start_price", "" ], // 价格开始区间
+ [ "end_price", "" ], // 价格结束区间
+ [ 'order', '' ], // 排序方式(综合:空,销量:sale_num,价格:price)
+ [ 'sort', 'desc' ], // 升序:asc,降序:desc
+ ]);
+
+ return success(( new NewcomerService() )->getGoodsPage($data));
+ }
+
+ /**
+ * 新人专享组件商品列表
+ * @return Response
+ */
+ public function componentsList()
+ {
+ $data = $this->request->params([
+ [ 'limit', 0 ],
+ [ 'sku_ids', [] ]
+ ]);
+ return success(( new NewcomerService() )->getComponentsList($data));
+ }
+
+ /**
+ * 获取新人专享活动规则
+ * @return Response
+ */
+ public function config()
+ {
+ return success(data:( new NewcomerService() )->getConfig());
+ }
+
+}
diff --git a/niucloud/addon/shop/app/api/controller/order/Invoice.php b/niucloud/addon/shop/app/api/controller/order/Invoice.php
new file mode 100644
index 000000000..8bbca26e6
--- /dev/null
+++ b/niucloud/addon/shop/app/api/controller/order/Invoice.php
@@ -0,0 +1,116 @@
+request->params([
+ ['status', ''],
+ ]);
+ $data = (new InvoiceService())->pages($data);
+ return success($data);
+ }
+
+ /**
+ * 发票列表
+ * @return \think\Response
+ */
+ public function info($id)
+ {
+ $data = (new InvoiceService())->detail($id);
+ return success($data);
+ }
+
+ /**
+ * 申请开发票
+ * @return \think\Response
+ */
+ public function apply()
+ {
+ $data = $this->request->params([
+ ['trade_ids', []],
+ ['header_type', ''],
+ ['header_name', ''],
+ ['type', ''],
+ ['name', ''],
+ ['tax_number', ''],
+ ['mobile', ''],
+ ['email', ''],
+ ['telephone', ''],
+ ['address', ''],
+ ['bank_name', ''],
+ ['bank_card_number', ''],
+ ['money', ''],
+ ['pay_voucher', ''],
+ ]);
+ (new InvoiceService())->apply($data);
+ return success("SUCCESS");
+ }
+
+ /**
+ * 计算发票金额
+ * @param $trade_ids
+ * @return \think\Response
+ */
+ public function calculate($trade_ids)
+ {
+ $info = (new OrderService())->calculateInvoiceMoney($trade_ids);
+ return success("SUCCESS", $info);
+ }
+
+ /**
+ * 发票列表
+ * @return \think\Response
+ */
+ public function edit($id)
+ {
+ $data = $this->request->params([
+ ['id', $id],
+ ['header_type', ''],
+ ['header_name', ''],
+ ['type', ''],
+ ['name', ''],
+ ['tax_number', ''],
+ ['mobile', ''],
+ ['email', ''],
+ ['telephone', ''],
+ ['address', ''],
+ ['bank_name', ''],
+ ['bank_card_number', ''],
+ ['money', ''],
+ ['pay_voucher', ''],
+ ]);
+ (new InvoiceService())->edit($data);
+ return success('EDIT_SUCCESS');
+ }
+
+ /**
+ * 取消发票
+ * @return \think\Response
+ */
+ public function cancel($id)
+ {
+ (new InvoiceService())->cancel($id);
+ return success('SUCCESS');
+ }
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/app/api/controller/order/Order.php b/niucloud/addon/shop/app/api/controller/order/Order.php
new file mode 100644
index 000000000..678cedd37
--- /dev/null
+++ b/niucloud/addon/shop/app/api/controller/order/Order.php
@@ -0,0 +1,98 @@
+request->params([
+ [ 'order_no', '' ],
+ [ 'status', '' ],
+ [ 'activity_type', '' ],
+ [ 'body', '' ],
+ ]);
+ return success(( new OrderService() )->getPage($data));
+ }
+
+ /**
+ * 订单详情
+ * @param $order_id
+ * @return Response
+ */
+ public function detail($order_id)
+ {
+ return success(( new OrderService() )->getDetail($order_id));
+ }
+
+ /**
+ * 获取订单状态
+ * @return Response
+ */
+ public function orderStatus()
+ {
+ return success(OrderDict::getStatus());
+ }
+
+ /**
+ * 订单关闭
+ * @param $id
+ * @return Response
+ */
+ public function orderClose($id)
+ {
+ return success(data:( new OrderService() )->close($id));
+ }
+
+ /**
+ * 订单完成
+ * @param $id
+ * @return Response
+ */
+ public function orderFinish($id)
+ {
+ return success(data:( new OrderService() )->finish($id));
+ }
+
+ public function getPackage()
+ {
+ $data = $this->request->params([
+ [ 'id', '' ],
+ [ 'mobile', '' ],
+ ]);
+ return success(( new OrderService() )->getDeliveryPackage($data));
+ }
+
+ public function getNum()
+ {
+ return success(( new OrderService() )->num());
+ }
+
+ /**
+ * 订单设置
+ * @return Response
+ */
+ public function getConfig()
+ {
+ return success(( new ConfigService() )->getConfig());
+ }
+}
diff --git a/niucloud/addon/shop/app/api/controller/order/OrderCreate.php b/niucloud/addon/shop/app/api/controller/order/OrderCreate.php
new file mode 100644
index 000000000..ed545a0be
--- /dev/null
+++ b/niucloud/addon/shop/app/api/controller/order/OrderCreate.php
@@ -0,0 +1,109 @@
+request->params([
+// ['cart_ids', []],
+// ['sku_data', []],
+// ['delivery_type', ''],//配送方式
+//
+// ]);
+// return success('SUCCESS', (new OrderCreateService())->confirm($data));
+// }
+
+ /**
+ * 计算
+ * @return Response
+ */
+ public function calculate()
+ {
+ $data = $this->request->params([
+ ['order_key', []],
+ ['cart_ids', []],
+ ['sku_data', []],
+ ['delivery', []],
+ ['is_need_recalculate', 0],
+// ['member_remark', ''],//买家留言
+ ['discount', []],//优惠
+// ['invoice', []],//发票
+ ['extend_data', []],// 扩展数据
+ ['impulse_buy_goods', []], // 顺买商品信息
+ ]);
+
+ return success('SUCCESS', ( new OrderCreateService() )->calculate($data));
+ }
+
+ /**
+ * 订单创建
+ * @return Response
+ */
+ public function create()
+ {
+ $data = $this->request->params([
+ ['order_key', []],
+ ['member_remark', ''],//买家留言
+ ['delivery', []],//配送参数
+// ['discount', []],//优惠
+ ['invoice', []],//发票
+ ['form_data', []] // 万能表单数据
+ ]);
+ return success('SUCCESS', (new OrderCreateService())->create($data));
+ }
+
+ /**
+ * 查询优惠券
+ * @return Response
+ */
+ public function getCoupon()
+ {
+ $data = $this->request->params([
+ ['order_key', []],
+ ]);
+ return success('SUCCESS', (new OrderCreateService())->getCoupon($data));
+ }
+
+ /**
+ * 获取自提点
+ * @return Response
+ * @throws \think\db\exception\DataNotFoundException
+ * @throws \think\db\exception\DbException
+ * @throws \think\db\exception\ModelNotFoundException
+ */
+ public function getStore()
+ {
+ $data = $this->request->params([
+ ['latlng', []],
+ ]);
+ return success('SUCCESS', (new OrderCreateService())->getStore($data['latlng']));
+ }
+
+ /**
+ * 获取同城配送配置项
+ * @return Response
+ */
+ public function getLocalDeliveryConfig()
+ {
+ return success(((new OrderCreateService())->getLocalDeliveryConfig()));
+ }
+}
diff --git a/niucloud/addon/shop/app/api/controller/refund/Refund.php b/niucloud/addon/shop/app/api/controller/refund/Refund.php
new file mode 100644
index 000000000..2917d14be
--- /dev/null
+++ b/niucloud/addon/shop/app/api/controller/refund/Refund.php
@@ -0,0 +1,170 @@
+request->params([
+ [ 'status', '' ],
+ ]);
+ return success(( new RefundService() )->getPage($data));
+ }
+
+ /**
+ * 订单详情
+ * @param int $order_refund_no
+ * @return Response
+ */
+ public function detail(string $order_refund_no)
+ {
+ return success(( new RefundService() )->getDetail($order_refund_no));
+ }
+
+ /**
+ * 发起退款
+ * @return Response
+ */
+ public function apply()
+ {
+ $data = $this->request->params([
+ [ 'order_id', 0 ],
+ [ 'order_goods_id', 0 ],
+ [ 'refund_type', '' ],
+ [ 'apply_money', 0 ],
+ [ 'reason', '' ],
+ [ 'remark', '' ],
+ [ 'voucher', '' ],
+ ]);
+ ( new RefundActionService() )->apply($data);
+ return success();
+ }
+
+ /**
+ * 修改退款
+ * @return Response
+ */
+ public function edit($order_refund_no)
+ {
+ $data = $this->request->params([
+ [ 'refund_type', '' ],
+ [ 'apply_money', 0 ],
+ [ 'reason', '' ],
+ [ 'remark', '' ],
+ [ 'voucher', '' ],
+ ]);
+ $data[ 'order_refund_no' ] = $order_refund_no;
+ ( new RefundActionService() )->edit($data);
+ return success();
+ }
+
+ /**
+ * 关闭退款
+ * @return Response
+ */
+ public function close($order_refund_no)
+ {
+ $data = $this->request->params([
+ [ 'refund_type', '' ],
+ [ 'apply_money', 0 ],
+ [ 'reason', '' ],
+ [ 'remark', '' ],
+ [ 'voucher', '' ],
+ ]);
+ $data[ 'order_refund_no' ] = $order_refund_no;
+ ( new RefundActionService() )->close($data);
+ return success();
+ }
+
+ /**
+ * 买家退货
+ * @return Response
+ */
+ public function delivery($order_refund_no)
+ {
+ $data = $this->request->params([
+ [ 'delivery', [] ],//{"express_number": 11, "express_company":4545, "remark":''}
+ ]);
+ $data[ 'order_refund_no' ] = $order_refund_no;
+ ( new RefundActionService() )->delivery($data);
+ return success();
+ }
+
+ /**
+ * 修改买家退货
+ * @return Response
+ */
+ public function editDelivery($order_refund_no)
+ {
+ $data = $this->request->params([
+ [ 'delivery', [] ],//{"express_number": 11, "express_company":4545, "remark":''}
+ ]);
+ $data[ 'order_refund_no' ] = $order_refund_no;
+ ( new RefundActionService() )->editDelivery($data);
+ return success();
+ }
+
+ /**
+ * 退款原因
+ * @return Response
+ */
+ public function getRefundReason()
+ {
+ return success(( new RefundActionService() )->getRefundReason());
+ }
+
+ /**
+ * 获取退款方式
+ * @return Response
+ */
+ public function getRefundType()
+ {
+ return success(OrderRefundDict::getRefundType());
+ }
+
+ /**
+ * 获取可退款信息
+ * @return void
+ */
+ public function getRefundData()
+ {
+ $data = $this->request->params([
+ [ 'order_goods_id', 0 ],
+ ]);
+ return success(data:( new RefundActionService() )->getRefundData($data));
+ }
+
+ /**
+ * 退款编辑可退款信息
+ * @return Response
+ */
+ public function getRefundDataByOrderRefundNo()
+ {
+ $data = $this->request->params([
+ [ 'order_refund_no', '' ],
+ ]);
+ return success(data:( new RefundActionService() )->getRefundDataByOrderRefundNo($data));
+ }
+}
+
+
diff --git a/niucloud/addon/shop/app/api/route/route.php b/niucloud/addon/shop/app/api/route/route.php
new file mode 100644
index 000000000..dc69d0730
--- /dev/null
+++ b/niucloud/addon/shop/app/api/route/route.php
@@ -0,0 +1,308 @@
+middleware(ApiChannel::class)
+ ->middleware(ApiCheckToken::class)//false表示不验证登录
+ ->middleware(ApiLog::class);
+
+
+Route::group('shop', function () {
+
+ /***************************************************** 购物车 ****************************************************/
+
+ // 添加购物车
+ Route::post('cart', 'addon\shop\app\api\controller\cart\Cart@add');
+
+ // 编辑购物车数量
+ Route::put('cart', 'addon\shop\app\api\controller\cart\Cart@edit');
+
+ // 购物车删除
+ Route::put('cart/delete', 'addon\shop\app\api\controller\cart\Cart@del');
+
+ // 清空购物车
+ Route::delete('cart/clear', 'addon\shop\app\api\controller\cart\Cart@clear');
+
+ // 购物车列表
+ Route::get('cart', 'addon\shop\app\api\controller\cart\Cart@lists');
+
+ // 购物车商品列表
+ Route::get('cart/goods', 'addon\shop\app\api\controller\cart\Cart@goodsLists');
+
+ // 购物车数量
+ Route::get('cart/sum', 'addon\shop\app\api\controller\cart\Cart@sum');
+
+ // 购物车计算
+ Route::get('cart/calculate', 'addon\shop\app\api\controller\cart\Cart@calculate');
+
+ /***************************************************** 订单 ****************************************************/
+
+ //列表
+ Route::get('order', 'addon\shop\app\api\controller\order\Order@lists');
+
+ //数量
+ Route::get('order/num', 'addon\shop\app\api\controller\order\Order@getNum');
+
+ //详情
+ Route::get('order/:order_id', 'addon\shop\app\api\controller\order\Order@detail');
+
+ //订单状态
+ Route::get('order/status', 'addon\shop\app\api\controller\order\Order@orderStatus');
+
+ // 订单设置
+ Route::get('order/config', 'addon\shop\app\api\controller\order\Order@getConfig');
+
+ //创建订单
+ Route::post('order_create/create', 'addon\shop\app\api\controller\order\OrderCreate@create');
+
+ //计算
+ Route::get('order_create/calculate', 'addon\shop\app\api\controller\order\OrderCreate@calculate');
+
+ //查询优惠券
+ Route::get('order_create/coupon', 'addon\shop\app\api\controller\order\OrderCreate@getCoupon');
+
+ // 查询自提点
+ Route::get('order_create/store', 'addon\shop\app\api\controller\order\OrderCreate@getStore');
+ Route::get('order_create/local', 'addon\shop\app\api\controller\order\OrderCreate@getLocalDeliveryConfig');
+
+ //获取订单确认数据
+ Route::get('confirm', 'addon\shop\app\api\controller\order\OrderCreate@confirm');
+
+ // 订单关闭
+ Route::put('order/close/:id', 'addon\shop\app\api\controller\order\Order@orderClose');
+
+ // 订单完成
+ Route::put('order/finish/:id', 'addon\shop\app\api\controller\order\Order@orderFinish');
+
+ //物流跟踪
+ Route::get('order/logistics', 'addon\shop\app\api\controller\order\Order@getPackage');
+ //发票相关
+ Route::get('order/invoice/list', 'addon\shop\app\api\controller\order\Invoice@list');
+ Route::get('order/invoice/:id', 'addon\shop\app\api\controller\order\Invoice@info');
+ Route::post('order/invoice/apply', 'addon\shop\app\api\controller\order\Invoice@apply');
+ Route::post('order/invoice/edit/:id', 'addon\shop\app\api\controller\order\Invoice@edit');
+ Route::delete('order/invoice/cancel/:id', 'addon\shop\app\api\controller\order\Invoice@cancel');
+ Route::post('order/invoice/calculate', 'addon\shop\app\api\controller\order\Invoice@calculate');
+
+ //添加优惠券
+ Route::post('coupon', 'addon\shop\app\api\controller\marketing\Coupon@receive');
+
+ //优惠券列表
+ Route::get('member/coupon', 'addon\shop\app\api\controller\marketing\Coupon@memberCouponlists');
+
+ //优惠券数量
+ Route::get('member/coupon/count', 'addon\shop\app\api\controller\marketing\Coupon@memberCouponCount');
+
+ //优惠券状态数量
+ Route::get('member/coupon/status_count', 'addon\shop\app\api\controller\marketing\Coupon@memberCouponStatusCount');
+
+ //商品收藏列表
+ Route::get('goods/collect', 'addon\shop\app\api\controller\goods\GoodsCollect@getMemberGoodsCollectList');
+
+ //商品添加收藏
+ Route::post('goods/collect/:goods_id', 'addon\shop\app\api\controller\goods\GoodsCollect@addGoodsCollect');
+
+ //商品取消收藏
+ Route::put('goods/collect', 'addon\shop\app\api\controller\goods\GoodsCollect@cancelGoodsCollect');
+
+ //商品足迹
+ Route::get('goods/browse', 'addon\shop\app\api\controller\goods\GoodsBrowse@getMemberGoodsBrowseList');
+
+ //商品足迹添加
+ Route::post('goods/browse', 'addon\shop\app\api\controller\goods\GoodsBrowse@addGoodsBrowse');
+
+ //商品足迹删除
+ Route::delete('goods/browse', 'addon\shop\app\api\controller\goods\GoodsBrowse@deleteGoodsBrowse');
+
+ //订单售后 列表
+ Route::get('order/refund', 'addon\shop\app\api\controller\refund\Refund@lists');
+
+ //订单售后 列表
+ Route::get('order/refund/:order_refund_no', 'addon\shop\app\api\controller\refund\Refund@detail');
+
+ // 查询订单项可退款信息
+ Route::get('refund/refund_data', 'addon\shop\app\api\controller\refund\Refund@getRefundData');
+
+ // 查询订单项退款信息
+ Route::get('refund/refund_data_by_no', 'addon\shop\app\api\controller\refund\Refund@getRefundDataByOrderRefundNo');
+
+ // 申请售后
+ Route::post('refund/apply', 'addon\shop\app\api\controller\refund\Refund@apply');
+
+ // 修改退款申请
+ Route::put('refund/:order_refund_no', 'addon\shop\app\api\controller\refund\Refund@edit');
+
+ // 售后退货
+ Route::post('refund/delivery/:order_refund_no', 'addon\shop\app\api\controller\refund\Refund@delivery');
+
+ // 修改售后退货信息
+ Route::put('refund/delivery/:order_refund_no', 'addon\shop\app\api\controller\refund\Refund@editDelivery');
+
+ // 取消售后
+ Route::put('refund/close/:order_refund_no', 'addon\shop\app\api\controller\refund\Refund@close');
+
+ // 退款原因
+ Route::get('refund/reason', 'addon\shop\app\api\controller\refund\Refund@getRefundReason');
+
+ // 退款方式
+ Route::get('order/refund/type', 'addon\shop\app\api\controller\refund\Refund@getRefundType');
+
+ //积分商城订单计算
+ Route::get('exchange_order/calculate', 'addon\shop\app\api\controller\exchange\OrderCreate@calculate');
+
+ //积分商城订单创建
+ Route::post('exchange_order/create', 'addon\shop\app\api\controller\exchange\OrderCreate@create');
+
+ // 发票列表
+ Route::get('invoice', 'addon\shop\app\api\controller\order\Invoice@lists');
+
+ // 发票详情
+ Route::get('invoice/:id', 'addon\shop\app\api\controller\order\Invoice@info');
+
+ /***************************************************** 满减送 ****************************************************/
+
+ // 获取商品满减优惠信息
+ Route::get('manjian/info', 'addon\shop\app\api\controller\marketing\Manjian@info');
+
+})->middleware(ApiChannel::class)
+ ->middleware(ApiCheckToken::class, true)//表示验证登录
+ ->middleware(ApiLog::class);
diff --git a/niucloud/addon/shop/app/dict/active/ActiveDict.php b/niucloud/addon/shop/app/dict/active/ActiveDict.php
new file mode 100644
index 000000000..ce80ecbec
--- /dev/null
+++ b/niucloud/addon/shop/app/dict/active/ActiveDict.php
@@ -0,0 +1,110 @@
+ get_lang('dict_shop_active_status.not_active'),
+ self::ACTIVE => get_lang('dict_shop_active_status.active'),
+ self::END => get_lang('dict_shop_active_status.end'),
+ self::CLOSE => get_lang('dict_shop_active_status.close'),
+ ];
+ if ($status == '') return $list;
+ return $list[ $status ] ?? '';
+ }
+
+ /**
+ * 活动类别
+ * @param $type
+ * @return array|mixed|string
+ */
+ public static function getClass($type = '')
+ {
+ $list = [
+ self::DISCOUNT => get_lang('dict_shop_active_class.discount'),
+ self::EXCHANGE => get_lang('dict_shop_active_class.exchange'),
+ self::MANJIANSONG => get_lang('dict_shop_active_class.manjiansong'),
+ self::NEWCOMER_DISCOUNT => get_lang('dict_shop_active_class.newcomer_discount'),
+ self::GIFTCARD => get_lang('dict_shop_active_class.newcomer_discount'),
+ self::PINTUAN => get_lang('dict_shop_active_class.newcomer_discount'),
+ ];
+ if ($type == '') return $list;
+ return $list[ $type ] ?? '';
+ }
+
+ /**
+ * 活动类型
+ * @param $type
+ * @return array|mixed|string
+ */
+ public static function getType($type = '')
+ {
+ $list = [
+ self::MEMBER => get_lang('dict_shop_active_type.member'),
+ self::GOODS => get_lang('dict_shop_active_type.goods'),
+ self::SHOP => get_lang('dict_shop_active_type.shop'),
+ ];
+ if ($type == '') return $list;
+ return $list[ $type ] ?? '';
+ }
+
+ /**
+ * 活动商品类型
+ * @param $type
+ * @return array|mixed|string
+ */
+ public static function getGoodsType($type = '')
+ {
+ $list = [
+ self::GOODS_SINGLE => get_lang('dict_shop_active_goods_type.single'),
+ self::GOODS_INDEPENDENT => get_lang('dict_shop_active_goods_type.independent'),
+ self::GOODS_SHOP => get_lang('dict_shop_active_goods_type.shop'),
+ ];
+ if ($type == '') return $list;
+ return $list[ $type ] ?? '';
+ }
+
+}
diff --git a/niucloud/addon/shop/app/dict/active/DiscountDict.php b/niucloud/addon/shop/app/dict/active/DiscountDict.php
new file mode 100644
index 000000000..80fa0744a
--- /dev/null
+++ b/niucloud/addon/shop/app/dict/active/DiscountDict.php
@@ -0,0 +1,47 @@
+ get_lang('dict_shop_active_status.not_active'),
+ self::ACTIVE => get_lang('dict_shop_active_status.active'),
+ self::END => get_lang('dict_shop_active_status.end'),
+ self::CLOSE => get_lang('dict_shop_active_status.close'),
+ ];
+ if ($status == '') return $list;
+ return $list[ $status ] ?? '';
+ }
+
+
+
+}
diff --git a/niucloud/addon/shop/app/dict/active/ExchangeDict.php b/niucloud/addon/shop/app/dict/active/ExchangeDict.php
new file mode 100644
index 000000000..c069539f1
--- /dev/null
+++ b/niucloud/addon/shop/app/dict/active/ExchangeDict.php
@@ -0,0 +1,75 @@
+ get_lang('dict_shop_point_exchange_type.goods'),
+ self::COUPON => get_lang('dict_shop_point_exchange_type.coupon'),
+ self::BALANCE => get_lang('dict_shop_point_exchange_type.balance'),
+ ];
+ if ($type == '') return $list;
+ return $list[ $type ] ?? '';
+ }
+
+
+ /**
+ * 活动状态
+ */
+ public static function getStatus($status = '')
+ {
+ $list = [
+ self::UP => '已上架',
+ self::DOWN => "已下架",
+ ];
+ if ($status == '') return $list;
+ return $list[ $status ] ?? '';
+ }
+
+
+ /**
+ * 活动类别
+ * @param $type
+ * @return array|mixed|string
+ */
+ public static function getClass($type = '')
+ {
+ $list = [
+ self::DISCOUNT => get_lang('dict_shop_active_class.exchange'),
+ ];
+ if ($type == '') return $list;
+ return $list[ $type ] ?? '';
+ }
+
+
+}
diff --git a/niucloud/addon/shop/app/dict/active/ManjianDict.php b/niucloud/addon/shop/app/dict/active/ManjianDict.php
new file mode 100644
index 000000000..6fd77647b
--- /dev/null
+++ b/niucloud/addon/shop/app/dict/active/ManjianDict.php
@@ -0,0 +1,128 @@
+ get_lang('dict_shop_manjian_condition_type.over_n_yuan'),
+ self::OVER_N_PIECE => get_lang('dict_shop_manjian_condition_type.over_n_piece'),
+ ];
+ if ($type == '') return $list;
+ return $list[ $type ] ?? '';
+ }
+
+ /**
+ * 参与类型
+ * @param $type
+ * @return array|mixed|string
+ */
+ public static function getGoodsType($type = '')
+ {
+ $list = [
+ self::ALL_GOODS => get_lang('dict_shop_manjian_goods_type.all_goods'),
+ self::SELECTED_GOODS => get_lang('dict_shop_manjian_goods_type.selected_goods'),
+ self::SELECTED_GOODS_NOT => get_lang('dict_shop_manjian_goods_type.selected_goods_not'),
+ ];
+ if ($type == '') return $list;
+ return $list[ $type ] ?? '';
+ }
+
+ /**
+ * 参与会员类型
+ * @param $type
+ * @return array|mixed|string
+ */
+ public static function getJoinMemberType($type = '')
+ {
+ $list = [
+ self::ALL_MEMBER => get_lang('dict_shop_manjian_join_member_type.all_member'),
+ self::SELECTED_MEMBER_LEVEL => get_lang('dict_shop_manjian_join_member_type.selected_member_level'),
+ self::SELECTED_MEMBER_LABEL => get_lang('dict_shop_manjian_join_member_type.selected_member_label'),
+ ];
+ if ($type == '') return $list;
+ return $list[ $type ] ?? '';
+ }
+
+ /**
+ * 优惠规格
+ * @param $type
+ * @return array|mixed|string
+ */
+ public static function getRuleType($type = '')
+ {
+ $list = [
+ self::LADDER => get_lang('dict_shop_manjian_rule_type.ladder'),
+ self::CYCLE => get_lang('dict_shop_manjian_rule_type.cycle'),
+ ];
+ if ($type == '') return $list;
+ return $list[ $type ] ?? '';
+ }
+
+ /**
+ * 状态
+ * @param $type
+ * @return array|mixed|string
+ */
+ public static function getStatus($type = '')
+ {
+ $data = [
+ self::NOT_ACTIVE => get_lang('dict_shop_manjian_status.not_active'), // 未开始
+ self::ACTIVE => get_lang('dict_shop_manjian_status.active'), // 进行中
+ self::END => get_lang('dict_shop_manjian_status.end'), // 已结束
+ self::CLOSE => get_lang('dict_shop_manjian_status.close'), // 已关闭
+ ];
+ if (!$type) {
+ return $data;
+ }
+ return $data[ $type ] ?? '';
+ }
+
+}
diff --git a/niucloud/addon/shop/app/dict/active/NewcomerDict.php b/niucloud/addon/shop/app/dict/active/NewcomerDict.php
new file mode 100644
index 000000000..03579b4cc
--- /dev/null
+++ b/niucloud/addon/shop/app/dict/active/NewcomerDict.php
@@ -0,0 +1,25 @@
+ get_lang('dict_shop_cart.normal'),
+ self::INVALID => get_lang('dict_shop_cart.invalid'),
+ ];
+ if ($status == '') return $list;
+ return $list[ $status ] ?? '';
+ }
+}
diff --git a/niucloud/addon/shop/app/dict/coupon/CouponDict.php b/niucloud/addon/shop/app/dict/coupon/CouponDict.php
new file mode 100644
index 000000000..96eb59008
--- /dev/null
+++ b/niucloud/addon/shop/app/dict/coupon/CouponDict.php
@@ -0,0 +1,142 @@
+ get_lang('dict_shop_coupon.all'),
+ self::CATEGORY => get_lang('dict_shop_coupon.category'),
+ self::GOODS => get_lang('dict_shop_coupon.goods'),
+ ];
+ if ($type == '') return $list;
+ return $list[ $type ] ?? '';
+ }
+
+ /**
+ * 领取优惠券类型
+ * @param $status
+ * @return array|mixed|string
+ */
+ public static function getReceiveType($type = '')
+ {
+ $list = [
+ self::USER => get_lang('dict_shop_coupon.user'),
+ self::GRANT => get_lang('dict_shop_coupon.grant'),
+ ];
+ if ($type == '') return $list;
+ return $list[ $type ] ?? '';
+ }
+
+
+ //未开始
+ const WAIT_START = 0;
+ //进行中
+ const NORMAL = 1;
+ //已过期
+ const EXPIRE = 2;
+ //已失效
+ const INVALID = 3;
+
+ const SEND_RANGE_ALL = 'all';
+ const SEND_RANGE_MEMBER = 'member';
+ const SEND_RANGE_MEMBER_LEVEL = 'member_level';
+ const SEND_RANGE_MEMBER_LABEL = 'member_label';
+
+ const SEND_STATUS_WAIT= 'wait';
+ const SEND_STATUS_PROGRESS= 'progress';
+ const SEND_STATUS_FINISH= 'finish';
+
+ /**
+ * 状态
+ * @param $status
+ * @return array|mixed|string
+ */
+ public static function getStatus($status = '')
+ {
+ $list = [
+ self::WAIT_START => get_lang('dict_shop_coupon.wait_start'),
+ self::NORMAL => get_lang('dict_shop_coupon.normal'),
+ self::EXPIRE => get_lang('dict_shop_coupon.expire'),
+ self::INVALID => get_lang('dict_shop_coupon.invalid'),
+ ];
+ if ($status == '') return $list;
+ return $list[ $status ] ?? '';
+ }
+
+ /**
+ * 发券范围
+ * @param $status
+ * @return array|mixed|string
+ */
+ public static function getSendCouponRangeType($range = '')
+ {
+ $list = [
+ self::SEND_RANGE_ALL => get_lang('dict_shop_send_coupon_range.all'),
+ self::SEND_RANGE_MEMBER => get_lang('dict_shop_send_coupon_range.member'),
+ self::SEND_RANGE_MEMBER_LEVEL => get_lang('dict_shop_send_coupon_range.member_level'),
+ self::SEND_RANGE_MEMBER_LABEL => get_lang('dict_shop_send_coupon_range.member_label'),
+ ];
+ if ($range == '') return $list;
+ return $list[ $range ] ?? '';
+ }
+
+ /**
+ * 发券范围描述
+ * @param $status
+ * @return array|mixed|string
+ */
+ public static function getSendCouponRangeTypeDesc($range = '')
+ {
+ $list = [
+ self::SEND_RANGE_ALL => get_lang('dict_shop_send_coupon_range_type_desc.all'),
+ self::SEND_RANGE_MEMBER => get_lang('dict_shop_send_coupon_range_type_desc.member'),
+ self::SEND_RANGE_MEMBER_LEVEL => get_lang('dict_shop_send_coupon_range_type_desc.member_level'),
+ self::SEND_RANGE_MEMBER_LABEL => get_lang('dict_shop_send_coupon_range_type_desc.member_label'),
+ ];
+ if ($range == '') return $list;
+ return $list[ $range ] ?? '';
+ }
+
+ /**
+ * 发券状态
+ * @param $status
+ * @return array|mixed|string
+ */
+ public static function getSendCouponStatus($range = '')
+ {
+ $list = [
+ self::SEND_STATUS_WAIT => get_lang('dict_shop_send_coupon_status.wait'),
+ self::SEND_STATUS_PROGRESS => get_lang('dict_shop_send_coupon_status.progress'),
+ self::SEND_STATUS_FINISH => get_lang('dict_shop_send_coupon_status.finish'),
+ ];
+ if ($range == '') return $list;
+ return $list[ $range ] ?? '';
+ }
+
+
+}
diff --git a/niucloud/addon/shop/app/dict/coupon/CouponMemberDict.php b/niucloud/addon/shop/app/dict/coupon/CouponMemberDict.php
new file mode 100644
index 000000000..e85e9fa33
--- /dev/null
+++ b/niucloud/addon/shop/app/dict/coupon/CouponMemberDict.php
@@ -0,0 +1,41 @@
+ get_lang('dict_shop_member_coupon.wait_use'),
+ self::USED => get_lang('dict_shop_member_coupon.used'),
+ self::EXPIRE => get_lang('dict_shop_member_coupon.expire'),
+ self::INVALID => get_lang('dict_shop_member_coupon.invalid'),
+ ];
+ if ($status == '') return $list;
+ return $list[$status] ?? '';
+ }
+}
diff --git a/niucloud/addon/shop/app/dict/delivery/DeliveryDict.php b/niucloud/addon/shop/app/dict/delivery/DeliveryDict.php
new file mode 100644
index 000000000..71ea9a200
--- /dev/null
+++ b/niucloud/addon/shop/app/dict/delivery/DeliveryDict.php
@@ -0,0 +1,100 @@
+ [ 'name' => '周一', 'type' => 1 ],
+ 2 => [ 'name' => '周二', 'type' => 2 ],
+ 3 => [ 'name' => '周三', 'type' => 3 ],
+ 4 => [ 'name' => '周四', 'type' => 4 ],
+ 5 => [ 'name' => '周五', 'type' => 5 ],
+ 6 => [ 'name' => '周六', 'type' => 6 ],
+ 0 => [ 'name' => '周日', 'type' => 0 ],
+ ];
+ //时间间隔 单位 分钟
+ const TIME_INTERVAL_30 = 30;
+ const TIME_INTERVAL_60 = 60;
+ const TIME_INTERVAL_90 = 90;
+ const TIME_INTERVAL_120 = 120;
+
+ /**
+ * 获取配送方式(用于订单)
+ * @param string $type
+ * @return array|array[]|string
+ */
+ public static function getType(string $type = '')
+ {
+ $data = [
+ self::EXPRESS => get_lang('dict_shop_delivery_type.express'),
+ self::LOCAL_DELIVERY => get_lang('dict_shop_delivery_type.local_delivery'),
+ self::STORE => get_lang('dict_shop_delivery_type.store'),
+ ];
+
+ if ($type == '') {
+ return $data;
+ }
+ return $data[ $type ] ?? '';
+ }
+
+ /**
+ * 获取周列表
+ * @param string $type
+ * @return array|array[]|string
+ */
+ public static function getWeekList($week = '')
+ {
+ if ($week !== '') {
+ return self::WEEK_LIST[ $week ];
+ }
+ return self::WEEK_LIST;
+ }
+
+ public static function getTimeIntervalList($time_interval = '')
+ {
+ $list = [
+ self::TIME_INTERVAL_30 => [
+ 'type' => self::TIME_INTERVAL_30,
+ 'name' => get_lang('dict_shop_delivery_store_time_interval.30'),
+ ],
+ self::TIME_INTERVAL_60 => [
+ 'type' => self::TIME_INTERVAL_60,
+ 'name' => get_lang('dict_shop_delivery_store_time_interval.60'),
+ ],
+ self::TIME_INTERVAL_90 => [
+ 'type' => self::TIME_INTERVAL_90,
+ 'name' => get_lang('dict_shop_delivery_store_time_interval.90'),
+ ],
+ self::TIME_INTERVAL_120 => [
+ 'type' => self::TIME_INTERVAL_120,
+ 'name' => get_lang('dict_shop_delivery_store_time_interval.120'),
+ ],
+ ];
+ if ($time_interval == '') return $list;
+ return $list[ $time_interval ];
+ }
+}
diff --git a/niucloud/addon/shop/app/dict/delivery/DeliveryLocalDict.php b/niucloud/addon/shop/app/dict/delivery/DeliveryLocalDict.php
new file mode 100644
index 000000000..5b2656868
--- /dev/null
+++ b/niucloud/addon/shop/app/dict/delivery/DeliveryLocalDict.php
@@ -0,0 +1,48 @@
+ [
+ 'name' => '达达配送',
+ 'column' => [ 'app_secret', 'app_key', 'shop_id', 'shop_store_no' ],
+ 'encrypt_params' => [ 'app_secret', 'app_key', 'shop_id', 'shop_store_no' ]
+ ],
+ ];
+
+ if ($type == '') {
+ return $data;
+ }
+ return $data[ $type ] ?? '';
+ }
+}
diff --git a/niucloud/addon/shop/app/dict/delivery/ElectronicSheetDict.php b/niucloud/addon/shop/app/dict/delivery/ElectronicSheetDict.php
new file mode 100644
index 000000000..ba9fd34f3
--- /dev/null
+++ b/niucloud/addon/shop/app/dict/delivery/ElectronicSheetDict.php
@@ -0,0 +1,50 @@
+ get_lang('dict_shop_delivery_electronic_sheet.cash_payment'),
+ 2 => get_lang('dict_shop_delivery_electronic_sheet.freight_collect'),
+ 3 => get_lang('dict_shop_delivery_electronic_sheet.monthly_statement')
+ ];
+ if ($type == '') return $type_list;
+ return $type_list[ $type ] ?? '';
+ }
+
+
+ /**
+ * 快递100 支付方式类型
+ * @param $type
+ * @return string|string[]
+ */
+ public static function getKd100PayType($type = '')
+ {
+ $type_list = [
+ 1 =>"SHIPPER",
+ 2 =>"CONSIGNEE",
+ 3 =>"THIRDPARTY"
+ ];
+ if ($type == '') return $type_list;
+ return $type_list[ $type ] ?? '';
+ }
+
+}
diff --git a/niucloud/addon/shop/app/dict/delivery/ShippingTemplateDict.php b/niucloud/addon/shop/app/dict/delivery/ShippingTemplateDict.php
new file mode 100644
index 000000000..4792195a8
--- /dev/null
+++ b/niucloud/addon/shop/app/dict/delivery/ShippingTemplateDict.php
@@ -0,0 +1,36 @@
+ get_lang('dict_shop_delivery.num'),
+ self::WEIGHT => get_lang('dict_shop_delivery.weight'),
+ self::VOLUME => get_lang('dict_shop_delivery.volume')
+ ];
+ if ($type == '') return $type_list;
+ return $type_list[$type] ?? '';
+ }
+}
diff --git a/niucloud/addon/shop/app/dict/diy/components.php b/niucloud/addon/shop/app/dict/diy/components.php
new file mode 100644
index 000000000..e4f59acf7
--- /dev/null
+++ b/niucloud/addon/shop/app/dict/diy/components.php
@@ -0,0 +1,977 @@
+ [
+ 'title' => get_lang('dict_diy.shop_component_type_basic'),
+ 'list' => [
+ 'GoodsList' => [
+ 'title' => '商品列表',
+ 'icon' => 'iconfont iconshangpinliebiaopc',
+ 'path' => 'edit-goods-list',
+ 'support_page' => [],
+ 'uses' => 0,
+ 'sort' => 10011,
+ 'value' => [
+ 'style' => 'style-1',
+ 'source' => 'all',
+ 'num' => 10,
+ 'goods_category' => '',
+ "goods_category_name" => "请选择",
+ 'goods_ids' => [],
+ "sortWay" => "default", // 排序方式,default:综合,sale_num:销量,price:价格
+ "goodsNameStyle" => [
+ "color" => "#303133",
+ "control" => true,
+ "fontWeight" => 'normal',
+ "isShow" => true
+ ],
+ "priceStyle" => [
+ "color" => "#FF4142",
+ "control" => true,
+ "isShow" => true
+ ],
+ "saleStyle" => [
+ "color" => "#999999",
+ "control" => true,
+ "isShow" => true
+ ],
+ "labelStyle" => [
+ "control" => true,
+ "isShow" => true
+ ],
+ "btnStyle" => [
+ "fontWeight" => false,
+ "padding" => 0,
+ "aroundRadius" => 25,
+ "cartEvent" => "detail",
+ "text" => "购买",
+ "textColor" => "#FFFFFF",
+ "startBgColor" => "#FF4142",
+ "endBgColor" => "#FF4142",
+ "style" => "button",
+ "control" => true
+ ],
+ "imgElementRounded" => 10,// 图片圆角
+ ],
+ // 组件属性
+ 'template' => [
+ "textColor" => "#303133", // 文字颜色
+ 'pageStartBgColor' => '', // 底部背景颜色(开始)
+ 'pageEndBgColor' => '', // 底部背景颜色(结束)
+ 'pageGradientAngle' => 'to bottom', // 渐变角度,从上到下(to bottom)、从左到右(to right)
+ 'componentBgUrl' => '', // 组件背景图片
+ 'componentBgAlpha' => 2, // 组件背景图片的透明度,0~10
+ "componentStartBgColor" => '', // 组件背景颜色(开始)
+ "componentEndBgColor" => '', // 组件背景颜色(结束)
+ "componentGradientAngle" => 'to bottom', // 渐变角度,上下(to bottom)、左右(to right)
+ "topRounded" => 0, // 组件上圆角
+ "bottomRounded" => 0, // 组件下圆角
+ "elementBgColor" => '', // 元素背景颜色
+ "topElementRounded" => 10,// 元素上圆角
+ "bottomElementRounded" => 10, // 元素下圆角
+ "margin" => [
+ "top" => 0, // 上边距
+ "bottom" => 0, // 下边距
+ "both" => 10 // 左右边距
+ ]
+ ]
+ ],
+ 'ShopSearch' => [
+ 'title' => '搜索',
+ 'icon' => 'iconfont iconsousuopc-1',
+ 'path' => 'edit-shop-search',
+ 'support_page' => [],
+ 'uses' => 1,
+ 'sort' => 10012,
+ 'value' => [
+ "searchStyle" => "style-1",
+ "searchLink" => [
+ "name" => ""
+ ],
+ "text" => "请输入搜索关键词",
+ "iconType" => "img",
+ "icon" => "",
+ "imageUrl" => ""
+ ],
+ // 组件属性
+ 'template' => [
+ "textColor" => "#303133", // 文字颜色
+ 'pageStartBgColor' => '', // 底部背景颜色(开始)
+ 'pageEndBgColor' => '', // 底部背景颜色(结束)
+ 'pageGradientAngle' => 'to bottom', // 渐变角度,从上到下(to bottom)、从左到右(to right)
+ 'componentBgUrl' => '', // 组件背景图片
+ 'componentBgAlpha' => 2, // 组件背景图片的透明度,0~10
+ "componentStartBgColor" => '', // 组件背景颜色(开始)
+ "componentEndBgColor" => '', // 组件背景颜色(结束)
+ "componentGradientAngle" => 'to bottom', // 渐变角度,上下(to bottom)、左右(to right)
+ "topRounded" => 0, // 组件上圆角
+ "bottomRounded" => 0, // 组件下圆角
+ "elementBgColor" => '', // 元素背景颜色
+ "topElementRounded" => 0,// 元素上圆角
+ "bottomElementRounded" => 0, // 元素下圆角
+ "margin" => [
+ "top" => 10, // 上边距
+ "bottom" => 10, // 下边距
+ "both" => 10 // 左右边距
+ ]
+ ]
+ ],
+ 'ManyGoodsList' => [
+ 'title' => '多商品组',
+ 'icon' => 'iconfont iconduoshangpinzupc',
+ 'path' => 'edit-many-goods-list',
+ 'support_page' => [],
+ 'uses' => 0,
+ 'sort' => 10013,
+ 'value' => [
+ 'style' => 'style-2',
+ 'num' => 6,
+ "sortWay" => "default", // 排序方式,default:综合,sale_num:销量,price:价格
+ "headStyle" => "style-1",
+ "aroundRadius" => 25,
+ "source" => "custom",
+ "goods_category" => '',
+ "goods_category_name" => '请选择',
+ "goodsNameStyle" => [
+ "color" => "#303133",
+ "control" => true,
+ "fontWeight" => 'normal',
+ "isShow" => true
+ ],
+ "priceStyle" => [
+ "color" => "#FF4142",
+ "control" => true,
+ "isShow" => true
+ ],
+ "saleStyle" => [
+ "color" => "#999999",
+ "control" => true,
+ "isShow" => true
+ ],
+ "labelStyle" => [
+ "control" => true,
+ "isShow" => true
+ ],
+ "btnStyle" => [
+ "fontWeight" => false,
+ "padding" => 0,
+ "aroundRadius" => 25,
+ "cartEvent" => "detail",
+ "text" => "购买",
+ "textColor" => "#FFFFFF",
+ "startBgColor" => "#FF4142",
+ "endBgColor" => "#FF4142",
+ "style" => "button",
+ "control" => true
+ ],
+ "list" => [
+ [
+ "title" => "推荐",
+ "desc" => "猜你喜欢",
+ "source" => "all",
+ "goods_category" => '',
+ "goods_category_name" => '请选择',
+ "goods_ids" => [],
+ "imageUrl" => ''
+ ]
+ ],
+ "imgElementRounded" => 0 // 图片圆角
+ ],
+ // 组件属性
+ 'template' => [
+ "textColor" => "#303133", // 文字颜色
+ 'pageStartBgColor' => '', // 底部背景颜色(开始)
+ 'pageEndBgColor' => '', // 底部背景颜色(结束)
+ 'pageGradientAngle' => 'to bottom', // 渐变角度,从上到下(to bottom)、从左到右(to right)
+ 'componentBgUrl' => '', // 组件背景图片
+ 'componentBgAlpha' => 2, // 组件背景图片的透明度,0~10
+ "componentStartBgColor" => '', // 组件背景颜色(开始)
+ "componentEndBgColor" => '', // 组件背景颜色(结束)
+ "componentGradientAngle" => 'to bottom', // 渐变角度,上下(to bottom)、左右(to right)
+ "topRounded" => 0, // 组件上圆角
+ "bottomRounded" => 0, // 组件下圆角
+ "elementBgColor" => '', // 元素背景颜色
+ "topElementRounded" => 0,// 元素上圆角
+ "bottomElementRounded" => 0, // 元素下圆角
+ "margin" => [
+ "top" => 0, // 上边距
+ "bottom" => 0, // 下边距
+ "both" => 10 // 左右边距
+ ]
+ ]
+ ],
+ 'GoodsCoupon' => [
+ 'title' => '优惠券',
+ 'icon' => 'iconfont iconyouhuiquanpc',
+ 'path' => 'edit-goods-coupon',
+ 'support_page' => [],
+ 'uses' => 0,
+ 'sort' => 10014,
+ 'value' => [
+ 'style' => 'style-1',
+ "styleName" => "风格一",
+ 'source' => 'all',
+ 'num' => 6,
+ 'couponIds' => [],
+ "btnText" => "立即领取",
+ 'couponTitle' => '先领券 再购物',
+ 'couponSubTitle' => '领券下单 享购物优惠',
+ "titleColor" => "#ffffff",
+ "subTitleColor" => "#ffffff",
+ "couponItem" => [
+ "bgColor" => "#ffffff",
+ "textColor" => "#333333",
+ "subTextColor" => "#666666",
+ "moneyColor" => "#333333",
+ "aroundRadius" => 12
+ ]
+ ],
+ // 组件属性
+ 'template' => [
+ "textColor" => "#303133", // 文字颜色
+ 'pageStartBgColor' => '', // 底部背景颜色(开始)
+ 'pageEndBgColor' => '', // 底部背景颜色(结束)
+ 'pageGradientAngle' => 'to bottom', // 渐变角度,从上到下(to bottom)、从左到右(to right)
+ 'componentBgUrl' => '', // 组件背景图片
+ 'componentBgAlpha' => 2, // 组件背景图片的透明度,0~10
+ "componentStartBgColor" => '', // 组件背景颜色(开始)
+ "componentEndBgColor" => '', // 组件背景颜色(结束)
+ "componentGradientAngle" => 'to bottom', // 渐变角度,上下(to bottom)、左右(to right)
+ "topRounded" => 0, // 组件上圆角
+ "bottomRounded" => 0, // 组件下圆角
+ "elementBgColor" => '', // 元素背景颜色
+ "topElementRounded" => 0,// 元素上圆角
+ "bottomElementRounded" => 0, // 元素下圆角
+ "margin" => [
+ "top" => 10, // 上边距
+ "bottom" => 10, // 下边距
+ "both" => 10 // 左右边距
+ ]
+ ]
+ ],
+ 'ShopMemberInfo' => [
+ 'title' => '会员信息',
+ 'icon' => 'iconfont iconhuiyuanqiandaopc',
+ 'path' => 'edit-shop-member-info',
+ 'support_page' => [ 'DIY_SHOP_MEMBER_INDEX', 'DIY_SHOP_GIFTCARD_MEMBER_INDEX' ],
+ 'uses' => 1,
+ 'sort' => 10015,
+ 'value' => [
+ "style" => "style-1",
+ "styleName" => "风格1",
+ 'bgUrl' => '',
+ 'isShowAccount' => true,
+ 'uidTextColor' => '#666666',
+ 'accountTextColor' => '#666666'
+ ],
+ ],
+ 'ShopOrderInfo' => [
+ 'title' => '订单中心',
+ 'icon' => 'iconfont icondingdanzhongxinPC-1',
+ 'path' => 'edit-shop-order-info',
+ 'support_page' => [ 'DIY_SHOP_MEMBER_INDEX' ],
+ 'uses' => 1,
+ 'sort' => 10016,
+ 'value' => [
+ "textColor" => "#303133",
+ "fontSize" => 16,
+ "fontWeight" => "normal",
+ "text" => "订单中心",
+ "more" => [
+ "text" => "全部订单",
+ "color" => "#999999",
+ ],
+ "item" => [
+ "fontSize" => 12,
+ "fontWeight" => "normal",
+ "color" => "#303133"
+ ],
+ ]
+ ],
+ 'ShopExchangeInfo' => [
+ 'title' => '积分兑换',
+ 'icon' => 'iconfont iconjifenpc',
+ 'path' => 'edit-shop-exchange-info',
+ 'support_page' => [],
+ 'uses' => 0,
+ 'sort' => 10017,
+ 'value' => [
+ 'bgUrl' => 'addon/shop/diy/point/point_index_bg.jpg',
+ ],
+ ],
+ 'ShopExchangeGoods' => [
+ 'title' => '积分商品',
+ 'icon' => 'iconfont iconjifenshangpinpc',
+ 'path' => 'edit-shop-exchange-goods',
+ 'support_page' => [],
+ 'uses' => 0,
+ 'sort' => 10018,
+ 'value' => [
+ 'style' => 'style-2',
+ 'source' => 'all',
+ 'num' => 10,
+ 'goods_category' => '',
+ "goods_category_name" => "请选择",
+ 'goods_ids' => [],
+ "sortWay" => "total_order_num", // 排序方式,total_order_num:综合,total_exchange_num:销量,price:价格
+ "goodsNameStyle" => [
+ "color" => "#333",
+ "control" => true,
+ "fontWeight" => 'normal'
+ ],
+ "priceStyle" => [
+ "mainColor" => "#FF4142",
+ "mainControl" => true,
+ "lineColor" => "#999CA7",
+ "lineControl" => true
+ ],
+ "saleStyle" => [
+ "color" => "#999999",
+ "control" => true
+ ],
+ "imgElementRounded" => 10,// 图片圆角
+ ],
+ // 组件属性
+ 'template' => [
+ "textColor" => "#303133", // 文字颜色
+ 'pageStartBgColor' => '', // 底部背景颜色(开始)
+ 'pageEndBgColor' => '', // 底部背景颜色(结束)
+ 'pageGradientAngle' => 'to bottom', // 渐变角度,从上到下(to bottom)、从左到右(to right)
+ 'componentBgUrl' => '', // 组件背景图片
+ 'componentBgAlpha' => 2, // 组件背景图片的透明度,0~10
+ "componentStartBgColor" => '', // 组件背景颜色(开始)
+ "componentEndBgColor" => '', // 组件背景颜色(结束)
+ "componentGradientAngle" => 'to bottom', // 渐变角度,上下(to bottom)、左右(to right)
+ "topRounded" => 0, // 组件上圆角
+ "bottomRounded" => 0, // 组件下圆角
+ "elementBgColor" => '', // 元素背景颜色
+ "topElementRounded" => 0,// 元素上圆角
+ "bottomElementRounded" => 0, // 元素下圆角
+ "margin" => [
+ "top" => 0, // 上边距
+ "bottom" => 0, // 下边距
+ "both" => 10 // 左右边距
+ ],
+ ]
+ ],
+ 'ShopGoodsRecommend' => [
+ 'title' => '商品推荐',
+ 'icon' => 'iconfont icona-shangpintuijianpc30',
+ 'path' => 'edit-shop-goods-recommend',
+ 'support_page' => [],
+ 'uses' => 0,
+ 'sort' => 10019,
+ 'value' => [
+ "priceStyle" => [
+ "mainColor" => "#333333",
+ ],
+ 'source' => 'all',
+ "goods_ids" => [],
+ 'list' => [
+ [
+ "title" => [
+ "text" => "今日推荐",
+ "textColor" => "#303133"
+ ],
+ "moreTitle" => [
+ "text" => "精选",
+ "textColor" => "#FFFFFF",
+ "startColor" => "#FF7234",
+ "endColor" => "#FF213F",
+ ],
+ "listFrame" => [
+ "startColor" => "#FFE5E5",
+ "endColor" => "#FFF5F0",
+ ],
+ "button" => [
+ "text" => "首单",
+ "textColor" => "#FFFFFF",
+ "color" => "#FF1128",
+ ]
+ ],
+ [
+ "title" => [
+ "text" => "品质好物",
+ "textColor" => "#303133"
+ ],
+ "moreTitle" => [
+ "text" => "精选",
+ "textColor" => "#FFFFFF",
+ "startColor" => "#F2C719",
+ "endColor" => "#FBBA08",
+ ],
+ "listFrame" => [
+ "startColor" => "#FFEFBA",
+ "endColor" => "#FFF5D7",
+ ],
+ "button" => [
+ "text" => "首单",
+ "textColor" => "#FFFFFF",
+ "color" => "#FF1128",
+ ]
+ ],
+ [
+ "title" => [
+ "text" => "热销爆款",
+ "textColor" => "#303133"
+ ],
+ "moreTitle" => [
+ "text" => "精选",
+ "textColor" => "#FFFFFF",
+ "startColor" => "#FFA629",
+ "endColor" => "#FF8E1E",
+ ],
+ "listFrame" => [
+ "startColor" => "#FFE4D9",
+ "endColor" => "#FFFBF9",
+ ],
+ "button" => [
+ "text" => "首单",
+ "textColor" => "#FFFFFF",
+ "color" => "#FF1128",
+ ]
+ ]
+ ],
+ "imgElementRounded" => 10,// 图片圆角
+ ],
+ // 组件属性
+ 'template' => [
+ "textColor" => "#303133", // 文字颜色
+ 'pageStartBgColor' => '', // 底部背景颜色(开始)
+ 'pageEndBgColor' => '', // 底部背景颜色(结束)
+ 'pageGradientAngle' => 'to bottom', // 渐变角度,从上到下(to bottom)、从左到右(to right)
+ 'componentBgUrl' => '', // 组件背景图片
+ 'componentBgAlpha' => 2, // 组件背景图片的透明度,0~10
+ "componentStartBgColor" => '', // 组件背景颜色(开始)
+ "componentEndBgColor" => '', // 组件背景颜色(结束)
+ "componentGradientAngle" => 'to bottom', // 渐变角度,上下(to bottom)、左右(to right)
+ "topRounded" => 0, // 组件上圆角
+ "bottomRounded" => 0, // 组件下圆角
+ "elementBgColor" => '', // 元素背景颜色
+ "topElementRounded" => 10,// 元素上圆角
+ "bottomElementRounded" => 10, // 元素下圆角
+ "margin" => [
+ "top" => 10, // 上边距
+ "bottom" => 10, // 下边距
+ "both" => 10 // 左右边距
+ ],
+ ]
+ ],
+ 'SingleRecommend' => [
+ 'title' => '精选推荐',
+ 'icon' => 'iconfont icona-jingxuantuijianpc30-12',
+ 'path' => 'edit-single-recommend',
+ 'support_page' => [],
+ 'uses' => 0,
+ 'sort' => 10019,
+ 'value' => [
+ "titleStyle" => [
+ 'title' => '风格1',
+ 'value' => 'style-1'
+ ],
+ 'textImg' => 'addon/shop/diy/index/style3/single_recommend_text1.png',
+ "textLink" => [
+ "name" => ""
+ ],
+ "titleColor" => "#999999",
+ "subTitle" => [
+ "text" => "更多",
+ "textColor" => "#999999",
+ "link" => [
+ "name" => ""
+ ]
+ ],
+ 'source' => 'all',
+ 'goods_ids' => [],
+ "imageHeight" => 250,
+ "list" => [
+ [
+ "link" => [
+ "name" => ""
+ ],
+ "imageUrl" => "addon/shop/diy/index/style3/single_recommend_banner1.jpg",
+ "imgWidth" => 345,
+ "imgHeight" => 495
+ ],
+ [
+ "link" => [
+ "name" => ""
+ ],
+ "imageUrl" => "addon/shop/diy/index/style3/single_recommend_banner2.jpg",
+ "imgWidth" => 345,
+ "imgHeight" => 495
+ ]
+ ],
+ "goodsNameStyle" => [
+ "color" => "#303133",
+ "control" => true,
+ "fontWeight" => 'normal'
+ ],
+ "priceStyle" => [
+ "mainColor" => "#FF4142",
+ "mainControl" => true,
+ "lineColor" => "#999CA7",
+ "lineControl" => true
+ ],
+ "saleStyle" => [
+ "color" => "#FF0000",
+ "control" => true
+ ],
+ 'topCarouselRounded' => 12,
+ 'bottomCarouselRounded' => 12,
+ 'indicatorColor' => 'rgba(255, 255, 255, 0.6)',
+ 'indicatorActiveColor' => '#ffffff',
+ ],
+ // 组件属性
+ 'template' => [
+ "textColor" => "#303133", // 文字颜色
+ 'pageStartBgColor' => '', // 底部背景颜色(开始)
+ 'pageEndBgColor' => '', // 底部背景颜色(结束)
+ 'pageGradientAngle' => 'to bottom', // 渐变角度,从上到下(to bottom)、从左到右(to right)
+ 'componentBgUrl' => '', // 组件背景图片
+ 'componentBgAlpha' => 2, // 组件背景图片的透明度,0~10
+ "componentStartBgColor" => '', // 组件背景颜色(开始)
+ "componentEndBgColor" => '', // 组件背景颜色(结束)
+ "componentGradientAngle" => 'to bottom', // 渐变角度,上下(to bottom)、左右(to right)
+ "topRounded" => 0, // 组件上圆角
+ "bottomRounded" => 0, // 组件下圆角
+ "elementBgColor" => '', // 元素背景颜色
+ "topElementRounded" => 0,// 元素上圆角
+ "bottomElementRounded" => 0, // 元素下圆角
+ "margin" => [
+ "top" => 10, // 上边距
+ "bottom" => 10, // 下边距
+ "both" => 10 // 左右边距
+ ]
+ ]
+ ],
+ 'ShopNewcomer' => [
+ 'title' => '新人专享',
+ 'icon' => 'iconfont icona-xinrenzhuanxiangpc30',
+ 'path' => 'edit-shop-newcomer',
+ 'support_page' => [],
+ 'uses' => 1,
+ 'sort' => 10020,
+ 'value' => [
+ "style" => [
+ 'title' => '风格1',
+ 'value' => 'style-1'
+ ],
+ 'textImg' => 'addon/shop/diy/newcomer/style_title_01.png',
+ "subTitle" => [
+ "text" => "查看更多",
+ "textColor" => "#FFFFFF",
+ "startColor" => "#FB792F",
+ "endColor" => "#F91700",
+ "link" => [
+ "name" => ""
+ ],
+ ],
+ "countDown" => [
+ "numberColor" => "rgba(255, 0, 0, 1)",
+ "numberBg" => [
+ "startColor" => "rgba(255, 255, 255, 1)",
+ "endColor" => ""
+ ],
+ "otherColor" => "rgba(255, 255, 255, 1)"
+ ],
+ 'source' => 'all',
+ 'num' => 10,
+ 'goods_category' => '',
+ "goods_category_name" => "请选择",
+ 'goods_ids' => [],
+ "imgElementRounded" => 10 // 图片圆角
+ ],
+ // 组件属性
+ 'template' => [
+ "textColor" => "#303133", // 文字颜色
+ 'pageStartBgColor' => '', // 底部背景颜色(开始)
+ 'pageEndBgColor' => '', // 底部背景颜色(结束)
+ 'pageGradientAngle' => 'to bottom', // 渐变角度,从上到下(to bottom)、从左到右(to right)
+ "componentStartBgColor" => '#ff6D1A', // 组件背景颜色(开始)
+ "componentEndBgColor" => 'rgba(255, 70, 56, 1)', // 组件背景颜色(结束)
+ "componentGradientAngle" => 'to right', // 渐变角度,上下(to bottom)、左右(to right)
+ "topRounded" => 12, // 组件上圆角
+ "bottomRounded" => 12, // 组件下圆角
+ "elementBgColor" => '', // 元素背景颜色
+ "topElementRounded" => 10,// 元素上圆角
+ "bottomElementRounded" => 10, // 元素下圆角
+ "margin" => [
+ "top" => 10, // 上边距
+ "bottom" => 10, // 下边距
+ "both" => 10 // 左右边距
+ ]
+ ]
+ ],
+ 'ShopGoodsRanking' => [
+ 'title' => '排行榜',
+ 'icon' => 'iconfont icona-paihangbangpc30',
+ 'path' => 'edit-shop-goods-ranking',
+ 'support_page' => [],
+ 'uses' => 0,
+ 'sort' => 10021,
+ 'value' => [
+ "list" => [
+ [
+ 'bgUrl' => 'addon/shop/rank/rank_bg_01.jpg', // 榜单背景图
+ 'text' => '热销排行榜',
+ "textColor" => "#FFFFFF",
+ "imgUrl" => "addon/shop/rank/rank_trophy.png", // 图标
+ 'subTitle' => [
+ 'text' => '查看更多',
+ 'textColor' => '#FFFFFF',
+ 'link' => [
+ 'name' => 'SHOP_GOODS_RANK',
+ "parent" => "SHOP_LINK",
+ 'title' => '商品排行榜',
+ 'url' => '/addon/shop/pages/goods/rank',
+ 'action' => '',
+ ]
+ ],
+ 'listFrame' => [
+ 'startColor' => '#FEA715',
+ 'endColor' => '#FE1E00',
+ ],
+ 'source' => 'default',
+ 'rankIds' => []
+ ],
+ [
+ 'bgUrl' => 'addon/shop/rank/rank_bg_02.jpg', // 榜单背景图
+ 'text' => '人气排行榜',
+ "textColor" => "#FFFFFF",
+ "imgUrl" => "addon/shop/rank/rank_top.png", // 图标
+ 'subTitle' => [
+ 'text' => '查看更多',
+ 'textColor' => '#FFFFFF',
+ 'link' => [
+ 'name' => 'SHOP_GOODS_RANK',
+ "parent" => "SHOP_LINK",
+ 'title' => '商品排行榜',
+ 'url' => '/addon/shop/pages/goods/rank',
+ 'action' => '',
+ ]
+ ],
+ 'listFrame' => [
+ 'startColor' => '#FEA715',
+ 'endColor' => '#FE1E00',
+ ],
+ 'source' => 'default',
+ 'rankIds' => []
+ ]
+ ],
+ ],
+ // 组件属性
+ 'template' => [
+ "textColor" => "#303133", // 文字颜色
+ 'pageStartBgColor' => '', // 底部背景颜色(开始)
+ 'pageEndBgColor' => '', // 底部背景颜色(结束)
+ 'pageGradientAngle' => 'to bottom', // 渐变角度,从上到下(to bottom)、从左到右(to right)
+ 'componentBgUrl' => '', // 组件背景图片
+ 'componentBgAlpha' => 2, // 组件背景图片的透明度,0~10
+ "componentStartBgColor" => '', // 组件背景颜色(开始)
+ "componentEndBgColor" => '', // 组件背景颜色(结束)
+ "componentGradientAngle" => 'to bottom', // 渐变角度,上下(to bottom)、左右(to right)
+ "topRounded" => 0, // 组件上圆角
+ "bottomRounded" => 0, // 组件下圆角
+ "elementBgColor" => '', // 元素背景颜色
+ "topElementRounded" => 10,// 元素上圆角
+ "bottomElementRounded" => 10, // 元素下圆角
+ "margin" => [
+ "top" => 10, // 上边距
+ "bottom" => 10, // 下边距
+ "both" => 10 // 左右边距
+ ]
+ ]
+ ]
+ ]
+ ],
+ 'SHOP_GOODS_DETAIL_COMPONENT' => [
+ 'title' => get_lang('dict_diy.shop_goods_detail_component_type_basic'),
+ 'list' => [
+ 'ShopGoodsDetailBasicInfo' => [
+ 'title' => '基础信息',
+ 'icon' => 'iconfont iconjichuxinxi',
+ 'path' => 'edit-shop-goods-detail-basic-info',
+ 'support_page' => [ 'DIY_SHOP_GOODS_DETAIL' ],
+ 'uses' => 1,
+ 'sort' => 10011,
+ 'position' => 'top_fixed', // 组件置顶标识,不能拖拽
+ 'value' => [
+ 'menuContent' => 'index,search,cart,member',
+ 'medium' => [
+ 'type' => 'square_img',
+ 'indicator' => true
+ ],
+ 'priceRegion' => [
+ 'showWay' => 'normal',
+ 'bgImg' => 'addon/shop/diy/goods_detail/style_01.jpg',
+ 'marketingBgImg' => 'addon/shop/diy/goods_detail/marketing_style_01.jpg',
+ 'goodsStyle' => [
+ 'title' => '风格1',
+ 'value' => 'style-1'
+ ],
+ 'marketingStyle' => [
+ 'title' => '风格1',
+ 'value' => 'style-1'
+ ]
+ ],
+ 'goodsInfo' => [
+ 'titleColor' => '#333333',
+ 'subTitleColor' => '#999999',
+ 'saleInfoColor' => '#999999',
+ 'priceTopRounded' => 20,
+ 'priceBottomRounded' => 0,
+ 'topRounded' => 20,
+ 'bottomRounded' => 0,
+ "priceBgColor" => '',
+ "startBgColor" => '#ffffff',
+ "endBgColor" => '#f6f6f6',
+ "priceAboutMargin" => 0,
+ "priceTopMargin" => -22,
+ "topMargin" => -17,
+ "aboutMargin" => 0
+ ],
+ 'saleInfo' => ['underlined_price','sales','stock']
+ ],
+ // 组件属性
+ 'template' => [
+ "textColor" => "#303133", // 文字颜色
+ 'pageStartBgColor' => '', // 底部背景颜色(开始)
+ 'pageEndBgColor' => '', // 底部背景颜色(结束)
+ 'pageGradientAngle' => 'to bottom', // 渐变角度,从上到下(to bottom)、从左到右(to right)
+ 'componentBgUrl' => '', // 组件背景图片
+ 'componentBgAlpha' => 2, // 组件背景图片的透明度,0~10
+ "componentStartBgColor" => '', // 组件背景颜色(开始)
+ "componentEndBgColor" => '', // 组件背景颜色(结束)
+ "componentGradientAngle" => 'to bottom', // 渐变角度,上下(to bottom)、左右(to right)
+ "topRounded" => 0, // 组件上圆角
+ "bottomRounded" => 0, // 组件下圆角
+ "elementBgColor" => '', // 元素背景颜色
+ "topElementRounded" => 0,// 元素上圆角
+ "bottomElementRounded" => 0, // 元素下圆角
+ "margin" => [
+ "top" => 0, // 上边距
+ "bottom" => 0, // 下边距
+ "both" => 0 // 左右边距
+ ]
+ ]
+ ],
+ 'ShopGoodsDetailPurchaseService' => [
+ 'title' => '商品服务',
+ 'icon' => 'iconfont iconshangpinfuwu1',
+ 'path' => 'edit-shop-goods-detail-purchase-service',
+ 'support_page' => [ 'DIY_SHOP_GOODS_DETAIL' ],
+ 'uses' => 1,
+ 'sort' => 10012,
+ 'value' => [
+ 'serviceConfig' => ['goods_service','spec_select','delivery_info','coupons','activity']
+ ],
+ // 组件属性
+ 'template' => [
+ "textColor" => "#303133", // 文字颜色
+ 'pageStartBgColor' => '', // 底部背景颜色(开始)
+ 'pageEndBgColor' => '', // 底部背景颜色(结束)
+ 'pageGradientAngle' => 'to bottom', // 渐变角度,从上到下(to bottom)、从左到右(to right)
+ 'componentBgUrl' => '', // 组件背景图片
+ 'componentBgAlpha' => 2, // 组件背景图片的透明度,0~10
+ "componentStartBgColor" => '#FFFFFF', // 组件背景颜色(开始)
+ "componentEndBgColor" => '', // 组件背景颜色(结束)
+ "componentGradientAngle" => 'to bottom', // 渐变角度,上下(to bottom)、左右(to right)
+ "topRounded" => 12, // 组件上圆角
+ "bottomRounded" => 12, // 组件下圆角
+ "elementBgColor" => '', // 元素背景颜色
+ "topElementRounded" => 0,// 元素上圆角
+ "bottomElementRounded" => 0, // 元素下圆角
+ "margin" => [
+ "top" => 12, // 上边距
+ "bottom" => 0, // 下边距
+ "both" => 10 // 左右边距
+ ]
+ ]
+ ],
+ 'ShopGoodsDetailEvaluate' => [
+ 'title' => '商品评价',
+ 'icon' => 'iconfont iconshangpinpingjia1',
+ 'path' => 'edit-shop-goods-detail-evaluate',
+ 'support_page' => [ 'DIY_SHOP_GOODS_DETAIL' ],
+ 'uses' => 1,
+ 'sort' => 10014,
+ 'value' => [
+ 'isShow' => true
+ ],
+ // 组件属性
+ 'template' => [
+ "textColor" => "#303133", // 文字颜色
+ 'pageStartBgColor' => '', // 底部背景颜色(开始)
+ 'pageEndBgColor' => '', // 底部背景颜色(结束)
+ 'pageGradientAngle' => 'to bottom', // 渐变角度,从上到下(to bottom)、从左到右(to right)
+ 'componentBgUrl' => '', // 组件背景图片
+ 'componentBgAlpha' => 2, // 组件背景图片的透明度,0~10
+ "componentStartBgColor" => '#FFFFFF', // 组件背景颜色(开始)
+ "componentEndBgColor" => '', // 组件背景颜色(结束)
+ "componentGradientAngle" => 'to bottom', // 渐变角度,上下(to bottom)、左右(to right)
+ "topRounded" => 12, // 组件上圆角
+ "bottomRounded" => 12, // 组件下圆角
+ "elementBgColor" => '', // 元素背景颜色
+ "topElementRounded" => 0,// 元素上圆角
+ "bottomElementRounded" => 0, // 元素下圆角
+ "margin" => [
+ "top" => 12, // 上边距
+ "bottom" => 0, // 下边距
+ "both" => 10 // 左右边距
+ ]
+ ]
+ ],
+ 'ShopGoodsDetailAttr' => [
+ 'title' => '商品属性',
+ 'icon' => 'iconfont iconshangpinshuxing',
+ 'path' => 'edit-shop-goods-detail-attr',
+ 'support_page' => [ 'DIY_SHOP_GOODS_DETAIL' ],
+ 'uses' => 1,
+ 'sort' => 10015,
+ 'value' => [
+ 'isShow' => true
+ ],
+ // 组件属性
+ 'template' => [
+ "textColor" => "#303133", // 文字颜色
+ 'pageStartBgColor' => '', // 底部背景颜色(开始)
+ 'pageEndBgColor' => '', // 底部背景颜色(结束)
+ 'pageGradientAngle' => 'to bottom', // 渐变角度,从上到下(to bottom)、从左到右(to right)
+ 'componentBgUrl' => '', // 组件背景图片
+ 'componentBgAlpha' => 2, // 组件背景图片的透明度,0~10
+ "componentStartBgColor" => '#FFFFFF', // 组件背景颜色(开始)
+ "componentEndBgColor" => '', // 组件背景颜色(结束)
+ "componentGradientAngle" => 'to bottom', // 渐变角度,上下(to bottom)、左右(to right)
+ "topRounded" => 12, // 组件上圆角
+ "bottomRounded" => 12, // 组件下圆角
+ "elementBgColor" => '', // 元素背景颜色
+ "topElementRounded" => 0,// 元素上圆角
+ "bottomElementRounded" => 0, // 元素下圆角
+ "margin" => [
+ "top" => 12, // 上边距
+ "bottom" => 0, // 下边距
+ "both" => 10 // 左右边距
+ ]
+ ]
+ ],
+ 'ShopGoodsDetailDesc' => [
+ 'title' => '商品详情',
+ 'icon' => 'iconfont iconshangpinxiangqing',
+ 'path' => 'edit-shop-goods-detail-desc',
+ 'support_page' => [ 'DIY_SHOP_GOODS_DETAIL' ],
+ 'uses' => 1,
+ 'sort' => 10016,
+ 'value' => [
+ 'isShow' => true
+ ],
+ // 组件属性
+ 'template' => [
+ "textColor" => "#303133", // 文字颜色
+ 'pageStartBgColor' => '', // 底部背景颜色(开始)
+ 'pageEndBgColor' => '', // 底部背景颜色(结束)
+ 'pageGradientAngle' => 'to bottom', // 渐变角度,从上到下(to bottom)、从左到右(to right)
+ 'componentBgUrl' => '', // 组件背景图片
+ 'componentBgAlpha' => 2, // 组件背景图片的透明度,0~10
+ "componentStartBgColor" => '#FFFFFF', // 组件背景颜色(开始)
+ "componentEndBgColor" => '', // 组件背景颜色(结束)
+ "componentGradientAngle" => 'to bottom', // 渐变角度,上下(to bottom)、左右(to right)
+ "topRounded" => 12, // 组件上圆角
+ "bottomRounded" => 12, // 组件下圆角
+ "elementBgColor" => '', // 元素背景颜色
+ "topElementRounded" => 0,// 元素上圆角
+ "bottomElementRounded" => 0, // 元素下圆角
+ "margin" => [
+ "top" => 12, // 上边距
+ "bottom" => 20, // 下边距
+ "both" => 10 // 左右边距
+ ]
+ ]
+ ],
+ 'ShopGoodsDetailBottom' => [
+ 'title' => '底部菜单',
+ 'icon' => 'iconfont icondibucaidan',
+ 'path' => 'edit-shop-goods-detail-bottom',
+ 'support_page' => [ 'DIY_SHOP_GOODS_DETAIL' ],
+ 'position' => 'bottom_fixed', // 组件置底标识,不能拖拽
+ 'uses' => 1,
+ 'sort' => 10017,
+ 'value' => [
+ 'menuContent' => ['index','service','cart'],
+ 'cartName' => '加入购物车',
+ 'buyName' => '立即购买',
+ 'cartIsShow' => true,
+ 'cartStyle' => [
+ "textColor" => "#FFFFFF", // 文字颜色
+ "fontSize" => 16,
+ "gradientAngle" => "to right",
+ "startColor" => "#FFB000",
+ "endColor" => "#FFA029"
+ ],
+ 'buyStyle' => [
+ "textColor" => "#FFFFFF", // 文字颜色
+ "fontSize" => 16,
+ "gradientAngle" => "to right",
+ "startColor" => "#FB7939",
+ "endColor" => "#FF4142"
+ ],
+ ],
+ // 组件属性
+ 'template' => [
+ "textColor" => "#303133", // 文字颜色
+ 'pageStartBgColor' => '', // 底部背景颜色(开始)
+ 'pageEndBgColor' => '', // 底部背景颜色(结束)
+ 'pageGradientAngle' => 'to bottom', // 渐变角度,从上到下(to bottom)、从左到右(to right)
+ 'componentBgUrl' => '', // 组件背景图片
+ 'componentBgAlpha' => 2, // 组件背景图片的透明度,0~10
+ "componentStartBgColor" => '#FFFFFF', // 组件背景颜色(开始)
+ "componentEndBgColor" => '', // 组件背景颜色(结束)
+ "componentGradientAngle" => 'to bottom', // 渐变角度,上下(to bottom)、左右(to right)
+ "topRounded" => 0, // 组件上圆角
+ "bottomRounded" => 0, // 组件下圆角
+ "elementBgColor" => '', // 元素背景颜色
+ "topElementRounded" => 0,// 元素上圆角
+ "bottomElementRounded" => 0, // 元素下圆角
+ "margin" => [
+ "top" => 0, // 上边距
+ "bottom" => 0, // 下边距
+ "both" => 0 // 左右边距
+ ]
+ ]
+ ],
+ 'ShopGoodsDetailSow' => [
+ 'title' => '种草秀',
+ 'icon' => 'iconfont iconzhongcaoxiu',
+ 'path' => 'edit-shop-goods-detail-sow',
+ 'support_page' => [ 'DIY_SHOP_GOODS_DETAIL' ],
+ 'uses' => 0,
+ 'sort' => 10018,
+ 'value' => [
+ 'isShow' => true
+ ],
+ // 组件属性
+ 'template' => [
+ "textColor" => "#303133", // 文字颜色
+ 'pageStartBgColor' => '', // 底部背景颜色(开始)
+ 'pageEndBgColor' => '', // 底部背景颜色(结束)
+ 'pageGradientAngle' => 'to bottom', // 渐变角度,从上到下(to bottom)、从左到右(to right)
+ 'componentBgUrl' => '', // 组件背景图片
+ 'componentBgAlpha' => 2, // 组件背景图片的透明度,0~10
+ "componentStartBgColor" => '#FFFFFF', // 组件背景颜色(开始)
+ "componentEndBgColor" => '', // 组件背景颜色(结束)
+ "componentGradientAngle" => 'to bottom', // 渐变角度,上下(to bottom)、左右(to right)
+ "topRounded" => 12, // 组件上圆角
+ "bottomRounded" => 12, // 组件下圆角
+ "elementBgColor" => '', // 元素背景颜色
+ "topElementRounded" => 0,// 元素上圆角
+ "bottomElementRounded" => 0, // 元素下圆角
+ "margin" => [
+ "top" => 12, // 上边距
+ "bottom" => 0, // 下边距
+ "both" => 10 // 左右边距
+ ]
+ ]
+ ]
+ ]
+ ],
+];
diff --git a/niucloud/addon/shop/app/dict/diy/links.php b/niucloud/addon/shop/app/dict/diy/links.php
new file mode 100644
index 000000000..d6571cd4f
--- /dev/null
+++ b/niucloud/addon/shop/app/dict/diy/links.php
@@ -0,0 +1,169 @@
+ [
+ 'title' => get_lang('dict_diy.shop_link'),
+ 'type' => 'folder', // 类型,folder 表示文件夹,link 表示链接
+ 'child_list' => [
+ [
+ 'name' => 'SHOP_LINK',
+ 'title' => get_lang('dict_diy.shop_link_basic'),
+ 'child_list' => [
+ [
+ 'name' => 'SHOP_INDEX',
+ 'title' => get_lang('dict_diy.shop_link_index'),
+ 'url' => '/addon/shop/pages/index',
+ 'is_share' => 1,
+ 'action' => 'decorate'
+ ],
+ [
+ 'name' => 'SHOP_GOODS_CATEGORY',
+ 'title' => get_lang('dict_diy.shop_link_goods_category'),
+ 'url' => '/addon/shop/pages/goods/category',
+ 'is_share' => 1,
+ 'action' => ''
+ ],
+ [
+ 'name' => 'SHOP_GOODS_LIST',
+ 'title' => get_lang('dict_diy.shop_link_goods_list'),
+ 'url' => '/addon/shop/pages/goods/list',
+ 'is_share' => 1,
+ 'action' => ''
+ ],
+ [
+ 'name' => 'SHOP_GOODS_RANK',
+ 'title' => get_lang('dict_diy.shop_link_goods_rank'),
+ 'url' => '/addon/shop/pages/goods/rank',
+ 'is_share' => 1,
+ 'action' => ''
+ ],
+ [
+ 'name' => 'SHOP_GOODS_SEARCH',
+ 'title' => get_lang('dict_diy.shop_link_goods_search'),
+ 'url' => '/addon/shop/pages/goods/search',
+ 'is_share' => 1,
+ 'action' => ''
+ ],
+ [
+ 'name' => 'SHOP_GOODS_CART',
+ 'title' => get_lang('dict_diy.shop_link_goods_cart'),
+ 'url' => '/addon/shop/pages/goods/cart',
+ 'is_share' => 0,
+ 'action' => ''
+ ],
+ [
+ 'name' => 'SHOP_COUPON_LIST',
+ 'title' => get_lang('dict_diy.shop_link_coupon_list'),
+ 'url' => '/addon/shop/pages/coupon/list',
+ 'is_share' => 1,
+ 'action' => ''
+ ],
+ [
+ 'name' => 'SHOP_MEMBER_INDEX',
+ 'title' => get_lang('dict_diy.page_link_member_index'),
+ 'url' => '/addon/shop/pages/member/index',
+ 'is_share' => 1,
+ 'action' => 'decorate'
+ ],
+ [
+ 'name' => 'SHOP_MY_COUPON',
+ 'title' => get_lang('dict_diy.shop_link_my_coupon'),
+ 'url' => '/addon/shop/pages/member/my_coupon',
+ 'is_share' => 0,
+ 'action' => ''
+ ],
+ [
+ 'name' => 'SHOP_MY_GOODS_COLLECT',
+ 'title' => get_lang('dict_diy.shop_link_my_goods_collect'),
+ 'url' => '/addon/shop/pages/goods/collect',
+ 'is_share' => 0,
+ 'action' => ''
+ ],
+ [
+ 'name' => 'SHOP_MY_GOODS_BROWSE',
+ 'title' => get_lang('dict_diy.shop_link_my_goods_browse'),
+ 'url' => '/addon/shop/pages/goods/browse',
+ 'is_share' => 0,
+ 'action' => ''
+ ],
+ [
+ 'name' => 'SHOP_ORDER_LIST',
+ 'title' => get_lang('dict_diy.shop_link_order_list'),
+ 'url' => '/addon/shop/pages/order/list',
+ 'is_share' => 0,
+ 'action' => ''
+ ],
+ [
+ 'name' => 'SHOP_REFUND_LIST',
+ 'title' => get_lang('dict_diy.shop_link_order_refund_list'),
+ 'url' => '/addon/shop/pages/refund/list',
+ 'is_share' => 0,
+ 'action' => ''
+ ],
+ [
+ 'name' => 'SHOP_POINT_INDEX',
+ 'title' => get_lang('dict_diy.shop_link_point_index'),
+ 'url' => '/addon/shop/pages/point/index',
+ 'is_share' => 1,
+ 'action' => ''
+ ],
+ [
+ 'name' => 'SHOP_POINT_LIST',
+ 'title' => get_lang('dict_diy.shop_link_point_list'),
+ 'url' => '/addon/shop/pages/point/list',
+ 'is_share' => 1,
+ 'action' => ''
+ ],
+ [
+ 'name' => 'SHOP_POINT_ORDER_LIST',
+ 'title' => get_lang('dict_diy.shop_link_point_order_list'),
+ 'url' => '/addon/shop/pages/point/order_list',
+ 'is_share' => 0,
+ 'action' => ''
+ ],
+ [
+ 'name' => 'SHOP_DISCOUNT_LIST',
+ 'title' => get_lang('dict_diy.shop_link_discount_list'),
+ 'url' => '/addon/shop/pages/discount/list',
+ 'is_share' => 1,
+ 'action' => ''
+ ],
+ [
+ 'name' => 'SHOP_NEWCOMER_LIST',
+ 'title' => get_lang('dict_diy.shop_link_newcomer_list'),
+ 'url' => '/addon/shop/pages/newcomer/list',
+ 'is_share' => 1,
+ 'action' => ''
+ ],
+ [
+ 'name' => 'SHOP_INVOICE_LIST',
+ 'title' => get_lang('dict_diy.shop_link_invoice_list'),
+ 'url' => '/addon/shop/pages/invoice/list',
+ 'is_share' => 1,
+ 'action' => ''
+ ],
+ ]
+ ],
+ [
+ 'name' => 'SHOP_GOODS_SELECT',
+ 'title' => get_lang('dict_diy.shop_link_goods_select'),
+ 'component' => '/src/addon/shop/views/goods/components/goods-select-content.vue'
+ ],
+ [
+ 'name' => 'SHOP_GOODS_CATEGORY_SELECT',
+ 'title' => get_lang('dict_diy.shop_link_goods_category_select'),
+ 'component' => '/src/addon/shop/views/goods/components/goods-category-select-content.vue'
+ ],
+ [
+ 'name' => 'SHOP_COUPON_SELECT',
+ 'title' => get_lang('dict_diy.shop_link_coupon_select'),
+ 'component' => '/src/addon/shop/views/marketing/coupon/components/coupon-select-content.vue'
+ ],
+ [
+ 'name' => 'SHOP_POINT_EXCHANGE_SELECT',
+ 'title' => get_lang('dict_diy.shop_link_point_exchange_select'),
+ 'component' => '/src/addon/shop/views/marketing/exchange/components/goods-select-content.vue'
+ ]
+ ],
+ ],
+];
diff --git a/niucloud/addon/shop/app/dict/diy/pages.php b/niucloud/addon/shop/app/dict/diy/pages.php
new file mode 100644
index 000000000..9214729eb
--- /dev/null
+++ b/niucloud/addon/shop/app/dict/diy/pages.php
@@ -0,0 +1,5627 @@
+ "3ilbpixhyia0",
+ "title" => "我的拼单",
+ "imageUrl" => "addon/pintuan/diy/member/style1/nav_my_spell.png",
+ "imgWidth" => 92,
+ "imgHeight" => 92,
+ "link" => [
+ "parent" => "PINTUAN_LINK",
+ "title" => "我的拼单",
+ "url" => "/addon/pintuan/pages/order/list",
+ "name" => "PINTUAN_ORDER_LIST",
+ "action" => ""
+ ],
+ "label" => [
+ "control" => false,
+ "text" => "热门",
+ "textColor" => "#FFFFFF",
+ "bgColorStart" => "#F83287",
+ "bgColorEnd" => "#FE3423"
+ ]
+];
+$my_help = [
+ "id" => "9tlbcgxsyihe",
+ "title" => "我的助力",
+ "imageUrl" => "addon/friend_help/diy/member/style1/nav_my_help.png",
+ "imgWidth" => 92,
+ "imgHeight" => 92,
+ "link" => [
+ "parent" => "FRIEND_HELP_LINK",
+ "title" => "我的助力",
+ "url" => "/addon/friend_help/pages/my_help",
+ "name" => "FRIEND_HELP_MY_LIST",
+ "action" => ""
+ ],
+ "label" => [
+ "control" => false,
+ "text" => "热门",
+ "textColor" => "#FFFFFF",
+ "bgColorStart" => "#F83287",
+ "bgColorEnd" => "#FE3423"
+ ]
+];
+
+$member_index_graphic_nav_list = [
+ [
+ "id" => "49kxbgr5lwue",
+ "title" => "签到",
+ "imageUrl" => "addon/shop/diy/member/style1/nav_sign_in.png",
+ "imgWidth" => 92,
+ "imgHeight" => 92,
+ "link" => [
+ "name" => "MEMBER_MY_SIGN_IN",
+ "parent" => "MEMBER_LINK",
+ "title" => "我的签到",
+ "url" => "/app/pages/member/sign_in",
+ "action" => ""
+ ],
+ "label" => [
+ "control" => false,
+ "text" => "热门",
+ "textColor" => "#FFFFFF",
+ "bgColorStart" => "#F83287",
+ "bgColorEnd" => "#FE3423"
+ ]
+ ],
+ [
+ "title" => "我的余额",
+ "link" => [
+ "parent" => "MEMBER_LINK",
+ "name" => "MEMBER_BALANCE",
+ "title" => "我的余额",
+ "url" => "/app/pages/member/balance",
+ "action" => ""
+ ],
+ "imageUrl" => "addon/shop/diy/member/style1/nav_balance.png",
+ "label" => [
+ "control" => false,
+ "text" => "热门",
+ "textColor" => "#FFFFFF",
+ "bgColorStart" => "#F83287",
+ "bgColorEnd" => "#FE3423"
+ ],
+ "id" => "2aqy33banse8",
+ "imgWidth" => 92,
+ "imgHeight" => 92
+ ],
+ [
+ "title" => "地址管理",
+ "link" => [
+ "parent" => "MEMBER_LINK",
+ "name" => "MEMBER_ADDRESS",
+ "title" => "收货地址",
+ "url" => "/app/pages/member/address",
+ "action" => ""
+ ],
+ "imageUrl" => "addon/shop/diy/member/style1/nav_address.png",
+ "label" => [
+ "control" => false,
+ "text" => "热门",
+ "textColor" => "#FFFFFF",
+ "bgColorStart" => "#F83287",
+ "bgColorEnd" => "#FE3423"
+ ],
+ "id" => "hdk4145zk40",
+ "imgWidth" => 92,
+ "imgHeight" => 92
+ ],
+ [
+ "title" => "优惠券",
+ "link" => [
+ "parent" => "SHOP_LINK",
+ "name" => "SHOP_MY_COUPON",
+ "title" => "我的优惠券",
+ "url" => "/addon/shop/pages/member/my_coupon",
+ "action" => ""
+ ],
+ "imageUrl" => "addon/shop/diy/member/style1/nav_coupon.png",
+ "label" => [
+ "control" => false,
+ "text" => "热门",
+ "textColor" => "#FFFFFF",
+ "bgColorStart" => "#F83287",
+ "bgColorEnd" => "#FE3423"
+ ],
+ "id" => "34t5xg9ik0i0",
+ "imgWidth" => 92,
+ "imgHeight" => 92
+ ],
+ [
+ "id" => "7dpefp0s9ew0",
+ "title" => "分销中心",
+ "imageUrl" => "addon/shop/diy/member/style1/nav_promote.png",
+ "imgWidth" => 92,
+ "imgHeight" => 92,
+ "link" => [
+ "name" => "SHOP_FENXIAO_INDEX",
+ "parent" => "SHOP_FENXIAO_LINK",
+ "title" => "分销中心",
+ "url" => "/addon/shop_fenxiao/pages/index",
+ "action" => ""
+ ],
+ "label" => [
+ "control" => false,
+ "text" => "热门",
+ "textColor" => "#FFFFFF",
+ "bgColorStart" => "#F83287",
+ "bgColorEnd" => "#FE3423"
+ ]
+ ],
+ [
+ "title" => "积分兑换",
+ "link" => [
+ "name" => "SHOP_LINK",
+ "parent" => "SHOP_FENXIAO_LINK",
+ "title" => "积分商城",
+ "url" => "/addon/shop/pages/point/index",
+ "action" => ""
+ ],
+ "imageUrl" => "addon/shop/diy/member/style1/nav_point_change.png",
+ "label" => [
+ "control" => false,
+ "text" => "热门",
+ "textColor" => "#FFFFFF",
+ "bgColorStart" => "#F83287",
+ "bgColorEnd" => "#FE3423"
+ ],
+ "id" => "692put4jerg0",
+ "imgWidth" => 92,
+ "imgHeight" => 92
+ ],
+ [
+ "id" => "78kxbgr4lipw",
+ "title" => "核销台",
+ "imageUrl" => "addon/shop/diy/member/style1/nav_verify_index.png",
+ "imgWidth" => 92,
+ "imgHeight" => 92,
+ "link" => [
+ "name" => "MEMBER_VERIFY_INDEX",
+ "parent" => "MEMBER_LINK",
+ "title" => "核销台",
+ 'url' => '/app/pages/verify/index',
+ "action" => ""
+ ],
+ "label" => [
+ "control" => false,
+ "text" => "热门",
+ "textColor" => "#FFFFFF",
+ "bgColorStart" => "#F83287",
+ "bgColorEnd" => "#FE3423"
+ ]
+ ],
+ [
+ "id" => "27kxbgr5lj3w",
+ "title" => "礼品卡",
+ "imageUrl" => "addon/shop/diy/member/style1/nav_giftcard.png",
+ "imgWidth" => 92,
+ "imgHeight" => 92,
+ "link" => [
+ "name" => "SHOP_GIFTCARD_MY_CARD_LIST",
+ "parent" => "SHOP_GIFTCARD_LINK",
+ "title" => "我的卡包",
+ "url" => "/addon/shop_giftcard/pages/my_card_list",
+ "action" => ""
+ ],
+ "label" => [
+ "control" => false,
+ "text" => "热门",
+ "textColor" => "#FFFFFF",
+ "bgColorStart" => "#F83287",
+ "bgColorEnd" => "#FE3423"
+ ]
+ ],
+ [
+ "id" => "4o2q7yss59m0",
+ "title" => "我的等级",
+ "imageUrl" => "addon/shop/diy/member/style1/nav_my_level.png",
+ "imgWidth" => 92,
+ "imgHeight" => 92,
+ "link" => [
+ "name" => "MEMBER_MY_LEVEL",
+ "parent" => "MEMBER_LINK",
+ "title" => "会员等级",
+ "url" => "/app/pages/member/level",
+ "action" => ""
+ ],
+ "label" => [
+ "control" => false,
+ "text" => "热门",
+ "textColor" => "#FFFFFF",
+ "bgColorStart" => "#F83287",
+ "bgColorEnd" => "#FE3423"
+ ]
+ ],
+ [
+ "id" => "78fnsh8cx5k0",
+ "title" => "我的收藏",
+ "imageUrl" => "addon/shop/diy/member/style1/nav_collect.png",
+ "imgWidth" => 92,
+ "imgHeight" => 92,
+ "link" => [
+ "name" => "SHOP_MY_GOODS_COLLECT",
+ "parent" => "SHOP_LINK",
+ "title" => "商品收藏",
+ "url" => "/addon/shop/pages/goods/collect",
+ "action" => ""
+ ],
+ "label" => [
+ "control" => false,
+ "text" => "热门",
+ "textColor" => "#FFFFFF",
+ "bgColorStart" => "#F83287",
+ "bgColorEnd" => "#FE3423"
+ ]
+ ],
+ [
+ "id" => "38fqtyu8cx5k0",
+ "title" => "我的足迹",
+ "imageUrl" => "addon/shop/diy/member/style1/nav_browse.png",
+ "imgWidth" => 92,
+ "imgHeight" => 92,
+ "link" => [
+ "name" => "SHOP_MY_GOODS_BROWSE",
+ "parent" => "SHOP_LINK",
+ "title" => "我的足迹",
+ "url" => "/addon/shop/pages/goods/browse",
+ "action" => ""
+ ],
+ "label" => [
+ "control" => false,
+ "text" => "热门",
+ "textColor" => "#FFFFFF",
+ "bgColorStart" => "#F83287",
+ "bgColorEnd" => "#FE3423"
+ ]
+ ],
+];
+
+$addon_service = new \app\service\admin\addon\AddonService();
+$site_addons = $addon_service->getInstallList();
+if(!empty($site_addons)) {
+ $site_addons = array_keys($site_addons);
+ if (in_array('pintuan', $site_addons)) {
+ $member_index_graphic_nav_list[] = $my_pintuan;
+ }
+ if (in_array('friend_help', $site_addons)) {
+ $member_index_graphic_nav_list[] = $my_help;
+ }
+}
+$member_index_graphic_nav_list[] = [
+ "id" => "27kxbgr5ljbw",
+ "title" => "联系客服",
+ "imageUrl" => "addon/shop/diy/member/style1/nav_service.png",
+ "imgWidth" => 92,
+ "imgHeight" => 92,
+ "link" => [
+ "name" => "MEMBER_CONTACT",
+ "parent" => "MEMBER_LINK",
+ "title" => "客服",
+ "url" => "/app/pages/member/contact",
+ "action" => ""
+ ],
+ "label" => [
+ "control" => false,
+ "text" => "热门",
+ "textColor" => "#FFFFFF",
+ "bgColorStart" => "#F83287",
+ "bgColorEnd" => "#FE3423"
+ ]
+];
+
+return [
+ 'DIY_SHOP_INDEX' => [
+ 'shop_index_style2' => [ // 页面标识
+ "title" => "商城首页1", // 页面名称
+ 'cover' => '', // 页面封面图
+ 'preview' => '', // 页面预览图
+ 'desc' => '', // 页面描述
+ 'mode' => 'diy', // 页面模式:diy:自定义,fixed:固定
+ // 页面数据源
+ "data" => [
+ "global" => [
+ "title" => "首页",
+ "pageStartBgColor" => "rgba(246, 246, 246, 1)",
+ "pageEndBgColor" => "",
+ "pageGradientAngle" => "to bottom",
+ "bgUrl" => "",
+ "bgHeightScale" => 100,
+ "imgWidth" => "",
+ "imgHeight" => "",
+ "topStatusBar" => [
+ 'control' => true,
+ "isShow" => false,
+ "bgColor" => "#ffffff",
+ "rollBgColor" => "#ffffff",
+ "style" => "style-1",
+ "styleName" => "风格1",
+ "textColor" => "#333333",
+ "rollTextColor" => "#333333",
+ "textAlign" => "center",
+ "inputPlaceholder" => "请输入搜索关键词",
+ "imgUrl" => "",
+ "link" => [
+ "name" => ""
+ ]
+ ],
+ "bottomTabBar" => [
+ 'control' => true,
+ 'isShow' => true,
+ 'designNav' => [
+ 'title' => '',
+ 'key' => ''
+ ]
+ ],
+ "copyright" => [
+ 'control' => true,
+ 'isShow' => false,
+ 'textColor' =>'#ccc'
+ ],
+ "popWindow" => [
+ "imgUrl" => "",
+ "imgWidth" => "",
+ "imgHeight" => "",
+ "count" => 'once',
+ "show" => 0,
+ "link" => [
+ "name" => ""
+ ]
+ ],
+ "template" => [
+ "textColor" => "#303133",
+ "pageStartBgColor" => "",
+ "pageEndBgColor" => "",
+ "pageGradientAngle" => "to bottom",
+ "componentBgUrl" => "",
+ "componentBgAlpha" => 2,
+ "componentStartBgColor" => "",
+ "componentEndBgColor" => "",
+ "componentGradientAngle" => "to bottom",
+ "topRounded" => 0,
+ "bottomRounded" => 0,
+ "elementBgColor" => "",
+ "topElementRounded" => 0,
+ "bottomElementRounded" => 0,
+ "margin" => [
+ "top" => 0,
+ "bottom" => 0,
+ "both" => 0
+ ]
+ ]
+ ],
+ "value" => [
+ [
+ "path" => "edit-carousel-search",
+ "uses" => 1,
+ "position" => "top_fixed",
+ "id" => "6r6qw5679oo0",
+ "componentName" => "CarouselSearch",
+ "componentTitle" => "轮播搜索",
+ "ignore" => [
+ "componentBgColor",
+ "componentBgUrl",
+ "marginTop",
+ "marginBottom",
+ "topRounded",
+ "bottomRounded",
+ "pageBgColor",
+ "marginBoth"
+ ],
+ "positionWay" => "fixed",
+ "fixedBgColor" => "",
+ "bgGradient" => false,
+ "search" => [
+ "logo" => "addon/shop/diy/index/style3/logo.png",
+ "text" => "请输入搜索关键词",
+ "link" => [
+ 'name' => 'SHOP_GOODS_SEARCH',
+ "parent" => "SHOP_LINK",
+ 'title' => '商品搜索',
+ 'url' => '/addon/shop/pages/goods/search',
+ 'action' => '',
+ ],
+ 'style' => 'style-2',
+ 'styleName' => '风格2',
+ "subTitle" => [
+ "text" => "本地好价·优选生活",
+ "textColor" => "#000000",
+ "startColor" => "rgba(255,255,255,0.7)",
+ "endColor" => "",
+ ],
+ 'positionColor' => '#ffffff',
+ "hotWord" => [
+ "interval" => 3,
+ "list" => [
+ [
+ 'text' => '新品推荐',
+ 'id' => '1l3juvqvimw0'
+ ],
+ [
+ 'text' => '爆款',
+ 'id' => '2vejp61n1xk0'
+ ]
+ ]
+ ],
+ 'color' => '#999999',
+ 'btnColor' => '#ffffff',
+ 'bgColor' => '#ffffff',
+ 'btnBgColor' => '#ff3434'
+ ],
+ "tab" => [
+ "control" => false,
+ "noColor" => "rgba(255, 255, 255, 0.7)",
+ "selectColor" => "rgba(255, 255, 255, 1)",
+ "fixedNoColor" => "rgba(255, 255, 255, 0.7)",
+ "fixedSelectColor" => "rgba(255, 255, 255, 1)",
+ "list" => [
+ [
+ "text" => "精选",
+ "source" => "diy_page",
+ "diy_id" => "",
+ "diy_title" => "",
+ "id" => "1wx7m1wykqbk"
+ ],
+ [
+ "text" => "猜你喜欢",
+ "source" => "diy_page",
+ "diy_id" => "",
+ "diy_title" => "",
+ "id" => "1gfh1oc6fsjk"
+ ],
+ [
+ "text" => "蔬菜",
+ "source" => "diy_page",
+ "diy_id" => "",
+ "diy_title" => "",
+ "id" => "25v390lfsd34"
+ ],
+ [
+ "text" => "水果",
+ "source" => "diy_page",
+ "diy_id" => "",
+ "diy_title" => "",
+ "id" => "2zb1znvn5jc0"
+ ],
+ [
+ "id" => "5acf7ab4f040",
+ "text" => "海鲜",
+ "source" => "diy_page",
+ "diy_id" => 0,
+ "diy_title" => ""
+ ],
+ [
+ "id" => "37a9vwqt1r20",
+ "text" => "熟食",
+ "source" => "diy_page",
+ "diy_id" => 0,
+ "diy_title" => ""
+ ],
+ [
+ "id" => "1en9w5jstvs0",
+ "text" => "米面",
+ "source" => "diy_page",
+ "diy_id" => 0,
+ "diy_title" => ""
+ ],
+ [
+ "id" => "3ae14irgqoa0",
+ "text" => "粮油",
+ "source" => "diy_page",
+ "diy_id" => 0,
+ "diy_title" => " "
+ ]
+ ]
+ ],
+ "swiper" => [
+ "control" => true,
+ "interval" => 5,
+ "indicatorColor" => "rgba(255, 255, 255, 1)",
+ "indicatorActiveColor" => "#FF0E0E",
+ "indicatorStyle" => "style-3",
+ "indicatorAlign" => "center",
+ "swiperStyle" => "style-3",
+ "imageHeight" => 274,
+ "topRounded" => 0,
+ "bottomRounded" => 0,
+ "list" => [
+ [
+ "imageUrl" => "addon/shop/diy/index/style3/banner1.jpg",
+ "imgWidth" => 750,
+ "imgHeight" => 580,
+ "link" => [
+ "name" => ""
+ ],
+ "id" => "397htiaqung0",
+ "width" => 355,
+ "height" => 274.53
+ ],
+ [
+ "imageUrl" => "addon/shop/diy/index/style3/banner2.jpg",
+ "imgWidth" => 750,
+ "imgHeight" => 580,
+ "link" => [
+ "name" => ""
+ ],
+ "id" => "6mrj3vwiamw0",
+ "width" => 355,
+ "height" => 274.53
+ ]
+ ]
+ ],
+ "textColor" => "#303133",
+ "pageStartBgColor" => "",
+ "pageEndBgColor" => "",
+ "pageGradientAngle" => "to bottom",
+ "componentBgUrl" => "",
+ "componentBgAlpha" => 2,
+ "componentStartBgColor" => "",
+ "componentEndBgColor" => "",
+ "componentGradientAngle" => "to bottom",
+ "topRounded" => 0,
+ "bottomRounded" => 0,
+ "elementBgColor" => "",
+ "topElementRounded" => 0,
+ "bottomElementRounded" => 0,
+ "margin" => [
+ "top" => 0,
+ "bottom" => 0,
+ "both" => 0
+ ],
+ "pageStyle" => "padding-top:2rpx;padding-bottom:0rpx;padding-right:0rpx;padding-left:0rpx;"
+ ],
+ [
+ "path" => "edit-horz-blank",
+ "uses" => 0,
+ "id" => "4wk9nzocm3c",
+ "componentName" => "HorzBlank",
+ "componentTitle" => "辅助空白",
+ "ignore" => [
+ "pageBgColor",
+ "componentBgUrl"
+ ],
+ "height" => 22,
+ "textColor" => "#303133",
+ "pageStartBgColor" => "",
+ "pageEndBgColor" => "",
+ "pageGradientAngle" => "to bottom",
+ "componentBgUrl" => "",
+ "componentBgAlpha" => 2,
+ "componentStartBgColor" => "rgba(246, 246, 246, 1)",
+ "componentEndBgColor" => "",
+ "componentGradientAngle" => "to bottom",
+ "topRounded" => 17,
+ "bottomRounded" => 0,
+ "elementBgColor" => "",
+ "topElementRounded" => 0,
+ "bottomElementRounded" => 0,
+ "margin" => [
+ "top" => -21,
+ "bottom" => 0,
+ "both" => 0
+ ],
+ "pageStyle" => "padding-top:2rpx;padding-bottom:0rpx;padding-right:0rpx;padding-left:0rpx;"
+ ],
+ [
+ "path" => "edit-graphic-nav",
+ "uses" => 0,
+ "id" => "6h28ebyqqnk0",
+ "componentName" => "GraphicNav",
+ "componentTitle" => "图文导航",
+ "ignore" => [],
+ "layout" => "horizontal",
+ "mode" => "graphic",
+ "showStyle" => "fixed",
+ "rowCount" => 5,
+ "pageCount" => 2,
+ "carousel" => [
+ "type" => "circle",
+ "color" => "#FFFFFF"
+ ],
+ "imageSize" => 40,
+ "aroundRadius" => 25,
+ "font" => [
+ "size" => 12,
+ "weight" => "normal",
+ "color" => "#303133"
+ ],
+ "list" => [
+ [
+ "title" => "签到",
+ "link" => [
+ "name" => "MEMBER_MY_SIGN_IN",
+ "parent" => "MEMBER_LINK",
+ "title" => "我的签到",
+ "url" => "/app/pages/member/sign_in",
+ "action" => ""
+ ],
+ "imageUrl" => "addon/shop/diy/index/style3/nav_sign_in.png",
+ "label" => [
+ "control" => false,
+ "text" => "热门",
+ "textColor" => "#FFFFFF",
+ "bgColorStart" => "#F83287",
+ "bgColorEnd" => "#FE3423"
+ ],
+ "id" => "1evjnc3zeb5s",
+ "imgWidth" => 180,
+ "imgHeight" => 180
+ ],
+ [
+ "title" => "分销管理",
+ "link" => [
+ "name" => "SHOP_FENXIAO_INDEX",
+ "parent" => "SHOP_FENXIAO_LINK",
+ "title" => "分销中心",
+ "url" => "/addon/shop_fenxiao/pages/index",
+ "action" => ""
+ ],
+ "imageUrl" => "addon/shop/diy/index/style3/nav_fenxiao.png",
+ "label" => [
+ "control" => false,
+ "text" => "热门",
+ "textColor" => "#FFFFFF",
+ "bgColorStart" => "#F83287",
+ "bgColorEnd" => "#FE3423"
+ ],
+ "id" => "2ktzer8wrnc0",
+ "imgWidth" => 180,
+ "imgHeight" => 180
+ ],
+ [
+ "title" => "分销专区",
+ "link" => [
+ "name" => "SHOP_FENXIAO_ZONE",
+ "parent" => "SHOP_FENXIAO_LINK",
+ "title" => "分销专区",
+ "url" => "/addon/shop_fenxiao/pages/zone",
+ "action" => "decorate"
+ ],
+ "imageUrl" => "addon/shop/diy/index/style3/nav_fenxiao_zone.png",
+ "label" => [
+ "control" => false,
+ "text" => "热门",
+ "textColor" => "#FFFFFF",
+ "bgColorStart" => "#F83287",
+ "bgColorEnd" => "#FE3423"
+ ],
+ "id" => "4aixr8qu5ek0",
+ "imgWidth" => 180,
+ "imgHeight" => 180
+ ],
+ [
+ "title" => "领券中心",
+ "link" => [
+ "name" => "SHOP_COUPON_LIST",
+ "parent" => "SHOP_LINK",
+ "title" => "优惠券列表",
+ "url" => "/addon/shop/pages/coupon/list",
+ "action" => ""
+ ],
+ "imageUrl" => "addon/shop/diy/index/style3/nav_coupon.png",
+ "label" => [
+ "control" => false,
+ "text" => "热门",
+ "textColor" => "#FFFFFF",
+ "bgColorStart" => "#F83287",
+ "bgColorEnd" => "#FE3423"
+ ],
+ "id" => "3bmtyrslxxy0",
+ "imgWidth" => 180,
+ "imgHeight" => 180
+ ],
+ [
+ "id" => "6iux9g1aojo0",
+ "title" => "新闻资讯",
+ "imageUrl" => "addon/shop/diy/index/style3/nav_news_info.png",
+ "imgWidth" => 180,
+ "imgHeight" => 180,
+ "link" => [
+ "name" => ""
+ ],
+ "label" => [
+ "control" => false,
+ "text" => "热门",
+ "textColor" => "#FFFFFF",
+ "bgColorStart" => "#F83287",
+ "bgColorEnd" => "#FE3423"
+ ]
+ ],
+ [
+ "id" => "7jggy5euv3w0",
+ "title" => "限时折扣",
+ "imageUrl" => "addon/shop/diy/index/style3/nav_discount.png",
+ "imgWidth" => 180,
+ "imgHeight" => 180,
+ "link" => [
+ "name" => "SHOP_DISCOUNT_LIST",
+ "parent" => "SHOP_LINK",
+ "title" => "限时折扣列表",
+ 'url' => '/addon/shop/pages/discount/list',
+ "action" => ""
+ ],
+ "label" => [
+ "control" => false,
+ "text" => "热门",
+ "textColor" => "#FFFFFF",
+ "bgColorStart" => "#F83287",
+ "bgColorEnd" => "#FE3423"
+ ]
+ ],
+ [
+ "id" => "7bqpc6bjha80",
+ "title" => "积分商城",
+ "imageUrl" => "addon/shop/diy/index/style3/nav_point_index.png",
+ "imgWidth" => 180,
+ "imgHeight" => 180,
+ "link" => [
+ "name" => "SHOP_POINT_INDEX",
+ "parent" => "SHOP_LINK",
+ "title" => "积分商城",
+ 'url' => '/addon/shop/pages/point/index',
+ "action" => ""
+ ],
+ "label" => [
+ "control" => false,
+ "text" => "热门",
+ "textColor" => "#FFFFFF",
+ "bgColorStart" => "#F83287",
+ "bgColorEnd" => "#FE3423"
+ ]
+ ],
+ [
+ "id" => "tgo5qmjawnk",
+ "title" => "礼品卡",
+ "imageUrl" => "addon/shop/diy/index/style3/nav_giftcard.png",
+ "imgWidth" => 180,
+ "imgHeight" => 180,
+ "link" => [
+ "name" => "SHOP_GIFTCARD_INDEX",
+ "parent" => "SHOP_GIFTCARD_LINK",
+ "title" => "礼品卡",
+ "url" => "/addon/shop_giftcard/pages/index",
+ "action" => ""
+ ],
+ "label" => [
+ "control" => false,
+ "text" => "热门",
+ "textColor" => "#FFFFFF",
+ "bgColorStart" => "#F83287",
+ "bgColorEnd" => "#FE3423"
+ ]
+ ],
+ [
+ "id" => "1fprven2cqrk",
+ "title" => "新人专享",
+ "imageUrl" => "addon/shop/diy/index/style3/nav_my_newcomer.png",
+ "imgWidth" => 180,
+ "imgHeight" => 180,
+ "link" => [
+ "name" => "SHOP_NEWCOMER_LIST",
+ "parent" => "SHOP_LINK",
+ "title" => "新人专享",
+ "url" => "/addon/shop/pages/newcomer/list",
+ "action" => ""
+ ],
+ "label" => [
+ "control" => false,
+ "text" => "热门",
+ "textColor" => "#FFFFFF",
+ "bgColorStart" => "#F83287",
+ "bgColorEnd" => "#FE3423"
+ ]
+ ],
+ [
+ "id" => "2wggehpnako0",
+ "title" => "限时秒杀",
+ "imageUrl" => "addon/shop/diy/index/style3/nav_seckill.png",
+ "imgWidth" => 180,
+ "imgHeight" => 180,
+ "link" => [
+ "parent" => "SECKILL_LINK",
+ "title" => "秒杀首页",
+ "url" => "/addon/seckill/pages/index",
+ "name" => "SECKILL_INDEX"
+ ],
+ "label" => [
+ "control" => false,
+ "text" => "热门",
+ "textColor" => "#FFFFFF",
+ "bgColorStart" => "#F83287",
+ "bgColorEnd" => "#FE3423"
+ ]
+ ]
+ ],
+ // 轮播图设置
+ 'swiper' => [
+ 'indicatorColor' => 'rgba(0, 0, 0, 0.3)', // 未选中颜色
+ "indicatorActiveColor" => '#FF0E0E',
+ 'indicatorStyle' => 'style-1',
+ 'indicatorAlign' => 'center',
+ ],
+ "textColor" => "#303133",
+ "pageStartBgColor" => "",
+ "pageEndBgColor" => "",
+ "pageGradientAngle" => "to bottom",
+ "componentBgUrl" => "",
+ "componentBgAlpha" => 2,
+ "componentStartBgColor" => "rgba(255, 255, 255, 1)",
+ "componentEndBgColor" => "",
+ "componentGradientAngle" => "to bottom",
+ "topRounded" => 12,
+ "bottomRounded" => 12,
+ "elementBgColor" => "",
+ "topElementRounded" => 0,
+ "bottomElementRounded" => 0,
+ "margin" => [
+ "top" => -10,
+ "bottom" => 10,
+ "both" => 10
+ ],
+ "pageStyle" => "padding-top:2rpx;padding-bottom:0rpx;padding-right:0rpx;padding-left:0rpx;"
+ ],
+ [
+ "path" => "edit-notice",
+ "uses" => 0,
+ "id" => "5ux60nfdm680",
+ "componentName" => "Notice",
+ "componentTitle" => "公告",
+ "ignore" => [],
+ "noticeType" => "img",
+ "imgType" => "diy",
+ "systemUrl" => "style_1",
+ "imageUrl" => "addon/shop/diy/index/style3/notice.png",
+ "showType" => "popup",
+ "scrollWay" => "upDown",
+ "fontSize" => 12,
+ "fontWeight" => "normal",
+ "noticeTitle" => "公告",
+ "list" => [
+ [
+ "text" => "最新公告:欢迎来到小店参观!",
+ "link" => [
+ "name" => ""
+ ],
+ "id" => "1rz6s4buaxc0"
+ ],
+ [
+ "id" => "2wksdax75fc0",
+ "text" => "最新公告:欢迎来到小店参观!",
+ "link" => [
+ "name" => ""
+ ]
+ ]
+ ],
+ "textColor" => "#303133",
+ "pageStartBgColor" => "",
+ "pageEndBgColor" => "",
+ "pageGradientAngle" => "to bottom",
+ "componentBgUrl" => "",
+ "componentBgAlpha" => 2,
+ "componentStartBgColor" => "rgba(255, 255, 255, 1)",
+ "componentEndBgColor" => "",
+ "componentGradientAngle" => "to bottom",
+ "topRounded" => 12,
+ "bottomRounded" => 12,
+ "elementBgColor" => "",
+ "topElementRounded" => 0,
+ "bottomElementRounded" => 0,
+ "margin" => [
+ "top" => 0,
+ "bottom" => 0,
+ "both" => 10
+ ],
+ "pageStyle" => "padding-top:2rpx;padding-bottom:0rpx;padding-right:20rpx;padding-left:20rpx;"
+ ],
+ [
+ "path" => "edit-goods-coupon",
+ "uses" => 0,
+ "id" => "5zq2inzbmu00",
+ "componentName" => "GoodsCoupon",
+ "componentTitle" => "优惠券",
+ "ignore" => [
+ "componentBgColor",
+ "componentBgUrl"
+ ],
+ "style" => "style-3",
+ "styleName" => "风格3",
+ "source" => "all",
+ "num" => 6,
+ "couponIds" => [],
+ "btnText" => "立即领取",
+ "couponTitle" => "每日省钱",
+ "couponSubTitle" => "先领券 再购物",
+ "titleColor" => "#ffffff",
+ "subTitleColor" => "#ffffff",
+ "couponItem" => [
+ "bgColor" => "#ffffff",
+ "textColor" => "#333333",
+ "subTextColor" => "#666666",
+ "moneyColor" => "#333333",
+ "aroundRadius" => 12
+ ],
+ "textColor" => "#303133",
+ "pageStartBgColor" => "",
+ "pageEndBgColor" => "",
+ "pageGradientAngle" => "to bottom",
+ "componentBgUrl" => "",
+ "componentBgAlpha" => 2,
+ "componentStartBgColor" => "",
+ "componentEndBgColor" => "",
+ "componentGradientAngle" => "to bottom",
+ "topRounded" => 12,
+ "bottomRounded" => 12,
+ "elementBgColor" => "",
+ "topElementRounded" => 0,
+ "bottomElementRounded" => 0,
+ "margin" => [
+ "top" => 10,
+ "bottom" => null,
+ "both" => 10
+ ],
+ "pageStyle" => "padding-top:20rpx;padding-bottom:0rpx;padding-right:20rpx;padding-left:20rpx;"
+ ],
+ [
+ "path" => "edit-shop-goods-recommend",
+ "uses" => 0,
+ "id" => "2ezdal8ps1og",
+ "componentName" => "ShopGoodsRecommend",
+ "componentTitle" => "商品推荐",
+ "ignore" => [],
+ "priceStyle" => [
+ "mainColor" => "#333333"
+ ],
+ 'source' => 'all',
+ "goods_ids" => [],
+ "list" => [
+ [
+ "title" => [
+ "text" => "今日推荐",
+ "textColor" => "#303133"
+ ],
+ "moreTitle" => [
+ "text" => "精选",
+ "textColor" => "#FFFFFF",
+ "startColor" => "#FF7234",
+ "endColor" => "#FF213F"
+ ],
+ "listFrame" => [
+ "startColor" => "#FFE5E5",
+ "endColor" => "#FFF5F0"
+ ],
+ "button" => [
+ "text" => "首单",
+ "textColor" => "#FFFFFF",
+ "color" => "#FF1128"
+ ],
+ "id" => "6t9kv928d680"
+ ],
+ [
+ "title" => [
+ "text" => "品质好物",
+ "textColor" => "#303133"
+ ],
+ "moreTitle" => [
+ "text" => "精选",
+ "textColor" => "#FFFFFF",
+ "startColor" => "#F2C719",
+ "endColor" => "#FBBA08"
+ ],
+ "listFrame" => [
+ "startColor" => "#FFEFBA",
+ "endColor" => "#FFF5D7"
+ ],
+ "button" => [
+ "text" => "首单",
+ "textColor" => "#FFFFFF",
+ "color" => "#FF1128"
+ ],
+ "id" => "4u1rv0e4qpo0"
+ ],
+ [
+ "title" => [
+ "text" => "热销爆款",
+ "textColor" => "#303133"
+ ],
+ "moreTitle" => [
+ "text" => "精选",
+ "textColor" => "#FFFFFF",
+ "startColor" => "#FFA629",
+ "endColor" => "#FF8E1E"
+ ],
+ "listFrame" => [
+ "startColor" => "#FFE4D9",
+ "endColor" => "#FFFBF9"
+ ],
+ "button" => [
+ "text" => "首单",
+ "textColor" => "#FFFFFF",
+ "color" => "#FF1128"
+ ],
+ "id" => "4v1bhzhxay60"
+ ]
+ ],
+ "imgElementRounded" => 10, // 图片圆角
+ "textColor" => "#303133",
+ "pageStartBgColor" => "",
+ "pageEndBgColor" => "",
+ "pageGradientAngle" => "to bottom",
+ "componentBgUrl" => "",
+ "componentBgAlpha" => 2,
+ "componentStartBgColor" => "",
+ "componentEndBgColor" => "",
+ "componentGradientAngle" => "to bottom",
+ "topRounded" => 0,
+ "bottomRounded" => 0,
+ "elementBgColor" => "",
+ "topElementRounded" => 10,
+ "bottomElementRounded" => 10,
+ "margin" => [
+ "top" => 10,
+ "bottom" => 0,
+ "both" => 10
+ ],
+ "pageStyle" => "padding-top:20rpx;padding-bottom:0rpx;padding-right:20rpx;padding-left:20rpx;"
+ ],
+ [
+ "path" => "edit-active-cube",
+ "uses" => 0,
+ "id" => "3vmpaydr2a60",
+ "componentName" => "ActiveCube",
+ "componentTitle" => "活动魔方",
+ "ignore" => [],
+ "titleStyle" => [
+ "title" => "风格5",
+ "value" => "style-5"
+ ],
+ "text" => "超值爆款",
+ "textLink" => [
+ "name" => ""
+ ],
+ "titleColor" => "#F91700",
+ "subTitle" => [
+ "text" => "为您精选爆款",
+ "textColor" => "rgba(153, 153, 153, 1)",
+ "startColor" => "rgba(255, 255, 255, 1)",
+ "endColor" => "rgba(255, 255, 255, 1)",
+ "link" => [
+ "name" => ""
+ ]
+ ],
+ "blockStyle" => [
+ "title" => "风格2",
+ "value" => "style-2",
+ "fontWeight" => "bold",
+ "btnText" => "italics"
+ ],
+ "list" => [
+ [
+ "title" => [
+ "text" => "品质好物",
+ "textColor" => "#303133"
+ ],
+ "subTitle" => [
+ "text" => "品质好物推荐",
+ "textColor" => "#999999",
+ "startColor" => "",
+ "endColor" => ""
+ ],
+ "moreTitle" => [
+ "text" => "GO!",
+ "startColor" => "#FFC051",
+ "endColor" => "#FF9C00"
+ ],
+ "listFrame" => [
+ "startColor" => "#FFF1DB",
+ "endColor" => "#FFFBF4"
+ ],
+ "link" => [
+ "name" => ""
+ ],
+ "imageUrl" => "static/resource/images/diy/active_cube/active_cube_goods1.png",
+ "id" => "77tls7gaho80"
+ ],
+ [
+ "title" => [
+ "text" => "热销推荐",
+ "textColor" => "#303133"
+ ],
+ "subTitle" => [
+ "text" => "本周热销商品",
+ "textColor" => "#999999",
+ "startColor" => "",
+ "endColor" => ""
+ ],
+ "moreTitle" => [
+ "text" => "GO!",
+ "startColor" => "#A4E894",
+ "endColor" => "#45CC2A"
+ ],
+ "listFrame" => [
+ "startColor" => "#E6F6E2",
+ "endColor" => "#F5FDF3"
+ ],
+ "link" => [
+ "name" => ""
+ ],
+ "imageUrl" => "static/resource/images/diy/active_cube/active_cube_goods2.png",
+ "id" => "m4scwuc67do"
+ ],
+ [
+ "title" => [
+ "text" => "优惠好物",
+ "textColor" => "#303133"
+ ],
+ "subTitle" => [
+ "text" => "领券后更优惠",
+ "textColor" => "#999999",
+ "startColor" => "",
+ "endColor" => ""
+ ],
+ "moreTitle" => [
+ "text" => "GO!",
+ "startColor" => "#4BC2FF",
+ "endColor" => "#1F7DFF"
+ ],
+ "listFrame" => [
+ "startColor" => "#E2F6FF",
+ "endColor" => "#F2FAFF"
+ ],
+ "link" => [
+ "name" => ""
+ ],
+ "imageUrl" => "static/resource/images/diy/active_cube/active_cube_goods3.png",
+ "id" => "33nbfp8czea0"
+ ],
+ [
+ "title" => [
+ "text" => "今日推荐",
+ "textColor" => "#303133"
+ ],
+ "subTitle" => [
+ "text" => "诚意推荐",
+ "textColor" => "#999999",
+ "startColor" => "",
+ "endColor" => ""
+ ],
+ "moreTitle" => [
+ "text" => "GO!",
+ "startColor" => "#FB792F",
+ "endColor" => "#F91700"
+ ],
+ "listFrame" => [
+ "startColor" => "#FFEAEA",
+ "endColor" => "#FFFCFB"
+ ],
+ "link" => [
+ "name" => ""
+ ],
+ "imageUrl" => "static/resource/images/diy/active_cube/active_cube_goods4.png",
+ "id" => "49scoy4bgsg0"
+ ]
+ ],
+ "textColor" => "#303133",
+ "pageStartBgColor" => "",
+ "pageEndBgColor" => "",
+ "pageGradientAngle" => "to bottom",
+ "componentBgUrl" => "",
+ "componentBgAlpha" => 2,
+ "componentStartBgColor" => "rgba(255, 255, 255, 1)",
+ "componentEndBgColor" => "",
+ "componentGradientAngle" => "to bottom",
+ "topRounded" => 12,
+ "bottomRounded" => 12,
+ "elementBgColor" => "#FFFAF5",
+ "topElementRounded" => 10,
+ "bottomElementRounded" => 10,
+ "margin" => [
+ "top" => 10,
+ "bottom" => 0,
+ "both" => 10
+ ],
+ "textImg" => "static/resource/images/diy/active_cube/active_cube_text1.png",
+ "contentBtnTextStyle" => "italics",
+ "pageStyle" => "padding-top:20rpx;padding-bottom:0rpx;padding-right:20rpx;padding-left:20rpx;"
+ ],
+ [
+ "path" => "edit-picture-show",
+ "uses" => 0,
+ "id" => "2o99dw6mytk0",
+ "componentName" => "PictureShow",
+ "componentTitle" => "图片展播",
+ "ignore" => [],
+ "moduleOne" => [
+ "head" => [
+ "textImg" => "static/resource/images/diy/picture_show/picture_show_head_text1.png",
+ "subText" => "每日上新",
+ "subTextColor" => "#666666"
+ ],
+ "list" => [
+ [
+ "btnTitle" => [
+ "text" => "仅限今日",
+ "color" => "#ffffff",
+ "startColor" => "#F5443E",
+ "endColor" => "#F5443E"
+ ],
+ "link" => [
+ "name" => ""
+ ],
+ "imageUrl" => "static/resource/images/diy/picture_show/picture_01.png"
+ ],
+ [
+ "btnTitle" => [
+ "text" => "超值上新",
+ "color" => "#ffffff",
+ "startColor" => "#F5443E",
+ "endColor" => "#F5443E"
+ ],
+ "link" => [
+ "name" => ""
+ ],
+ "imageUrl" => "static/resource/images/diy/picture_show/picture_02.png"
+ ]
+ ],
+ "listFrame" => [
+ "startColor" => "#FFDDDD",
+ "endColor" => "#FFEBED"
+ ]
+ ],
+ "moduleTwo" => [
+ "head" => [
+ "textImg" => "static/resource/images/diy/picture_show/picture_show_head_text2.png",
+ "subText" => "好物低至1折1",
+ "subTextColor" => "#666666"
+ ],
+ "list" => [
+ [
+ "btnTitle" => [
+ "text" => "大牌直降",
+ "color" => "#ffffff",
+ "startColor" => "#F5443E",
+ "endColor" => "#F5443E"
+ ],
+ "link" => [
+ "name" => ""
+ ],
+ "imageUrl" => "static/resource/images/diy/picture_show/picture_03.png"
+ ],
+ [
+ "btnTitle" => [
+ "text" => "天天底价",
+ "color" => "#ffffff",
+ "startColor" => "#F5443E",
+ "endColor" => "#F5443E"
+ ],
+ "link" => [
+ "name" => ""
+ ],
+ "imageUrl" => "static/resource/images/diy/picture_show/picture_04.png"
+ ]
+ ],
+ "listFrame" => [
+ "startColor" => "#E6E1FE",
+ "endColor" => "#F0EEFC"
+ ]
+ ],
+ "moduleRounded" => [
+ "topRounded" => 10,
+ "bottomRounded" => 10
+ ],
+ "textColor" => "#303133",
+ "pageStartBgColor" => "",
+ "pageEndBgColor" => "",
+ "pageGradientAngle" => "to bottom",
+ "componentBgUrl" => "",
+ "componentBgAlpha" => 2,
+ "componentStartBgColor" => "",
+ "componentEndBgColor" => "",
+ "componentGradientAngle" => "to bottom",
+ "topRounded" => 0,
+ "bottomRounded" => 0,
+ "elementBgColor" => "",
+ "topElementRounded" => 0,
+ "bottomElementRounded" => 0,
+ "margin" => [
+ "top" => 10,
+ "bottom" => null,
+ "both" => 10
+ ],
+ "pageStyle" => "padding-top:20rpx;padding-bottom:0rpx;padding-right:20rpx;padding-left:20rpx;"
+ ],
+ [
+ "path" => "edit-picture-show",
+ "uses" => 0,
+ "id" => "3wz1r5bww3q0",
+ "componentName" => "PictureShow",
+ "componentTitle" => "图片展播",
+ "ignore" => [],
+ "moduleOne" => [
+ "head" => [
+ "textImg" => "static/resource/images/diy/picture_show/picture_show_head_text3.png",
+ "subText" => "最高补1200元",
+ "subTextColor" => "#666666"
+ ],
+ "list" => [
+ [
+ "btnTitle" => [
+ "text" => "全网低价",
+ "color" => "#ffffff",
+ "startColor" => "#F5443E",
+ "endColor" => "#F5443E"
+ ],
+ "link" => [
+ "name" => ""
+ ],
+ "imageUrl" => "static/resource/images/diy/picture_show/picture_05.png"
+ ],
+ [
+ "btnTitle" => [
+ "text" => "大牌特惠",
+ "color" => "#ffffff",
+ "startColor" => "#F5443E",
+ "endColor" => "#F5443E"
+ ],
+ "link" => [
+ "name" => ""
+ ],
+ "imageUrl" => "static/resource/images/diy/picture_show/picture_06.png"
+ ]
+ ],
+ "listFrame" => [
+ "startColor" => "rgba(212, 239, 255, 1)",
+ "endColor" => "rgba(235, 244, 250, 1)"
+ ]
+ ],
+ "moduleTwo" => [
+ "head" => [
+ "textImg" => "static/resource/images/diy/picture_show/picture_show_head_text4.png",
+ "subText" => "每日上新",
+ "subTextColor" => "#666666"
+ ],
+ "list" => [
+ [
+ "btnTitle" => [
+ "text" => "人气爆款",
+ "color" => "#ffffff",
+ "startColor" => "#F5443E",
+ "endColor" => "#F5443E"
+ ],
+ "link" => [
+ "name" => ""
+ ],
+ "imageUrl" => "static/resource/images/diy/picture_show/picture_07.png"
+ ],
+ [
+ "btnTitle" => [
+ "text" => "官方正品",
+ "color" => "#ffffff",
+ "startColor" => "#F5443E",
+ "endColor" => "#F5443E"
+ ],
+ "link" => [
+ "name" => ""
+ ],
+ "imageUrl" => "static/resource/images/diy/picture_show/picture_08.png"
+ ]
+ ],
+ "listFrame" => [
+ "startColor" => "rgba(255, 241, 212, 1)",
+ "endColor" => "rgba(249, 242, 229, 1)"
+ ]
+ ],
+ "moduleRounded" => [
+ "topRounded" => 10,
+ "bottomRounded" => 10
+ ],
+ "textColor" => "#303133",
+ "pageStartBgColor" => "",
+ "pageEndBgColor" => "",
+ "pageGradientAngle" => "to bottom",
+ "componentBgUrl" => "",
+ "componentBgAlpha" => 2,
+ "componentStartBgColor" => "",
+ "componentEndBgColor" => "",
+ "componentGradientAngle" => "to bottom",
+ "topRounded" => 0,
+ "bottomRounded" => 0,
+ "elementBgColor" => "",
+ "topElementRounded" => 0,
+ "bottomElementRounded" => 0,
+ "margin" => [
+ "top" => 10,
+ "bottom" => null,
+ "both" => 10
+ ],
+ "pageStyle" => "padding-top:20rpx;padding-bottom:0rpx;padding-right:20rpx;padding-left:20rpx;"
+ ],
+ [
+ "path" => "edit-shop-newcomer",
+ "uses" => 1,
+ "id" => "2hjc1q7f7q80",
+ "componentName" => "ShopNewcomer",
+ "componentTitle" => "新人专享",
+ "ignore" => [],
+ "style" => [
+ "title" => "风格1",
+ "value" => "style-1"
+ ],
+ "textImg" => "addon/shop/diy/newcomer/style_title_01.png",
+ "subTitle" => [
+ "text" => "查看更多",
+ "textColor" => "#FFFFFF",
+ "startColor" => "#FB792F",
+ "endColor" => "#F91700",
+ "link" => [
+ "name" => ""
+ ]
+ ],
+ "countDown" => [
+ "numberColor" => "rgba(255, 0, 0, 1)",
+ "numberBg" => [
+ "startColor" => "rgba(255, 255, 255, 1)",
+ "endColor" => ""
+ ],
+ "otherColor" => "rgba(255, 255, 255, 1)"
+ ],
+ "imgElementRounded" => 10, // 图片圆角
+ "source" => "all",
+ "num" => 10,
+ "goods_category" => "",
+ "goods_category_name" => "请选择",
+ "goods_ids" => [],
+ "textColor" => "#303133",
+ "pageStartBgColor" => "",
+ "pageEndBgColor" => "",
+ "pageGradientAngle" => "to bottom",
+ "componentBgUrl" => "",
+ "componentBgAlpha" => 2,
+ "componentStartBgColor" => "#ff6D1A",
+ "componentEndBgColor" => "rgba(255, 70, 56, 1)",
+ "componentGradientAngle" => "to right",
+ "topRounded" => 12,
+ "bottomRounded" => 12,
+ "elementBgColor" => "",
+ "topElementRounded" => 10,
+ "bottomElementRounded" => 10,
+ "margin" => [
+ "top" => 10,
+ "bottom" => 0,
+ "both" => 10
+ ],
+ "pageStyle" => "padding-top:20rpx;padding-bottom:0rpx;padding-right:20rpx;padding-left:20rpx;"
+ ],
+ [
+ "path" => "edit-single-recommend",
+ "uses" => 0,
+ "id" => "2mxsu6pbqpu0",
+ "componentName" => "SingleRecommend",
+ "componentTitle" => "精选推荐",
+ "ignore" => [],
+ "titleStyle" => [
+ "title" => "风格1",
+ "value" => "style-1"
+ ],
+ "textImg" => "addon/shop/diy/index/style3/single_recommend_text1.png",
+ "textLink" => [
+ "name" => ""
+ ],
+ "titleColor" => "rgba(153, 153, 153, 1)",
+ "subTitle" => [
+ "text" => "更多",
+ "textColor" => "rgba(153, 153, 153, 1)",
+ "link" => [
+ "name" => ""
+ ]
+ ],
+ "source" => "all",
+ "goods_ids" => [],
+ "imageHeight" => "250",
+ "list" => [
+ [
+ "id" => "18o4pyaufktc",
+ "imageUrl" => "addon/shop/diy/index/style3/single_recommend_banner1.jpg",
+ "imgWidth" => 345,
+ "imgHeight" => 495,
+ "link" => [
+ "name" => ""
+ ],
+ "width" => 355,
+ "height" => 509.3478260869565
+ ],
+ [
+ "id" => "18o8pyaufktc",
+ "imageUrl" => "addon/shop/diy/index/style3/single_recommend_banner2.jpg",
+ "imgWidth" => 345,
+ "imgHeight" => 495,
+ "link" => [
+ "name" => ""
+ ],
+ "width" => 355,
+ "height" => 509.3478260869565
+ ]
+ ],
+ "goodsNameStyle" => [
+ "color" => "#303133",
+ "control" => true,
+ "fontWeight" => "normal"
+ ],
+ "priceStyle" => [
+ "mainColor" => "#FF4142",
+ "mainControl" => true,
+ "lineColor" => "#999CA7",
+ "lineControl" => true
+ ],
+ "saleStyle" => [
+ "color" => "rgba(255, 0, 0, 1)",
+ "control" => true
+ ],
+ "textColor" => "#303133",
+ "pageStartBgColor" => "",
+ "pageEndBgColor" => "",
+ "pageGradientAngle" => "to bottom",
+ "componentBgUrl" => "",
+ "componentBgAlpha" => 2,
+ "componentStartBgColor" => null,
+ "componentEndBgColor" => null,
+ "componentGradientAngle" => "to bottom",
+ "topRounded" => 0,
+ "bottomRounded" => 0,
+ "elementBgColor" => "rgba(255, 255, 255, 1)",
+ "topElementRounded" => 12,
+ "bottomElementRounded" => 12,
+ "margin" => [
+ "top" => 15,
+ "bottom" => 0,
+ "both" => 10
+ ],
+ "pageStyle" => "padding-top:20rpx;padding-bottom:20rpx;padding-right:20rpx;padding-left:20rpx;",
+ "topCarouselRounded" => 12,
+ "bottomCarouselRounded" => 12,
+ "indicatorColor" => "rgba(255, 255, 255, 0.6)",
+ "indicatorActiveColor" => "rgba(255, 255, 255, 1)"
+ ],
+ [
+ "path" => "edit-image-ads",
+ "uses" => 0,
+ "id" => "1kfmhruhijgg",
+ "componentName" => "ImageAds",
+ "componentTitle" => "图片广告",
+ "ignore" => [
+
+ ],
+ "imageHeight" => 89,
+ "isSameScreen" => false,
+ "list" => [
+ [
+ "link" => [
+ "name" => ""
+ ],
+ "imageUrl" => "addon/shop/diy/index/style3/discount_img.png",
+ "imgWidth" => 710,
+ "imgHeight" => 170,
+ "id" => "6eo9vdo9xtc0",
+ "width" => 375,
+ "height" => 89.78873239436619
+ ]
+ ],
+ "textColor" => "#303133",
+ "pageStartBgColor" => "",
+ "pageEndBgColor" => "",
+ "pageGradientAngle" => "to bottom",
+ "componentBgUrl" => "",
+ "componentBgAlpha" => 2,
+ "componentStartBgColor" => "",
+ "componentEndBgColor" => "",
+ "componentGradientAngle" => "to bottom",
+ "topRounded" => 0,
+ "bottomRounded" => 0,
+ "elementBgColor" => "",
+ "topElementRounded" => 0,
+ "bottomElementRounded" => 0,
+ "margin" => [
+ "top" => 10,
+ "bottom" => 10,
+ "both" => 10
+ ]
+ ],
+ [
+ "path" => "edit-many-goods-list",
+ "uses" => 0,
+ "id" => "37adfqtqe080",
+ "componentName" => "ManyGoodsList",
+ "componentTitle" => "多商品组",
+ "ignore" => [
+ "componentBgUrl"
+ ],
+ "style" => "style-2",
+ "num" => 6,
+ "sortWay" => "default",
+ "headStyle" => "style-4",
+ "aroundRadius" => 25,
+ "source" => "custom",
+ "goods_category" => "",
+ "goods_category_name" => "请选择",
+ "goodsNameStyle" => [
+ "color" => "#303133",
+ "control" => true,
+ "fontWeight" => "normal",
+ "isShow" => true
+ ],
+ "priceStyle" => [
+ "color" => "#FF4142",
+ "control" => true,
+ "isShow" => true
+ ],
+ "saleStyle" => [
+ "color" => "#999999",
+ "control" => true,
+ "isShow" => true
+ ],
+ "labelStyle" => [
+ "control" => true,
+ "isShow" => true
+ ],
+ "btnStyle" => [
+ "fontWeight" => false,
+ "padding" => 0,
+ "aroundRadius" => 25,
+ "cartEvent" => "detail",
+ "text" => "购买",
+ "textColor" => "#FFFFFF",
+ "startBgColor" => "#FF4142",
+ "endBgColor" => "#FF4142",
+ "style" => "nc-icon-gouwuche1",
+ "control" => true
+ ],
+ "imgElementRounded" => 12, // 图片圆角
+ "list" => [
+ [
+ "title" => "推荐",
+ "desc" => "猜你喜欢",
+ "source" => "all",
+ "goods_category" => "",
+ "goods_category_name" => "请选择",
+ "goods_ids" => [],
+ "imageUrl" => "",
+ "id" => "67pl1ysjhr40"
+ ],
+ [
+ "id" => "6z59zcmk4jk0",
+ "title" => "衣鞋包饰",
+ "desc" => "分类描述",
+ "source" => "all",
+ "goods_category" => "",
+ "goods_category_name" => "请选择",
+ "goods_ids" => [],
+ "imageUrl" => ""
+ ],
+ [
+ "id" => "1cfbll6wnmw0",
+ "title" => "居家百货",
+ "desc" => "分类描述",
+ "source" => "all",
+ "goods_category" => "",
+ "goods_category_name" => "请选择",
+ "goods_ids" => [],
+ "imageUrl" => ""
+ ],
+ [
+ "id" => "49p79g5l5qs0",
+ "title" => "食品营养",
+ "desc" => "分类描述",
+ "source" => "all",
+ "goods_category" => "",
+ "goods_category_name" => "请选择",
+ "goods_ids" => [],
+ "imageUrl" => ""
+ ]
+ ],
+ "textColor" => "#303133",
+ "pageStartBgColor" => "rgba(255, 255, 255, 1)",
+ "pageEndBgColor" => "rgba(255, 255, 255, 0.4)",
+ "pageGradientAngle" => "to bottom",
+ "componentBgUrl" => "",
+ "componentBgAlpha" => 2,
+ "componentStartBgColor" => null,
+ "componentEndBgColor" => null,
+ "componentGradientAngle" => "to bottom",
+ "topRounded" => 0,
+ "bottomRounded" => 0,
+ "elementBgColor" => "",
+ "topElementRounded" => 12,
+ "bottomElementRounded" => 12,
+ "margin" => [
+ "top" => 0,
+ "bottom" => 0,
+ "both" => 10
+ ],
+ "pageStyle" => "background:linear-gradient(to bottom,rgba(255, 255, 255, 1),rgba(255, 255, 255, 0.4));padding-top:2rpx;padding-bottom:0rpx;padding-right:20rpx;padding-left:20rpx;"
+ ]
+ ]
+ ]
+ ],
+ 'shop_index_style1' => [ // 页面标识
+ "title" => "商城首页2", // 页面名称
+ 'cover' => 'addon/shop/diy/template/shop_index_one_cover.png', // 页面封面图
+ 'preview' => '', // 页面预览图
+ 'desc' => '', // 页面描述
+ 'mode' => 'diy', // 页面模式:diy:自定义,fixed:固定
+ // 页面数据源
+ "data" => [
+ "global" => [
+ "title" => "首页",
+ 'pageStartBgColor' => 'rgba(246, 246, 246, 1)',
+ 'pageEndBgColor' => '',
+ 'pageGradientAngle' => 'to bottom',
+ "bgUrl" => "",
+ 'bgHeightScale' => 0,
+ "imgWidth" => "",
+ "imgHeight" => "",
+ "topStatusBar" => [
+ 'control' => true,
+ 'isShow' => false,
+ 'bgColor' => "#ffffff",
+ 'rollBgColor' => "#ffffff",
+ 'style' => 'style-1',
+ 'styleName' => '风格1',
+ 'textColor' => "#333333",
+ 'rollTextColor' => "#333333",
+ 'textAlign' => 'center',
+ 'inputPlaceholder' => '请输入搜索关键词',
+ 'imgUrl' => '',
+ 'link' => [
+ 'name' => ""
+ ]
+ ],
+ "bottomTabBar" => [
+ 'control' => true,
+ 'isShow' => true,
+ 'designNav' => [
+ 'title' => '',
+ 'key' => ''
+ ]
+ ],
+ "copyright" => [
+ 'control' => true,
+ 'isShow' => false,
+ 'textColor' =>'#ccc'
+ ],
+ "popWindow" => [
+ "imgUrl" => "",
+ "imgWidth" => "",
+ "imgHeight" => "",
+ "count" => 'once',
+ "show" => 0,
+ "link" => [
+ "name" => ""
+ ]
+ ],
+ "template" => [
+ "textColor" => "#303133",
+ 'pageStartBgColor' => '',
+ 'pageEndBgColor' => '',
+ 'pageGradientAngle' => 'to bottom',
+ 'componentBgUrl' => '',
+ 'componentBgAlpha' => 2,
+ "componentStartBgColor" => "",
+ "componentEndBgColor" => "",
+ "componentGradientAngle" => "to bottom",
+ "topRounded" => 0,
+ "bottomRounded" => 0,
+ "elementBgColor" => "",
+ "topElementRounded" => 0,
+ "bottomElementRounded" => 0,
+ "margin" => [
+ "top" => 0,
+ "bottom" => 0,
+ "both" => 0
+ ]
+ ]
+ ],
+ "value" => [
+ [
+ "path" => "edit-carousel-search",
+ "uses" => 1,
+ "position" => "top_fixed",
+ "id" => "5wyf9s0k8jw0",
+ "componentName" => "CarouselSearch",
+ "componentTitle" => "轮播搜索",
+ "ignore" => [
+ "componentBgColor",
+ "componentBgUrl",
+ "marginTop",
+ "marginBottom",
+ "topRounded",
+ "bottomRounded",
+ "pageBgColor",
+ "marginBoth"
+ ],
+ "positionWay" => "fixed",
+ "fixedBgColor" => "",
+ 'bgGradient' => true,
+ "search" => [
+ "logo" => "addon/shop/diy/index/style2/logo.png",
+ "text" => "请输入搜索关键词",
+ "link" => [
+ 'name' => 'SHOP_GOODS_SEARCH',
+ "parent" => "SHOP_LINK",
+ 'title' => '商品搜索',
+ 'url' => '/addon/shop/pages/goods/search',
+ 'action' => '',
+ ],
+ 'style' => 'style-1',
+ 'styleName' => '风格一',
+ "subTitle" => [
+ "text" => "本地好价·优选生活",
+ "textColor" => "#000000",
+ "startColor" => "rgba(255,255,255,0.7)",
+ "endColor" => "",
+ ],
+ 'positionColor' => '#ffffff',
+ 'hotWord' => [
+ "interval" => 3,
+ 'list' => [
+ [
+ 'text' => '新品推荐'
+ ],
+ [
+ 'text' => '爆款'
+ ]
+ ]
+ ]
+ ],
+ "tab" => [
+ "control" => true,
+ "noColor" => "rgba(255, 255, 255, 1)",
+ "selectColor" => "rgba(255, 255, 255, 1)",
+ "fixedNoColor" => "rgba(255, 255, 255, 1)",
+ "fixedSelectColor" => "rgba(255, 255, 255, 1)",
+ "list" => [
+ [
+ "text" => "精选",
+ "source" => "diy_page",
+ "diy_id" => 0,
+ "diy_title" => "",
+ "id" => "4tbvliuezhq0"
+ ],
+ [
+ "text" => "猜你喜欢",
+ "source" => "diy_page",
+ "diy_id" => 0,
+ "diy_title" => "",
+ "id" => "1rpxkuehd03k"
+ ],
+ [
+ "text" => "蔬菜",
+ "source" => "diy_page",
+ "diy_id" => 0,
+ "diy_title" => "",
+ "id" => "6d0zybcxzvc0"
+ ],
+ [
+ "text" => "水果",
+ "source" => "diy_page",
+ "diy_id" => 0,
+ "diy_title" => "",
+ "id" => "17r58ld9i8xs"
+ ],
+ [
+ "id" => "5acf7ab4f040",
+ "text" => "海鲜",
+ "source" => "diy_page",
+ "diy_id" => 0,
+ "diy_title" => ""
+ ],
+ [
+ "id" => "37a9vwqt1r20",
+ "text" => "熟食",
+ "source" => "diy_page",
+ "diy_id" => 0,
+ "diy_title" => ""
+ ],
+ [
+ "id" => "1en9w5jstvs0",
+ "text" => "米面",
+ "source" => "diy_page",
+ "diy_id" => 0,
+ "diy_title" => ""
+ ],
+ [
+ "id" => "3ae14irgqoa0",
+ "text" => "粮油",
+ "source" => "diy_page",
+ "diy_id" => 0,
+ "diy_title" => " "
+ ]
+ ]
+ ],
+ "swiper" => [
+ "control" => true,
+ "interval" => 5,
+ "indicatorColor" => "rgba(0, 0, 0, 0.3)",
+ "indicatorActiveColor" => "#FF0E0E",
+ 'indicatorStyle' => 'style-1',
+ 'indicatorAlign' => 'center',
+ 'swiperStyle' => 'style-1',
+ "imageHeight" => 158,
+ "topRounded" => 10,
+ "bottomRounded" => 10,
+ "list" => [
+ [
+ "imageUrl" => "addon/shop/diy/index/style2/banner1.png",
+ "imgWidth" => 630,
+ "imgHeight" => 290,
+ "link" => [
+ "name" => ""
+ ],
+ "id" => "2ywogh006ai0",
+ "width" => 345,
+ "height" => 158.8095238095238
+ ],
+ [
+ "id" => "3p7wiewe0o00",
+ "imageUrl" => "addon/shop/diy/index/style2/banner2.png",
+ "imgWidth" => 630,
+ "imgHeight" => 290,
+ "link" => [
+ "name" => ""
+ ]
+ ]
+ ]
+ ],
+ 'color' => '#999999',
+ 'btnColor' => '#ffffff',
+ 'bgColor' => '#ffffff',
+ 'btnBgColor' => '#ff3434',
+ "textColor" => "#303133",
+ 'pageStartBgColor' => '',
+ 'pageEndBgColor' => '',
+ 'pageGradientAngle' => 'to bottom',
+ 'componentBgUrl' => '',
+ 'componentBgAlpha' => 2,
+ "componentStartBgColor" => "",
+ "componentEndBgColor" => "",
+ "componentGradientAngle" => "to bottom",
+ "topRounded" => 12,
+ "bottomRounded" => 12,
+ "elementBgColor" => "",
+ "topElementRounded" => 0,
+ "bottomElementRounded" => 0,
+ "margin" => [
+ "top" => 0,
+ "bottom" => 0,
+ "both" => 0
+ ]
+ ],
+ [
+ "path" => "edit-graphic-nav",
+ "uses" => 0,
+ "id" => "6lvx8ztvquc0",
+ "componentName" => "GraphicNav",
+ "componentTitle" => "图文导航",
+ "ignore" => [],
+ "layout" => "horizontal",
+ "mode" => "graphic",
+ "showStyle" => "fixed",
+ "rowCount" => 5,
+ "pageCount" => 2,
+ "carousel" => [
+ "type" => "circle",
+ "color" => "#FFFFFF"
+ ],
+ "imageSize" => 40,
+ "aroundRadius" => 25,
+ "font" => [
+ "size" => 12,
+ "weight" => "normal",
+ "color" => "#303133"
+ ],
+ "list" => [
+ [
+ "title" => "签到",
+ "link" => [
+ "name" => "MEMBER_MY_SIGN_IN",
+ "parent" => "MEMBER_LINK",
+ "title" => "我的签到",
+ "url" => "/app/pages/member/sign_in",
+ "action" => ""
+ ],
+ "imageUrl" => "addon/shop/diy/index/style2/nav_sign_in.png",
+ "label" => [
+ "control" => false,
+ "text" => "热门",
+ "textColor" => "#FFFFFF",
+ "bgColorStart" => "#F83287",
+ "bgColorEnd" => "#FE3423"
+ ],
+ "id" => "1evjnc3zeb5s",
+ "imgWidth" => 135,
+ "imgHeight" => 135
+ ],
+ [
+ "title" => "分销管理",
+ "link" => [
+ "name" => "SHOP_FENXIAO_INDEX",
+ "parent" => "SHOP_FENXIAO_LINK",
+ "title" => "分销中心",
+ "url" => "/addon/shop_fenxiao/pages/index",
+ "action" => ""
+ ],
+ "imageUrl" => "addon/shop/diy/index/style2/nav_fenxiao.png",
+ "label" => [
+ "control" => false,
+ "text" => "热门",
+ "textColor" => "#FFFFFF",
+ "bgColorStart" => "#F83287",
+ "bgColorEnd" => "#FE3423"
+ ],
+ "id" => "2ktzer8wrnc0",
+ "imgWidth" => 180,
+ "imgHeight" => 180
+ ],
+ [
+ "title" => "分销专区",
+ "link" => [
+ "name" => "SHOP_FENXIAO_ZONE",
+ "parent" => "SHOP_FENXIAO_LINK",
+ "title" => "分销专区",
+ "url" => "/addon/shop_fenxiao/pages/zone",
+ "action" => "decorate"
+ ],
+ "imageUrl" => "addon/shop/diy/index/style2/nav_fenxiao_zone.png",
+ "label" => [
+ "control" => false,
+ "text" => "热门",
+ "textColor" => "#FFFFFF",
+ "bgColorStart" => "#F83287",
+ "bgColorEnd" => "#FE3423"
+ ],
+ "id" => "4aixr8qu5ek0",
+ "imgWidth" => 135,
+ "imgHeight" => 135
+ ],
+ [
+ "title" => "领券中心",
+ "link" => [
+ "name" => "SHOP_COUPON_LIST",
+ "parent" => "SHOP_LINK",
+ "title" => "优惠券列表",
+ "url" => "/addon/shop/pages/coupon/list",
+ "action" => ""
+ ],
+ "imageUrl" => "addon/shop/diy/index/style2/nav_coupon.png",
+ "label" => [
+ "control" => false,
+ "text" => "热门",
+ "textColor" => "#FFFFFF",
+ "bgColorStart" => "#F83287",
+ "bgColorEnd" => "#FE3423"
+ ],
+ "id" => "3bmtyrslxxy0",
+ "imgWidth" => 180,
+ "imgHeight" => 180
+ ],
+ [
+ "id" => "6iux9g1aojo0",
+ "title" => "新闻资讯",
+ "imageUrl" => "addon/shop/diy/index/style2/nav_news_info.png",
+ "imgWidth" => 180,
+ "imgHeight" => 180,
+ "link" => [
+ "name" => ""
+ ],
+ "label" => [
+ "control" => false,
+ "text" => "热门",
+ "textColor" => "#FFFFFF",
+ "bgColorStart" => "#F83287",
+ "bgColorEnd" => "#FE3423"
+ ]
+ ],
+ [
+ "id" => "7jggy5euv3w0",
+ "title" => "限时折扣",
+ "imageUrl" => "addon/shop/diy/index/style2/nav_discount.png",
+ "imgWidth" => 135,
+ "imgHeight" => 135,
+ "link" => [
+ "name" => "SHOP_DISCOUNT_LIST",
+ "parent" => "SHOP_LINK",
+ "title" => "限时折扣列表",
+ 'url' => '/addon/shop/pages/discount/list',
+ "action" => ""
+ ],
+ "label" => [
+ "control" => false,
+ "text" => "热门",
+ "textColor" => "#FFFFFF",
+ "bgColorStart" => "#F83287",
+ "bgColorEnd" => "#FE3423"
+ ]
+ ],
+ [
+ "id" => "7bqpc6bjha80",
+ "title" => "积分商城",
+ "imageUrl" => "addon/shop/diy/index/style2/nav_point_index.png",
+ "imgWidth" => 135,
+ "imgHeight" => 135,
+ "link" => [
+ "name" => "SHOP_POINT_INDEX",
+ "parent" => "SHOP_LINK",
+ "title" => "积分商城",
+ 'url' => '/addon/shop/pages/point/index',
+ "action" => ""
+ ],
+ "label" => [
+ "control" => false,
+ "text" => "热门",
+ "textColor" => "#FFFFFF",
+ "bgColorStart" => "#F83287",
+ "bgColorEnd" => "#FE3423"
+ ]
+ ],
+ [
+ "id" => "tgo5qmjawnk",
+ "title" => "礼品卡",
+ "imageUrl" => "addon/shop/diy/index/style2/nav_giftcard.png",
+ "imgWidth" => 180,
+ "imgHeight" => 180,
+ "link" => [
+ "name" => "SHOP_GIFTCARD_INDEX",
+ "parent" => "SHOP_GIFTCARD_LINK",
+ "title" => "礼品卡",
+ "url" => "/addon/shop_giftcard/pages/index",
+ "action" => ""
+ ],
+ "label" => [
+ "control" => false,
+ "text" => "热门",
+ "textColor" => "#FFFFFF",
+ "bgColorStart" => "#F83287",
+ "bgColorEnd" => "#FE3423"
+ ]
+ ],
+ [
+ "id" => "1fprven2cqrk",
+ "title" => "我的余额",
+ "imageUrl" => "addon/shop/diy/index/style2/nav_my_balance.png",
+ "imgWidth" => 180,
+ "imgHeight" => 180,
+ "link" => [
+ "name" => "MEMBER_BALANCE",
+ "parent" => "MEMBER_LINK",
+ "title" => "我的余额",
+ "url" => "/app/pages/member/balance",
+ "action" => ""
+ ],
+ "label" => [
+ "control" => false,
+ "text" => "热门",
+ "textColor" => "#FFFFFF",
+ "bgColorStart" => "#F83287",
+ "bgColorEnd" => "#FE3423"
+ ]
+ ],
+ [
+ "id" => "2wggehpnako0",
+ "title" => "地址管理",
+ "imageUrl" => "addon/shop/diy/index/style2/nav_my_address.png",
+ "imgWidth" => 180,
+ "imgHeight" => 180,
+ "link" => [
+ "name" => "MEMBER_ADDRESS",
+ "parent" => "MEMBER_LINK",
+ "title" => "收货地址",
+ "url" => "/app/pages/member/address",
+ "action" => ""
+ ],
+ "label" => [
+ "control" => false,
+ "text" => "热门",
+ "textColor" => "#FFFFFF",
+ "bgColorStart" => "#F83287",
+ "bgColorEnd" => "#FE3423"
+ ]
+ ]
+ ],
+ // 轮播图设置
+ 'swiper' => [
+ 'indicatorColor' => 'rgba(0, 0, 0, 0.3)', // 未选中颜色
+ "indicatorActiveColor" => '#FF0E0E',
+ 'indicatorStyle' => 'style-1',
+ 'indicatorAlign' => 'center',
+ ],
+ "textColor" => "#303133",
+ 'pageStartBgColor' => '',
+ 'pageEndBgColor' => '',
+ 'pageGradientAngle' => 'to bottom',
+ 'componentBgUrl' => '',
+ 'componentBgAlpha' => 2,
+ "componentStartBgColor" => "rgba(255, 255, 255, 1)",
+ "componentEndBgColor" => "",
+ "componentGradientAngle" => "to bottom",
+ "topRounded" => 12,
+ "bottomRounded" => 12,
+ "elementBgColor" => "",
+ "topElementRounded" => 0,
+ "bottomElementRounded" => 0,
+ "margin" => [
+ "top" => -1,
+ "bottom" => 5,
+ "both" => 10
+ ]
+ ],
+ [
+ "path" => "edit-notice",
+ "uses" => 0,
+ "id" => "4m9g2ylz1di0",
+ "componentName" => "Notice",
+ "componentTitle" => "公告",
+ "ignore" => [],
+ "noticeType" => "img",
+ "imgType" => "system",
+ "systemUrl" => "style_2",
+ "imageUrl" => "",
+ "showType" => "popup",
+ "scrollWay" => "upDown",
+ "fontSize" => 12,
+ "fontWeight" => "normal",
+ "noticeTitle" => "公告",
+ "list" => [
+ [
+ "text" => "最新公告:欢迎来到小店参观!",
+ "link" => [
+ "name" => ""
+ ],
+ "id" => "1rz6s4buaxc0"
+ ],
+ [
+ "id" => "2wksdax75fc0",
+ "text" => "最新公告:欢迎来到小店参观!",
+ "link" => [
+ "name" => ""
+ ]
+ ]
+ ],
+ "textColor" => "#303133",
+ 'pageStartBgColor' => '',
+ 'pageEndBgColor' => '',
+ 'pageGradientAngle' => 'to bottom',
+ 'componentBgUrl' => '',
+ 'componentBgAlpha' => 2,
+ "componentStartBgColor" => "rgba(255, 255, 255, 1)",
+ "componentEndBgColor" => "",
+ "componentGradientAngle" => "to bottom",
+ "topRounded" => 12,
+ "bottomRounded" => 12,
+ "elementBgColor" => "",
+ "topElementRounded" => 0,
+ "bottomElementRounded" => 0,
+ "margin" => [
+ "top" => 5,
+ "bottom" => 5,
+ "both" => 10
+ ]
+ ],
+ [
+ "path" => "edit-goods-coupon",
+ "uses" => 0,
+ "id" => "52ldidxgpcg0",
+ "componentName" => "GoodsCoupon",
+ "componentTitle" => "优惠券",
+ "ignore" => [
+ "componentBgColor",
+ "componentBgUrl"
+ ],
+ "style" => "style-1",
+ "styleName" => "风格一",
+ "source" => "all",
+ "num" => 6,
+ "couponIds" => [],
+ "btnText" => "立即领取",
+ "couponTitle" => "先领券 再购物",
+ "couponSubTitle" => "领券下单 享购物优惠",
+ "titleColor" => "#ffffff",
+ "subTitleColor" => "#ffffff",
+ "couponItem" => [
+ "bgColor" => "#ffffff",
+ "textColor" => "#333333",
+ "subTextColor" => "#666666",
+ "moneyColor" => "#333333",
+ "aroundRadius" => 12
+ ],
+ "textColor" => "#303133",
+ 'pageStartBgColor' => '',
+ 'pageEndBgColor' => '',
+ 'pageGradientAngle' => 'to bottom',
+ 'componentBgUrl' => '',
+ 'componentBgAlpha' => 2,
+ "componentStartBgColor" => "",
+ "componentEndBgColor" => "",
+ "componentGradientAngle" => "to bottom",
+ "topRounded" => 0,
+ "bottomRounded" => 12,
+ "elementBgColor" => "",
+ "topElementRounded" => 0,
+ "bottomElementRounded" => 0,
+ "margin" => [
+ "top" => 5,
+ "bottom" => 5,
+ "both" => 10
+ ]
+ ],
+ [
+ "path" => "edit-active-cube",
+ "uses" => 0,
+ "id" => "717m86hlcho0",
+ "componentName" => "ActiveCube",
+ "componentTitle" => "活动魔方",
+ "ignore" => [],
+ "titleStyle" => [
+ "title" => "风格1",
+ "value" => "style-1"
+ ],
+ "text" => "超值爆款",
+ "textLink" => [
+ "name" => ""
+ ],
+ "textImg" => "static/resource/images/diy/active_cube/active_cube_text1.png",
+ "titleColor" => "#F91700",
+ "subTitle" => [
+ "text" => "为您精选爆款",
+ "textColor" => "#FFFFFF",
+ "startColor" => "#FB792F",
+ "endColor" => "#F91700",
+ "link" => [
+ "name" => ""
+ ],
+ ],
+ "blockStyle" => [
+ "title" => "风格4",
+ "value" => "style-4",
+ 'fontWeight' => 'bold',
+ 'btnText' => 'normal'
+ ],
+ "list" => [
+ [
+ "title" => [
+ "text" => "今日推荐",
+ "textColor" => "#303133"
+ ],
+ "subTitle" => [
+ "text" => "诚意推荐",
+ "textColor" => "rgba(237, 110, 0, 1)",
+ "startColor" => "rgba(243, 218, 197, 1)",
+ "endColor" => "rgba(255, 228, 217, 1)"
+ ],
+ "moreTitle" => [
+ "text" => "去看看",
+ "startColor" => "#FEA715",
+ "endColor" => "#FE1E00",
+ ],
+ "listFrame" => [
+ "startColor" => "rgba(255, 173, 77, 1)",
+ "endColor" => "rgba(249, 61, 2, 1)"
+ ],
+ "link" => [
+ "name" => ""
+ ],
+ "imageUrl" => "static/resource/images/diy/active_cube/active_cube_goods1.png",
+ "id" => "bvn98cr8j1s"
+ ],
+ [
+ "title" => [
+ "text" => "优惠好物",
+ "textColor" => "#303133"
+ ],
+ "subTitle" => [
+ "text" => "领券优惠",
+ "textColor" => "rgba(46, 89, 233, 1)",
+ "startColor" => "rgba(205, 217, 248, 1)",
+ "endColor" => "rgba(205, 217, 248, 1)"
+ ],
+ "moreTitle" => [
+ "text" => "去看看",
+ "startColor" => "#FFBF50",
+ "endColor" => "#FF9E03"
+ ],
+ "listFrame" => [
+ "startColor" => "rgba(124, 167, 244, 1)",
+ "endColor" => "rgba(43, 86, 233, 1)"
+ ],
+ "link" => [
+ "name" => ""
+ ],
+ "imageUrl" => "static/resource/images/diy/active_cube/active_cube_goods2.png",
+ "id" => "6u24tqbyc780"
+ ],
+ [
+ "title" => [
+ "text" => "热销推荐",
+ "textColor" => "#303133"
+ ],
+ "subTitle" => [
+ "text" => "热销商品",
+ "textColor" => "rgba(246, 47, 85, 1)",
+ "startColor" => "rgba(252, 216, 219, 1)",
+ "endColor" => "rgba(252, 216, 219, 1)"
+ ],
+ "moreTitle" => [
+ "text" => "去看看",
+ "startColor" => "#A2E792",
+ "endColor" => "#49CD2D"
+ ],
+ "listFrame" => [
+ "startColor" => "rgba(255, 127, 72, 1)",
+ "endColor" => "rgba(238, 51, 91, 1)"
+ ],
+ "link" => [
+ "name" => ""
+ ],
+ "imageUrl" => "static/resource/images/diy/active_cube/active_cube_goods3.png",
+ "id" => "6dn1yt1j0as0"
+ ],
+ [
+ "title" => [
+ "text" => "书桌好物",
+ "textColor" => "#303133"
+ ],
+ "subTitle" => [
+ "text" => "好物推荐",
+ "textColor" => "rgba(19, 155, 60, 1)",
+ "startColor" => "rgba(211, 241, 218, 1)",
+ "endColor" => "rgba(211, 241, 218, 1)"
+ ],
+ "moreTitle" => [
+ "text" => "去看看",
+ "startColor" => "#4AC1FF",
+ "endColor" => "#1D7CFF",
+ ],
+ "listFrame" => [
+ "startColor" => "rgba(144, 212, 140, 1)",
+ "endColor" => "rgba(41, 159, 79, 1)"
+ ],
+ "link" => [
+ "name" => ""
+ ],
+ "imageUrl" => "static/resource/images/diy/active_cube/active_cube_goods4.png",
+ "id" => "4q9zphidqtm0"
+ ]
+ ],
+ "textColor" => "#303133",
+ 'pageStartBgColor' => '',
+ 'pageEndBgColor' => '',
+ 'pageGradientAngle' => 'to bottom',
+ 'componentBgUrl' => '',
+ 'componentBgAlpha' => 2,
+ "componentStartBgColor" => "#ffffff",
+ "componentEndBgColor" => "",
+ "componentGradientAngle" => "to bottom",
+ "topRounded" => 12,
+ "bottomRounded" => 12,
+ "elementBgColor" => "#FFFAF5",
+ "topElementRounded" => 10,
+ "bottomElementRounded" => 10,
+ "margin" => [
+ "top" => 5,
+ "bottom" => 5,
+ "both" => 10
+ ]
+ ],
+ [
+ "path" => "edit-active-cube",
+ "uses" => 0,
+ "id" => "3keeqqrkpxk0",
+ "componentName" => "ActiveCube",
+ "componentTitle" => "活动魔方",
+ "ignore" => [],
+ "titleStyle" => [
+ "title" => "风格4",
+ "value" => "style-4"
+ ],
+ "text" => "数码产品",
+ "textImg" => "static/resource/images/diy/active_cube/active_cube_text1.png",
+ "textLink" => [
+ "name" => ""
+ ],
+ "titleColor" => "rgba(255, 255, 255, 1)",
+ "subTitle" => [
+ "text" => "去逛逛",
+ "textColor" => "#303133",
+ "startColor" => "rgba(255, 255, 255, 1)",
+ "endColor" => "rgba(255, 255, 255, 1)",
+ "link" => [
+ "name" => ""
+ ],
+ ],
+ "blockStyle" => [
+ "title" => "风格3",
+ "value" => "style-3",
+ 'fontWeight' => 'normal',
+ 'btnText' => 'normal'
+ ],
+ "list" => [
+ [
+ "title" => [
+ "text" => "蓝牙耳机",
+ "textColor" => "#303133"
+ ],
+ "subTitle" => [
+ "text" => "诚意推荐",
+ "textColor" => "#999999",
+ "startColor" => "",
+ "endColor" => ""
+ ],
+ "moreTitle" => [
+ "text" => "去看看",
+ "startColor" => "#FEA715",
+ "endColor" => "#FE1E00"
+ ],
+ "listFrame" => [
+ "startColor" => "",
+ "endColor" => ""
+ ],
+ "link" => [
+ "name" => ""
+ ],
+ "imageUrl" => "static/resource/images/diy/active_cube/active_cube_goods5.png",
+ "id" => "5am2l07pkr00"
+ ],
+ [
+ "title" => [
+ "text" => "医用雾化",
+ "textColor" => "#303133"
+ ],
+ "subTitle" => [
+ "text" => "领券更优惠",
+ "textColor" => "#999999",
+ "startColor" => "",
+ "endColor" => ""
+ ],
+ "moreTitle" => [
+ "text" => "去看看",
+ "startColor" => "#FFBF50",
+ "endColor" => "#FF9E03"
+ ],
+ "listFrame" => [
+ "startColor" => "",
+ "endColor" => ""
+ ],
+ "link" => [
+ "name" => ""
+ ],
+ "imageUrl" => "static/resource/images/diy/active_cube/active_cube_goods6.png",
+ "id" => "2v4zusih9u80"
+ ],
+ [
+ "title" => [
+ "text" => "智能手表",
+ "textColor" => "#303133"
+ ],
+ "subTitle" => [
+ "text" => "本周热销商品",
+ "textColor" => "#999999",
+ "startColor" => "",
+ "endColor" => ""
+ ],
+ "moreTitle" => [
+ "text" => "去看看",
+ "startColor" => "#A2E792",
+ "endColor" => "#49CD2D"
+ ],
+ "listFrame" => [
+ "startColor" => "",
+ "endColor" => ""
+ ],
+ "link" => [
+ "name" => ""
+ ],
+ "imageUrl" => "static/resource/images/diy/active_cube/active_cube_goods7.png",
+ "id" => "va5dyomnq68"
+ ],
+ [
+ "title" => [
+ "text" => "甜心咖啡",
+ "textColor" => "#303133"
+ ],
+ "subTitle" => [
+ "text" => "办公好物推荐",
+ "textColor" => "#999999",
+ "startColor" => "",
+ "endColor" => ""
+ ],
+ "moreTitle" => [
+ "text" => "去看看",
+ "startColor" => "#4AC1FF",
+ "endColor" => "#1D7CFF"
+ ],
+ "listFrame" => [
+ "startColor" => "",
+ "endColor" => ""
+ ],
+ "link" => [
+ "name" => ""
+ ],
+ "imageUrl" => "static/resource/images/diy/active_cube/active_cube_goods8.png",
+ "id" => "4h16lw3ntsw0"
+ ]
+ ],
+ "textColor" => "#303133",
+ "pageStartBgColor" => "",
+ "pageEndBgColor" => "",
+ "pageGradientAngle" => "to bottom",
+ "componentBgUrl" => "static/resource/images/diy/active_cube/active_cube_bg.png",
+ "componentBgAlpha" => 7,
+ "componentStartBgColor" => "",
+ "componentEndBgColor" => "",
+ "componentGradientAngle" => "to bottom",
+ "topRounded" => 12,
+ "bottomRounded" => 12,
+ "elementBgColor" => "#FFFAF5",
+ "topElementRounded" => 10,
+ "bottomElementRounded" => 10,
+ "margin" => [
+ "top" => 5,
+ "bottom" => 5,
+ "both" => 10
+ ]
+ ],
+ [
+ "path" => "edit-horz-blank",
+ "uses" => 0,
+ "id" => "6nc7hkh3g100",
+ "componentName" => "HorzBlank",
+ "componentTitle" => "辅助空白",
+ "ignore" => [
+ "pageBgColor",
+ "componentBgUrl"
+ ],
+ "textColor" => "#303133",
+ "pageStartBgColor" => "",
+ "pageEndBgColor" => "",
+ "pageGradientAngle" => "to bottom",
+ "componentBgUrl" => "",
+ "componentBgAlpha" => 2,
+ "componentStartBgColor" => "rgba(255, 169, 97, 1)",
+ "componentEndBgColor" => "rgba(250, 61, 61, 1)",
+ "componentGradientAngle" => "to right",
+ "topRounded" => 12,
+ "bottomRounded" => 0,
+ "elementBgColor" => "",
+ "topElementRounded" => 0,
+ "bottomElementRounded" => 0,
+ "margin" => [
+ "top" => 5,
+ "bottom" => 0,
+ "both" => 10
+ ],
+ "height" => 10
+ ],
+ [
+ "path" => "edit-text",
+ "uses" => 0,
+ "position" => "",
+ "id" => "7f1nc9pkntw0",
+ "componentName" => "Text",
+ "componentTitle" => "标题",
+ "ignore" => [],
+ "style" => "style-2",
+ "styleName" => "风格2",
+ "text" => "新人尝鲜价",
+ "link" => [
+ "name" => ""
+ ],
+ "textColor" => "#FFFFFF",
+ "fontSize" => 15,
+ "fontWeight" => "normal",
+ "textAlign" => "center",
+ "subTitle" => [
+ "text" => "数量有限 抢完为止",
+ "color" => "#FFFFFF",
+ "fontSize" => 12,
+ "control" => true,
+ "fontWeight" => "normal"
+ ],
+ "more" => [
+ "text" => "查看更多",
+ "control" => true,
+ "isShow" => false,
+ "link" => [
+ "name" => ""
+ ],
+ "color" => "#999999"
+ ],
+ 'pageStartBgColor' => '',
+ 'pageEndBgColor' => '',
+ 'pageGradientAngle' => 'to bottom',
+ 'componentBgUrl' => '',
+ 'componentBgAlpha' => 2,
+ "componentStartBgColor" => "rgba(255, 169, 97, 1)",
+ "componentEndBgColor" => "rgba(250, 61, 61, 1)",
+ "componentGradientAngle" => "to right",
+ "topRounded" => 0,
+ "bottomRounded" => 0,
+ "elementBgColor" => "",
+ "topElementRounded" => 0,
+ "bottomElementRounded" => 0,
+ "margin" => [
+ "top" => 0,
+ "bottom" => 0,
+ "both" => 10
+ ]
+ ],
+ [
+ "path" => "edit-horz-blank",
+ "uses" => 0,
+ "id" => "1o6ptkjsnabk",
+ "componentName" => "HorzBlank",
+ "componentTitle" => "辅助空白",
+ "ignore" => [
+ "pageBgColor",
+ "componentBgUrl"
+ ],
+ "textColor" => "#303133",
+ "pageStartBgColor" => "",
+ "pageEndBgColor" => "",
+ "pageGradientAngle" => "to bottom",
+ "componentBgUrl" => "",
+ "componentBgAlpha" => 2,
+ "componentStartBgColor" => "rgba(255, 169, 97, 1)",
+ "componentEndBgColor" => "rgba(250, 61, 61, 1)",
+ "componentGradientAngle" => "to right",
+ "topRounded" => 0,
+ "bottomRounded" => 0,
+ "elementBgColor" => "",
+ "topElementRounded" => 0,
+ "bottomElementRounded" => 0,
+ "margin" => [
+ "top" => 0,
+ "bottom" => 0,
+ "both" => 10
+ ],
+ "height" => 10
+ ],
+ [
+ "path" => "edit-goods-list",
+ "uses" => 0,
+ "id" => "17uao387qdds",
+ "componentName" => "GoodsList",
+ "componentTitle" => "商品列表",
+ "ignore" => [],
+ "style" => "style-3",
+ "source" => "all",
+ "num" => 10,
+ "goods_category" => "",
+ "goods_category_name" => "请选择",
+ "goods_ids" => [],
+ "sortWay" => "default",
+ "goodsNameStyle" => [
+ "color" => "#303133",
+ "control" => true,
+ "fontWeight" => "normal",
+ "isShow" => true
+ ],
+ "priceStyle" => [
+ "color" => "#FF4142",
+ "control" => true,
+ "isShow" => true
+ ],
+ "saleStyle" => [
+ "color" => "#999999",
+ "control" => true,
+ "isShow" => true
+ ],
+ "labelStyle" => [
+ "control" => true,
+ "isShow" => true
+ ],
+ "btnStyle" => [
+ "fontWeight" => false,
+ "padding" => 0,
+ "aroundRadius" => 25,
+ "cartEvent" => "detail",
+ "text" => "购买",
+ "textColor" => "#FFFFFF",
+ "startBgColor" => "#FF4142",
+ "endBgColor" => "#FF4142",
+ "style" => "nc-icon-jiahaoV6xx",
+ "control" => true
+ ],
+ "imgElementRounded" => 10,// 图片圆角
+ "textColor" => "#303133",
+ 'pageStartBgColor' => '',
+ 'pageEndBgColor' => '',
+ 'pageGradientAngle' => 'to bottom',
+ 'componentBgUrl' => '',
+ 'componentBgAlpha' => 2,
+ "componentStartBgColor" => "rgba(255, 169, 97, 1)",
+ "componentEndBgColor" => "rgba(250, 61, 61, 1)",
+ "componentGradientAngle" => "to right",
+ "topRounded" => 0,
+ "bottomRounded" => 12,
+ "elementBgColor" => "",
+ "topElementRounded" => 10,
+ "bottomElementRounded" => 10,
+ "margin" => [
+ "top" => 0,
+ "bottom" => 9,
+ "both" => 10
+ ]
+ ],
+ [
+ "path" => "edit-horz-blank",
+ "uses" => 0,
+ "id" => "4z9jltfk8jc0",
+ "componentName" => "HorzBlank",
+ "componentTitle" => "辅助空白",
+ "ignore" => [
+ "pageBgColor",
+ "componentBgUrl"
+ ],
+ "textColor" => "#303133",
+ "pageStartBgColor" => "",
+ "pageEndBgColor" => "",
+ "pageGradientAngle" => "to bottom",
+ "componentBgUrl" => "",
+ "componentBgAlpha" => 2,
+ "componentStartBgColor" => "rgba(253, 41, 52, 1)",
+ "componentEndBgColor" => "",
+ "componentGradientAngle" => "to bottom",
+ "topRounded" => 12,
+ "bottomRounded" => 0,
+ "elementBgColor" => "",
+ "topElementRounded" => 0,
+ "bottomElementRounded" => 0,
+ "margin" => [
+ "top" => 5,
+ "bottom" => 0,
+ "both" => 10
+ ],
+ "height" => 10
+ ],
+ [
+ "path" => "edit-text",
+ "uses" => 0,
+ "position" => "",
+ "id" => "65qaokgbzg80",
+ "componentName" => "Text",
+ "componentTitle" => "标题",
+ "ignore" => [],
+ "style" => "style-2",
+ "styleName" => "风格2",
+ "text" => "今日疯抢",
+ "link" => [
+ "name" => ""
+ ],
+ "textColor" => "#FFFFFF",
+ "fontSize" => 15,
+ "fontWeight" => "normal",
+ "textAlign" => "center",
+ "subTitle" => [
+ "text" => "数量有限 抢完为止",
+ "color" => "#FFFFFF",
+ "fontSize" => 12,
+ "control" => true,
+ "fontWeight" => "normal"
+ ],
+ "more" => [
+ "text" => "查看更多",
+ "control" => true,
+ "isShow" => false,
+ "link" => [
+ "name" => ""
+ ],
+ "color" => "#999999"
+ ],
+ 'pageStartBgColor' => '',
+ 'pageEndBgColor' => '',
+ 'pageGradientAngle' => 'to bottom',
+ 'componentBgUrl' => '',
+ 'componentBgAlpha' => 2,
+ "componentStartBgColor" => "rgba(253, 41, 52, 1)",
+ "componentEndBgColor" => "",
+ "componentGradientAngle" => "to bottom",
+ "topRounded" => 0,
+ "bottomRounded" => 0,
+ "elementBgColor" => "",
+ "topElementRounded" => 0,
+ "bottomElementRounded" => 0,
+ "margin" => [
+ "top" => 0,
+ "bottom" => 0,
+ "both" => 10
+ ]
+ ],
+ [
+ "path" => "edit-goods-list",
+ "uses" => 0,
+ "id" => "2u96wyrm79u0",
+ "componentName" => "GoodsList",
+ "componentTitle" => "商品列表",
+ "ignore" => [],
+ "style" => "style-1",
+ "source" => "all",
+ "num" => 10,
+ "goods_category" => "",
+ "goods_category_name" => "请选择",
+ "goods_ids" => [],
+ "sortWay" => "default",
+ "goodsNameStyle" => [
+ "color" => "#303133",
+ "control" => true,
+ "fontWeight" => "normal",
+ "isShow" => true
+ ],
+ "priceStyle" => [
+ "color" => "#FF4142",
+ "control" => true,
+ "isShow" => true
+ ],
+ "saleStyle" => [
+ "color" => "#999999",
+ "control" => true,
+ "isShow" => true
+ ],
+ "labelStyle" => [
+ "control" => true,
+ "isShow" => true
+ ],
+ "btnStyle" => [
+ "fontWeight" => false,
+ "padding" => 0,
+ "aroundRadius" => 25,
+ "cartEvent" => "detail",
+ "text" => "购买",
+ "textColor" => "#FFFFFF",
+ "startBgColor" => "#FF4142",
+ "endBgColor" => "#FF4142",
+ "style" => "button",
+ "control" => true
+ ],
+ "imgElementRounded" => 10,// 图片圆角
+ "textColor" => "#303133",
+ 'pageStartBgColor' => '',
+ 'pageEndBgColor' => '',
+ 'pageGradientAngle' => 'to bottom',
+ 'componentBgUrl' => '',
+ 'componentBgAlpha' => 2,
+ "componentStartBgColor" => "",
+ "componentEndBgColor" => "",
+ "componentGradientAngle" => "to bottom",
+ "topRounded" => 0,
+ "bottomRounded" => 12,
+ "elementBgColor" => "",
+ "topElementRounded" => 10,
+ "bottomElementRounded" => 10,
+ "margin" => [
+ "top" => 0,
+ "bottom" => 5,
+ "both" => 10
+ ]
+ ],
+ [
+ "path" => "edit-text",
+ "uses" => 0,
+ "position" => "",
+ "id" => "5izyn9jcz3k0",
+ "componentName" => "Text",
+ "componentTitle" => "标题",
+ "ignore" => [],
+ "style" => "style-1",
+ "styleName" => "风格1",
+ "text" => "精选推荐",
+ "link" => [
+ "name" => ""
+ ],
+ "textColor" => "#303133",
+ "fontSize" => 15,
+ "fontWeight" => "normal",
+ "textAlign" => "center",
+ "subTitle" => [
+ "text" => "副标题",
+ "color" => "#999999",
+ "fontSize" => 14,
+ "control" => false,
+ "fontWeight" => "normal"
+ ],
+ "more" => [
+ "text" => "查看更多",
+ "control" => false,
+ "isShow" => true,
+ "link" => [
+ "name" => ""
+ ],
+ "color" => "#999999"
+ ],
+ 'pageStartBgColor' => '',
+ 'pageEndBgColor' => '',
+ 'pageGradientAngle' => 'to bottom',
+ 'componentBgUrl' => '',
+ 'componentBgAlpha' => 2,
+ "componentStartBgColor" => "",
+ "componentEndBgColor" => "",
+ "componentGradientAngle" => "to bottom",
+ "topRounded" => 0,
+ "bottomRounded" => 0,
+ "elementBgColor" => "",
+ "topElementRounded" => 0,
+ "bottomElementRounded" => 0,
+ "margin" => [
+ "top" => 20,
+ "bottom" => 15,
+ "both" => 0
+ ]
+ ],
+ [
+ "path" => "edit-goods-list",
+ "uses" => 0,
+ "id" => "4y7mw7j2uko0",
+ "componentName" => "GoodsList",
+ "componentTitle" => "商品列表",
+ "ignore" => [],
+ "style" => "style-2",
+ "source" => "all",
+ "num" => 10,
+ "goods_category" => "",
+ "goods_category_name" => "请选择",
+ "goods_ids" => [],
+ "sortWay" => "default",
+ "goodsNameStyle" => [
+ "color" => "#303133",
+ "control" => true,
+ "fontWeight" => "normal",
+ "isShow" => true
+ ],
+ "priceStyle" => [
+ "color" => "#FF4142",
+ "control" => true,
+ "isShow" => true
+ ],
+ "saleStyle" => [
+ "color" => "#999999",
+ "control" => true,
+ "isShow" => true
+ ],
+ "labelStyle" => [
+ "control" => true,
+ "isShow" => true
+ ],
+ "btnStyle" => [
+ "fontWeight" => false,
+ "padding" => 0,
+ "aroundRadius" => 25,
+ "cartEvent" => "detail",
+ "text" => "购买",
+ "textColor" => "#FFFFFF",
+ "startBgColor" => "#FF4142",
+ "endBgColor" => "#FF4142",
+ "style" => "button",
+ "control" => true
+ ],
+ "imgElementRounded" => 12,// 图片圆角
+ "textColor" => "#303133",
+ 'pageStartBgColor' => '',
+ 'pageEndBgColor' => '',
+ 'pageGradientAngle' => 'to bottom',
+ 'componentBgUrl' => '',
+ 'componentBgAlpha' => 2,
+ "componentStartBgColor" => "",
+ "componentEndBgColor" => "",
+ "componentGradientAngle" => "to bottom",
+ "topRounded" => 12,
+ "bottomRounded" => 12,
+ "elementBgColor" => "",
+ "topElementRounded" => 12,
+ "bottomElementRounded" => 12,
+ "margin" => [
+ "top" => 5,
+ "bottom" => 5,
+ "both" => 10
+ ]
+ ],
+ [
+ "path" => "edit-many-goods-list",
+ "uses" => 0,
+ "id" => "65lv65b38ig0",
+ "componentName" => "ManyGoodsList",
+ "componentTitle" => "多商品组",
+ "ignore" => ['componentBgUrl'],
+ "style" => "style-2",
+ "num" => 6,
+ "sortWay" => "default",
+ "headStyle" => "style-2",
+ "aroundRadius" => 25,
+ "source" => "custom",
+ "goodsNameStyle" => [
+ "color" => "#303133",
+ "control" => true,
+ "fontWeight" => "normal",
+ "isShow" => true
+ ],
+ "priceStyle" => [
+ "color" => "#FF4142",
+ "control" => true,
+ "isShow" => true
+ ],
+ "saleStyle" => [
+ "color" => "#999999",
+ "control" => true,
+ "isShow" => true
+ ],
+ "labelStyle" => [
+ "control" => true,
+ "isShow" => true
+ ],
+ "imgElementRounded" => 12, // 图片圆角
+ "btnStyle" => [
+ "fontWeight" => false,
+ "padding" => 0,
+ "aroundRadius" => 25,
+ "cartEvent" => "detail",
+ "text" => "购买",
+ "textColor" => "#FFFFFF",
+ "startBgColor" => "#FF4142",
+ "endBgColor" => "#FF4142",
+ "style" => "button",
+ "control" => true
+ ],
+ "list" => [
+ [
+ "title" => "推荐",
+ "desc" => "猜你喜欢",
+ "source" => "all",
+ "goods_category" => "",
+ "goods_category_name" => "请选择",
+ "goods_ids" => [],
+ "id" => "2iljdx2ajqg0"
+ ],
+ [
+ "id" => "3a1x4kgbre40",
+ "title" => "衣鞋包饰",
+ "desc" => "分类描述",
+ "source" => "all",
+ "goods_category" => "",
+ "goods_category_name" => "请选择",
+ "goods_ids" => []
+ ],
+ [
+ "id" => "12ozjal2rfe8",
+ "title" => "居家百货",
+ "desc" => "分类描述",
+ "source" => "all",
+ "goods_category" => "",
+ "goods_category_name" => "请选择",
+ "goods_ids" => []
+ ],
+ [
+ "id" => "71kwrfxeoxw0",
+ "title" => "热卖好物",
+ "desc" => "分类描述",
+ "source" => "all",
+ "goods_category" => "",
+ "goods_category_name" => "请选择",
+ "goods_ids" => []
+ ],
+ [
+ "id" => "5tktk8897ag0",
+ "title" => "优品精选",
+ "desc" => "分类描述",
+ "source" => "all",
+ "goods_category" => "",
+ "goods_category_name" => "请选择",
+ "goods_ids" => []
+ ]
+ ],
+ "textColor" => "#303133",
+ 'pageStartBgColor' => '',
+ 'pageEndBgColor' => '',
+ 'pageGradientAngle' => 'to bottom',
+ 'componentBgUrl' => '',
+ 'componentBgAlpha' => 2,
+ "componentStartBgColor" => "rgba(255, 255, 255, 1)",
+ "componentEndBgColor" => "",
+ "componentGradientAngle" => "to bottom",
+ "topRounded" => 12,
+ "bottomRounded" => 12,
+ "elementBgColor" => "",
+ "topElementRounded" => 12,
+ "bottomElementRounded" => 12,
+ "margin" => [
+ "top" => 10,
+ "bottom" => 10,
+ "both" => 10
+ ]
+ ]
+ ]
+ ]
+ ],
+ 'shop_index' => [ // 页面标识
+ "title" => "商城首页3", // 页面名称
+ 'cover' => 'addon/shop/diy/template/shop_index_two_cover.png', // 页面封面图
+ 'preview' => '', // 页面预览图
+ 'desc' => '', // 页面描述
+ 'mode' => 'diy', // 页面模式:diy:自定义,fixed:固定
+ // 页面数据源
+ "data" => [
+ "global" => [
+ "title" => "首页",
+ 'pageStartBgColor' => 'rgba(255, 255, 255, 1)',
+ 'pageEndBgColor' => '',
+ 'pageGradientAngle' => 'to bottom',
+ "bgUrl" => "addon/shop/diy/index/bg.png",
+ 'bgHeightScale' => 0,
+ "imgWidth" => 750,
+ "imgHeight" => 1485,
+ "bottomTabBar" => [
+ 'control' => true,
+ 'isShow' => true,
+ 'designNav' => [
+ 'title' => '',
+ 'key' => ''
+ ]
+ ],
+ "copyright" => [
+ 'control' => true,
+ 'isShow' => false,
+ 'textColor' =>'#ccc'
+ ],
+ "template" => [
+ 'textColor' => "#303133",
+ 'pageStartBgColor' => '',
+ 'pageEndBgColor' => '',
+ 'pageGradientAngle' => 'to bottom',
+ 'componentBgUrl' => '',
+ 'componentBgAlpha' => 2,
+ "componentStartBgColor" => "",
+ "componentEndBgColor" => "",
+ "componentGradientAngle" => "to bottom",
+ "topRounded" => 0,
+ "bottomRounded" => 0,
+ "elementBgColor" => "",
+ "topElementRounded" => 0,
+ "bottomElementRounded" => 0,
+ "margin" => [
+ "top" => 0,
+ "bottom" => 0,
+ "both" => 10
+ ]
+ ],
+ 'topStatusBar' => [
+ 'control' => true,
+ 'isShow' => true,
+ 'bgColor' => "#ffffff",
+ 'rollBgColor' => "#ffffff",
+ 'style' => 'style-1',
+ 'styleName' => '风格1',
+ 'textColor' => "#333333",
+ 'rollTextColor' => "#333333",
+ 'textAlign' => 'center',
+ 'inputPlaceholder' => '请输入搜索关键词',
+ 'imgUrl' => '',
+ 'link' => [
+ 'name' => ""
+ ]
+ ],
+ 'popWindow' => [
+ 'imgUrl' => "",
+ 'imgWidth' => '',
+ 'imgHeight' => '',
+ 'count' => 'once',
+ 'show' => 0,
+ 'link' => [
+ 'name' => ""
+ ],
+ ]
+ ],
+ "value" => [
+ [
+ "path" => "edit-shop-search",
+ "uses" => 1,
+ "id" => "245qvzv4w8gw",
+ "componentName" => "ShopSearch",
+ "componentTitle" => "搜索",
+ "ignore" => [],
+ "searchStyle" => "style-1",
+ "searchLink" => [
+ "name" => ""
+ ],
+ "text" => "请输入搜索关键词",
+ "iconType" => "img",
+ "icon" => "",
+ "imageUrl" => "",
+ "textColor" => "#303133",
+ 'pageStartBgColor' => '',
+ 'pageEndBgColor' => '',
+ 'pageGradientAngle' => 'to bottom',
+ 'componentBgUrl' => '',
+ 'componentBgAlpha' => 2,
+ "componentStartBgColor" => "",
+ "componentEndBgColor" => "",
+ "componentGradientAngle" => "to bottom",
+ "topRounded" => 0,
+ "bottomRounded" => 0,
+ "elementBgColor" => "",
+ "topElementRounded" => 0,
+ "bottomElementRounded" => 0,
+ "margin" => [
+ "top" => 20,
+ "bottom" => 15,
+ "both" => 10
+ ]
+ ],
+ [
+ "path" => "edit-image-ads",
+ "uses" => 0,
+ "id" => "6jdfnu4e36g0",
+ "componentName" => "ImageAds",
+ "componentTitle" => "图片广告",
+ "ignore" => [],
+ "imageHeight" => 160,
+ "isSameScreen" => false,
+ "list" => [
+ [
+ "link" => [
+ "name" => ""
+ ],
+ "imageUrl" => "addon/shop/diy/index/banner.png",
+ "imgWidth" => 702,
+ "imgHeight" => 320,
+ "id" => "7ao3t56ug4o0",
+ "width" => 375,
+ "height" => 170.94
+ ]
+ ],
+ "textColor" => "#303133",
+ 'pageStartBgColor' => '',
+ 'pageEndBgColor' => '',
+ 'pageGradientAngle' => 'to bottom',
+ 'componentBgUrl' => '',
+ 'componentBgAlpha' => 2,
+ "componentStartBgColor" => "",
+ "componentEndBgColor" => "",
+ "componentGradientAngle" => "to bottom",
+ "topRounded" => 0,
+ "bottomRounded" => 0,
+ "elementBgColor" => "",
+ "topElementRounded" => 0,
+ "bottomElementRounded" => 0,
+ "margin" => [
+ "top" => 0,
+ "bottom" => 10,
+ "both" => 10
+ ]
+ ],
+ [
+ "path" => "edit-notice",
+ "uses" => 0,
+ "id" => "1xpv3z7vvtds",
+ "componentName" => "Notice",
+ "componentTitle" => "公告",
+ "ignore" => [],
+ "noticeType" => "img",
+ "imgType" => "system",
+ "systemUrl" => "style_1",
+ "imageUrl" => "",
+ "showType" => "popup",
+ "scrollWay" => "upDown",
+ "fontSize" => 14,
+ "fontWeight" => "normal",
+ "noticeTitle" => "公告",
+ "list" => [
+ [
+ "id" => "1rz6s4buaxc0",
+ "link" => [
+ "name" => ""
+ ],
+ "text" => "最新公告:欢迎来到小店参观!"
+ ]
+ ],
+ "textColor" => "#303133",
+ 'pageStartBgColor' => '',
+ 'pageEndBgColor' => '',
+ 'pageGradientAngle' => 'to bottom',
+ 'componentBgUrl' => '',
+ 'componentBgAlpha' => 2,
+ "componentStartBgColor" => "rgba(255, 255, 255, 1)",
+ "componentEndBgColor" => "",
+ "componentGradientAngle" => "to bottom",
+ "topRounded" => 9,
+ "bottomRounded" => 9,
+ "elementBgColor" => "",
+ "topElementRounded" => 0,
+ "bottomElementRounded" => 0,
+ "margin" => [
+ "top" => 0,
+ "bottom" => 10,
+ "both" => 10
+ ],
+ ],
+ [
+ "path" => "edit-graphic-nav",
+ "uses" => 0,
+ "id" => "5tnh9iiuxv40",
+ "componentName" => "GraphicNav",
+ "componentTitle" => "图文导航",
+ "ignore" => [],
+ "layout" => "horizontal",
+ "mode" => "graphic",
+ "showStyle" => "fixed",
+ "rowCount" => 5,
+ "pageCount" => 2,
+ "carousel" => [
+ "type" => "circle",
+ "color" => "#FFFFFF"
+ ],
+ "imageSize" => 26,
+ "aroundRadius" => 0,
+ "font" => [
+ "size" => 14,
+ "weight" => "normal",
+ "color" => "#303133"
+ ],
+ "list" => [
+ [
+ "title" => "首页",
+ "link" => [
+ "parent" => "SYSTEM_LINK",
+ "title" => "首页",
+ "url" => "/app/pages/index/index",
+ "name" => "INDEX"
+ ],
+ "imageUrl" => "addon/shop/diy/index/nav_notice.png",
+ "label" => [
+ "control" => false,
+ "text" => "热门",
+ "textColor" => "#FFFFFF",
+ "bgColorStart" => "#F83287",
+ "bgColorEnd" => "#FE3423"
+ ],
+ "id" => "5b46sybkhkg0",
+ "imgWidth" => 50,
+ "imgHeight" => 50
+ ],
+ [
+ "title" => "商品",
+ "link" => [
+ "parent" => "SHOP_LINK",
+ "title" => "商品列表",
+ "url" => "/addon/shop/pages/goods/list",
+ "name" => "SHOP_GOODS_LIST"
+ ],
+ "imageUrl" => "addon/shop/diy/index/nav_supermarket.png",
+ "label" => [
+ "control" => false,
+ "text" => "热门",
+ "textColor" => "#FFFFFF",
+ "bgColorStart" => "#F83287",
+ "bgColorEnd" => "#FE3423"
+ ],
+ "id" => "4dha169dzqe0",
+ "imgWidth" => 50,
+ "imgHeight" => 50
+ ],
+ [
+ "title" => "分类",
+ "link" => [
+ "parent" => "SHOP_LINK",
+ "title" => "商品分类",
+ "url" => "/addon/shop/pages/goods/category",
+ "name" => "SHOP_GOODS_CATEGORY"
+ ],
+ "imageUrl" => "addon/shop/diy/index/nav_article.png",
+ "label" => [
+ "control" => false,
+ "text" => "热门",
+ "textColor" => "#FFFFFF",
+ "bgColorStart" => "#F83287",
+ "bgColorEnd" => "#FE3423"
+ ],
+ "id" => "7eh2hqz0w900",
+ "imgWidth" => 50,
+ "imgHeight" => 50
+ ],
+ [
+ "id" => "7fu7atbr9bk0",
+ "title" => "领券",
+ "imageUrl" => "addon/shop/diy/index/nav_coupon.png",
+ "imgWidth" => 50,
+ "imgHeight" => 50,
+ "link" => [
+ "parent" => "SHOP_LINK",
+ "title" => "优惠券列表",
+ "url" => "/addon/shop/pages/coupon/list",
+ "name" => "SHOP_COUPON_LIST"
+ ],
+ "label" => [
+ "control" => false,
+ "text" => "热门",
+ "textColor" => "#FFFFFF",
+ "bgColorStart" => "#F83287",
+ "bgColorEnd" => "#FE3423"
+ ]
+ ],
+ [
+ "title" => "拼团",
+ "link" => [
+ "name" => ""
+ ],
+ "imageUrl" => "addon/shop/diy/index/nav_pintuan.png",
+ "label" => [
+ "control" => false,
+ "text" => "热门",
+ "textColor" => "#FFFFFF",
+ "bgColorStart" => "#F83287",
+ "bgColorEnd" => "#FE3423"
+ ],
+ "id" => "5q9ogqz2vjc0",
+ "imgWidth" => 50,
+ "imgHeight" => 50
+ ],
+ [
+ "id" => "2cc20cawafr4",
+ "title" => "秒杀",
+ "imageUrl" => "addon/shop/diy/index/nav_seckill.png",
+ "imgWidth" => 50,
+ "imgHeight" => 50,
+ "link" => [
+ "parent" => "SECKILL_LINK",
+ "title" => "秒杀首页",
+ "url" => "/addon/seckill/pages/index",
+ "name" => "SECKILL_INDEX"
+ ],
+ "label" => [
+ "control" => false,
+ "text" => "热门",
+ "textColor" => "#FFFFFF",
+ "bgColorStart" => "#F83287",
+ "bgColorEnd" => "#FE3423"
+ ]
+ ],
+ [
+ "id" => "532sx2po4do0",
+ "title" => "签到",
+ "imageUrl" => "addon/shop/diy/index/nav_signin.png",
+ "imgWidth" => 50,
+ "imgHeight" => 50,
+ "link" => [
+ "name" => "MEMBER_MY_SIGN_IN",
+ "parent" => "MEMBER_LINK",
+ "title" => "我的签到",
+ "url" => "/app/pages/member/sign_in",
+ "action" => ""
+ ],
+ "label" => [
+ "control" => false,
+ "text" => "热门",
+ "textColor" => "#FFFFFF",
+ "bgColorStart" => "#F83287",
+ "bgColorEnd" => "#FE3423"
+ ]
+ ],
+ [
+ "id" => "13itkrdjqteo",
+ "title" => "邀请好友",
+ "imageUrl" => "addon/shop/diy/index/nav_invite_friends.png",
+ "imgWidth" => 50,
+ "imgHeight" => 50,
+ "link" => [
+ "name" => ""
+ ],
+ "label" => [
+ "control" => false,
+ "text" => "热门",
+ "textColor" => "#FFFFFF",
+ "bgColorStart" => "#F83287",
+ "bgColorEnd" => "#FE3423"
+ ]
+ ],
+ [
+ "id" => "6sisp3zd0w80",
+ "title" => "公告",
+ "imageUrl" => "addon/shop/diy/index/nav_sys_message.png",
+ "imgWidth" => 50,
+ "imgHeight" => 50,
+ "link" => [
+ "name" => ""
+ ],
+ "label" => [
+ "control" => false,
+ "text" => "热门",
+ "textColor" => "#FFFFFF",
+ "bgColorStart" => "#F83287",
+ "bgColorEnd" => "#FE3423"
+ ]
+ ],
+ [
+ "id" => "6qoc0ssgvhc0",
+ "title" => "积分",
+ "imageUrl" => "addon/shop/diy/index/nav_point.png",
+ "imgWidth" => 50,
+ "imgHeight" => 50,
+ "link" => [
+ "name" => ""
+ ],
+ "label" => [
+ "control" => false,
+ "text" => "热门",
+ "textColor" => "#FFFFFF",
+ "bgColorStart" => "#F83287",
+ "bgColorEnd" => "#FE3423"
+ ]
+ ]
+ ],
+ // 轮播图设置
+ 'swiper' => [
+ 'indicatorColor' => 'rgba(0, 0, 0, 0.3)', // 未选中颜色
+ "indicatorActiveColor" => '#FF0E0E',
+ 'indicatorStyle' => 'style-1',
+ 'indicatorAlign' => 'center',
+ ],
+ "textColor" => "#303133",
+ 'pageStartBgColor' => '',
+ 'pageEndBgColor' => '',
+ 'pageGradientAngle' => 'to bottom',
+ 'componentBgUrl' => '',
+ 'componentBgAlpha' => 2,
+ "componentStartBgColor" => "rgba(255, 255, 255, 0.87)",
+ "componentEndBgColor" => "",
+ "componentGradientAngle" => "to bottom",
+ "topRounded" => 9,
+ "bottomRounded" => 9,
+ "elementBgColor" => "",
+ "topElementRounded" => 0,
+ "bottomElementRounded" => 0,
+ "margin" => [
+ "top" => 0,
+ "bottom" => 12,
+ "both" => 10
+ ]
+ ],
+ [
+ "path" => "edit-hot-area",
+ "uses" => 0,
+ "id" => "53fen2lf6l80",
+ "componentName" => "HotArea",
+ "componentTitle" => "热区",
+ "ignore" => [],
+ "imageUrl" => "addon/shop/diy/index/hot_area.png",
+ "imgWidth" => 698,
+ "imgHeight" => 466,
+ "heatMapData" => [],
+ "textColor" => "#303133",
+ 'pageStartBgColor' => '',
+ 'pageEndBgColor' => '',
+ 'pageGradientAngle' => 'to bottom',
+ 'componentBgUrl' => '',
+ 'componentBgAlpha' => 2,
+ "componentStartBgColor" => "",
+ "componentEndBgColor" => "",
+ "componentGradientAngle" => "to bottom",
+ "topRounded" => 0,
+ "bottomRounded" => 0,
+ "elementBgColor" => "",
+ "topElementRounded" => 0,
+ "bottomElementRounded" => 0,
+ "margin" => [
+ "top" => 0,
+ "bottom" => 12,
+ "both" => 10
+ ]
+ ],
+ [
+ "path" => "edit-text",
+ "uses" => 0,
+ "id" => "5lojzvbvg6o0",
+ "componentName" => "Text",
+ "componentTitle" => "标题",
+ "ignore" => [],
+ "style" => "style-1",
+ "styleName" => "风格1",
+ "text" => "商品推荐",
+ "link" => [
+ "name" => ""
+ ],
+ "textColor" => "#303133",
+ "fontSize" => 16,
+ "fontWeight" => "normal",
+ "textAlign" => "center",
+ "subTitle" => [
+ "text" => "副标题",
+ "color" => "#999999",
+ "fontSize" => 14,
+ "control" => false,
+ "fontWeight" => "normal"
+ ],
+ "more" => [
+ "text" => "查看更多",
+ "control" => false,
+ "isShow" => true,
+ "link" => [
+ "name" => ""
+ ],
+ "color" => "#999999"
+ ],
+ 'pageStartBgColor' => '',
+ 'pageEndBgColor' => '',
+ 'pageGradientAngle' => 'to bottom',
+ 'componentBgUrl' => '',
+ 'componentBgAlpha' => 2,
+ "componentStartBgColor" => "",
+ "componentEndBgColor" => "",
+ "componentGradientAngle" => "to bottom",
+ "topRounded" => 0,
+ "bottomRounded" => 0,
+ "elementBgColor" => "",
+ "topElementRounded" => 0,
+ "bottomElementRounded" => 0,
+ "margin" => [
+ "top" => 0,
+ "bottom" => 12,
+ "both" => 0
+ ]
+ ],
+ [
+ "path" => "edit-goods-list",
+ "uses" => 0,
+ "id" => "50pj7dmvbvo0",
+ "componentName" => "GoodsList",
+ "componentTitle" => "商品列表",
+ "ignore" => [],
+ 'style' => 'style-1',
+ "source" => "all",
+ "num" => 10,
+ "goods_category" => "",
+ "goods_category_name" => "请选择",
+ "goods_ids" => [],
+ "sortWay" => "default", // 排序方式,default:综合,sale_num:销量,price:价格
+ "goodsNameStyle" => [
+ "color" => "#303133",
+ "control" => true,
+ "fontWeight" => 'bold',
+ "isShow" => true
+ ],
+ "priceStyle" => [
+ "color" => "#FF4142",
+ "control" => true,
+ "isShow" => true
+ ],
+ "saleStyle" => [
+ "color" => "#999999",
+ "control" => true,
+ "isShow" => true
+ ],
+ "labelStyle" => [
+ "control" => true,
+ "isShow" => true
+ ],
+ "btnStyle" => [
+ "fontWeight" => false,
+ "padding" => 0,
+ "aroundRadius" => 25,
+ "cartEvent" => "detail",
+ "text" => "购买",
+ "textColor" => "#FFFFFF",
+ "startBgColor" => "#FF4142",
+ "endBgColor" => "#FF4142",
+ "style" => "button",
+ "control" => true
+ ],
+ "imgElementRounded" => 0,// 图片圆角
+ "textColor" => "#303133",
+ 'pageStartBgColor' => '',
+ 'pageEndBgColor' => '',
+ 'pageGradientAngle' => 'to bottom',
+ 'componentBgUrl' => '',
+ 'componentBgAlpha' => 2,
+ "componentStartBgColor" => "",
+ "componentEndBgColor" => "",
+ "componentGradientAngle" => "to bottom",
+ "topRounded" => 0,
+ "bottomRounded" => 0,
+ "elementBgColor" => "",
+ "topElementRounded" => 0,
+ "bottomElementRounded" => 0,
+ "margin" => [
+ "top" => 0,
+ "bottom" => 0,
+ "both" => 10
+ ]
+ ]
+ ]
+ ]
+ ],
+ ],
+ 'DIY_SHOP_MEMBER_INDEX' => [
+ 'shop_member_index_style1' => [
+ "title" => "商城个人中心1", // 页面名称
+ 'cover' => 'addon/shop/diy/template/member_index_cover.png', // 页面封面图
+ 'preview' => '', // 页面预览图
+ 'desc' => '个人中心', // 页面描述
+ 'mode' => 'diy', // 页面模式:diy:自定义,fixed:固定
+ 'data' => [
+ "global" => [
+ "title" => "个人中心",
+ "bgUrl" => "",
+ "imgWidth" => "",
+ "imgHeight" => "",
+ "bottomTabBar" => [
+ 'control' => true,
+ 'isShow' => true,
+ 'designNav' => [
+ 'title' => '',
+ 'key' => ''
+ ]
+ ],
+ "copyright" => [
+ 'control' => true,
+ 'isShow' => false,
+ 'textColor' =>'#ccc'
+ ],
+ "template" => [
+ "textColor" => "#303133",
+ "componentStartBgColor" => "",
+ "componentEndBgColor" => "",
+ "topRounded" => 0,
+ "bottomRounded" => 0,
+ "elementBgColor" => "",
+ "topElementRounded" => 0,
+ "bottomElementRounded" => 0,
+ "margin" => [
+ "top" => 0,
+ "bottom" => 0,
+ "both" => 0
+ ],
+ "pageStartBgColor" => "",
+ "pageEndBgColor" => "",
+ "pageGradientAngle" => "to bottom",
+ "componentBgUrl" => "",
+ "componentBgAlpha" => 2,
+ "componentGradientAngle" => "to bottom"
+ ],
+ "topStatusBar" => [
+ 'control' => true,
+ 'isShow' => true,
+ 'bgColor' => "#ffffff",
+ 'rollBgColor' => "#ffffff",
+ 'style' => 'style-1',
+ 'styleName' => '风格1',
+ 'textColor' => "#333333",
+ 'rollTextColor' => "#333333",
+ 'textAlign' => 'center',
+ 'inputPlaceholder' => '请输入搜索关键词',
+ 'imgUrl' => '',
+ 'link' => [
+ 'name' => ""
+ ]
+ ],
+ "popWindow" => [
+ "imgUrl" => "",
+ "imgWidth" => "",
+ "imgHeight" => "",
+ "count" => 'once',
+ "show" => 0,
+ "link" => [
+ "name" => ""
+ ]
+ ],
+ "pageStartBgColor" => "rgba(246, 246, 246, 1)",
+ "pageEndBgColor" => "",
+ "pageGradientAngle" => "to bottom",
+ "bgHeightScale" => 0
+ ],
+ "value" => [
+ [
+ "path" => "edit-shop-member-info",
+ "id" => "3pt9pn9bvn20",
+ "componentName" => "ShopMemberInfo",
+ "componentTitle" => "会员信息",
+ "uses" => 1,
+ "ignore" => [
+ "componentBgUrl"
+ ],
+ "componentStartBgColor" => "rgba(255, 255, 255, 1)",
+ "componentEndBgColor" => "rgba(246, 246, 246, 0.1)",
+ "topRounded" => 0,
+ "bottomRounded" => 0,
+ "elementBgColor" => "",
+ "topElementRounded" => 0,
+ "bottomElementRounded" => 0,
+ "margin" => [
+ "top" => 0,
+ "bottom" => 0,
+ "both" => 0
+ ],
+ "textColor" => "#333333",
+ "uidTextColor" => "#666666",
+ 'accountTextColor' => '#666666',
+ "pageStartBgColor" => "",
+ "pageEndBgColor" => "",
+ "pageGradientAngle" => "to bottom",
+ "componentBgUrl" => "",
+ "componentBgAlpha" => 2,
+ "componentGradientAngle" => "to bottom",
+ "style" => "style-1",
+ "styleName" => "风格1",
+ "bgUrl" => "",
+ "isShowAccount" => true
+ ],
+ [
+ "path" => "edit-member-level",
+ "uses" => 1,
+ "id" => "533e6ynytmo0",
+ "componentName" => "MemberLevel",
+ "componentTitle" => "会员等级",
+ "ignore" => [
+ "componentBgColor",
+ "componentBgUrl"
+ ],
+ "style" => "style-5",
+ "styleName" => "风格5",
+ "textColor" => "#303133",
+ "componentStartBgColor" => "",
+ "componentEndBgColor" => "",
+ "topRounded" => 12,
+ "bottomRounded" => 12,
+ "elementBgColor" => "",
+ "topElementRounded" => 0,
+ "bottomElementRounded" => 0,
+ "margin" => [
+ "top" => -45,
+ "bottom" => 0,
+ "both" => 10
+ ],
+ "pageStartBgColor" => "",
+ "pageEndBgColor" => "",
+ "pageGradientAngle" => "to bottom",
+ "componentBgUrl" => "",
+ "componentBgAlpha" => 2,
+ "componentGradientAngle" => "to bottom"
+ ],
+ [
+ "path" => "edit-shop-order-info",
+ "uses" => 1,
+ "id" => "2jmnqqhc8ri0",
+ "componentName" => "ShopOrderInfo",
+ "componentTitle" => "订单中心",
+ "ignore" => [],
+ "textColor" => "#303133",
+ "fontSize" => 15,
+ "fontWeight" => "normal",
+ "text" => "订单中心",
+ "more" => [
+ "text" => "全部订单",
+ "color" => "#999999",
+ ],
+ "item" => [
+ "fontSize" => 12,
+ "fontWeight" => "normal",
+ "color" => "#303133"
+ ],
+ "componentStartBgColor" => "rgba(255, 255, 255, 1)",
+ "componentEndBgColor" => "",
+ "topRounded" => 12,
+ "bottomRounded" => 12,
+ "elementBgColor" => "",
+ "topElementRounded" => 0,
+ "bottomElementRounded" => 0,
+ "margin" => [
+ "top" => 10,
+ "bottom" => 0,
+ "both" => 10
+ ],
+ "pageStartBgColor" => "",
+ "pageEndBgColor" => "",
+ "pageGradientAngle" => "to bottom",
+ "componentBgUrl" => "",
+ "componentBgAlpha" => 2,
+ "componentGradientAngle" => "to bottom"
+ ],
+ [
+ "path" => "edit-horz-blank",
+ "uses" => 0,
+ "id" => "6cil3ipiis40",
+ "componentName" => "HorzBlank",
+ "componentTitle" => "辅助空白",
+ "ignore" => ['pageBgColor', 'componentBgUrl'],
+ "height" => 10,
+ "textColor" => "#303133",
+ "componentStartBgColor" => "rgba(255, 255, 255, 1)",
+ "componentEndBgColor" => "",
+ "topRounded" => 12,
+ "bottomRounded" => 0,
+ "elementBgColor" => "",
+ "topElementRounded" => 0,
+ "bottomElementRounded" => 0,
+ "margin" => [
+ "top" => 10,
+ "bottom" => 0,
+ "both" => 10
+ ],
+ "pageStartBgColor" => "",
+ "pageEndBgColor" => "",
+ "pageGradientAngle" => "to bottom",
+ "componentBgUrl" => "",
+ "componentBgAlpha" => 2,
+ "componentGradientAngle" => "to bottom"
+ ],
+ [
+ "path" => "edit-text",
+ "uses" => 0,
+ "id" => "68gnubbygqg0",
+ "componentName" => "Text",
+ "componentTitle" => "标题",
+ "ignore" => [],
+ "textColor" => "#303133",
+ "componentStartBgColor" => "rgba(255, 255, 255, 1)",
+ "componentEndBgColor" => "",
+ "topRounded" => 0,
+ "bottomRounded" => 0,
+ "elementBgColor" => "",
+ "topElementRounded" => 0,
+ "bottomElementRounded" => 0,
+ "margin" => [
+ "top" => 0,
+ "bottom" => 0,
+ "both" => 10
+ ],
+ "fontSize" => 15,
+ "fontWeight" => "normal",
+ "pageStartBgColor" => "",
+ "pageEndBgColor" => "",
+ "pageGradientAngle" => "to bottom",
+ "componentBgUrl" => "",
+ "componentBgAlpha" => 2,
+ "componentGradientAngle" => "to bottom",
+ "position" => "",
+ "style" => "style-1",
+ "styleName" => "风格1",
+ "text" => "其他功能",
+ "link" => [
+ "name" => ""
+ ],
+ "textAlign" => "left",
+ "subTitle" => [
+ "text" => "副标题",
+ "color" => "#999999",
+ "fontSize" => 14,
+ "control" => false,
+ "fontWeight" => "normal"
+ ],
+ "more" => [
+ "text" => "查看更多",
+ "control" => false,
+ "isShow" => true,
+ "link" => [
+ "name" => ""
+ ],
+ "color" => "#999999"
+ ]
+ ],
+ [
+ "path" => "edit-horz-blank",
+ "uses" => 0,
+ "id" => "5jx57rrjl940",
+ "componentName" => "HorzBlank",
+ "componentTitle" => "辅助空白",
+ "ignore" => ['pageBgColor', 'componentBgUrl'],
+ "height" => 8,
+ "textColor" => "#303133",
+ "componentStartBgColor" => "rgba(255, 255, 255, 1)",
+ "componentEndBgColor" => "",
+ "topRounded" => 0,
+ "bottomRounded" => 0,
+ "elementBgColor" => "",
+ "topElementRounded" => 0,
+ "bottomElementRounded" => 0,
+ "margin" => [
+ "top" => 0,
+ "bottom" => 0,
+ "both" => 10
+ ],
+ "pageStartBgColor" => "",
+ "pageEndBgColor" => "",
+ "pageGradientAngle" => "to bottom",
+ "componentBgUrl" => "",
+ "componentBgAlpha" => 2,
+ "componentGradientAngle" => "to bottom"
+ ],
+ [
+ "path" => "edit-graphic-nav",
+ "uses" => 0,
+ "id" => "5myxk1opz0c0",
+ "componentName" => "GraphicNav",
+ "componentTitle" => "图文导航",
+ "ignore" => [],
+ "textColor" => "#303133",
+ "componentStartBgColor" => "rgba(255, 255, 255, 1)",
+ "componentEndBgColor" => "",
+ "topRounded" => 0,
+ "bottomRounded" => 12,
+ "elementBgColor" => "",
+ "topElementRounded" => 0,
+ "bottomElementRounded" => 0,
+ "margin" => [
+ "top" => 0,
+ "bottom" => 10,
+ "both" => 10
+ ],
+ "pageStartBgColor" => "",
+ "pageEndBgColor" => "",
+ "pageGradientAngle" => "to bottom",
+ "componentBgUrl" => "",
+ "componentBgAlpha" => 2,
+ "componentGradientAngle" => "to bottom",
+ "layout" => "horizontal",
+ "mode" => "graphic",
+ "showStyle" => "fixed",
+ "rowCount" => 4,
+ "pageCount" => 2,
+ "carousel" => [
+ "type" => "circle",
+ "color" => "#FFFFFF"
+ ],
+ "imageSize" => 20,
+ "aroundRadius" => 0,
+ "font" => [
+ "size" => 12,
+ "weight" => "normal",
+ "color" => "#303133"
+ ],
+ "list" => $member_index_graphic_nav_list,
+ // 轮播图设置
+ 'swiper' => [
+ 'indicatorColor' => 'rgba(0, 0, 0, 0.3)', // 未选中颜色
+ "indicatorActiveColor" => '#FF0E0E',
+ 'indicatorStyle' => 'style-1',
+ 'indicatorAlign' => 'center',
+ ]
+ ]
+ ]
+ ]
+ ],
+ 'shop_member_index' => [
+ "title" => "商城个人中心2", // 页面名称
+ 'cover' => 'addon/shop/diy/template/member_index_cover.png', // 页面封面图
+ 'preview' => '', // 页面预览图
+ 'desc' => '个人中心', // 页面描述
+ 'mode' => 'diy', // 页面模式:diy:自定义,fixed:固定
+ 'data' => [
+ "global" => [
+ "title" => "个人中心",
+ 'pageStartBgColor' => 'rgba(246, 247, 252, 1)',
+ 'pageEndBgColor' => '',
+ 'pageGradientAngle' => 'to bottom',
+ "bgUrl" => "",
+ 'bgHeightScale' => 0,
+ "imgWidth" => "",
+ "imgHeight" => "",
+ "bottomTabBar" => [
+ 'control' => true,
+ 'isShow' => true,
+ 'designNav' => [
+ 'title' => '',
+ 'key' => ''
+ ]
+ ],
+ "copyright" => [
+ 'control' => true,
+ 'isShow' => false,
+ 'textColor' =>'#ccc'
+ ],
+ "template" => [
+ "textColor" => "#303133",
+ 'pageStartBgColor' => '',
+ 'pageEndBgColor' => '',
+ 'pageGradientAngle' => 'to bottom',
+ 'componentBgUrl' => '',
+ 'componentBgAlpha' => 2,
+ "componentStartBgColor" => "",
+ "componentEndBgColor" => "",
+ "componentGradientAngle" => "to bottom",
+ "topRounded" => 0,
+ "bottomRounded" => 0,
+ "elementBgColor" => "",
+ "topElementRounded" => 0,
+ "bottomElementRounded" => 0,
+ "margin" => [
+ "top" => 0,
+ "bottom" => 0,
+ "both" => 10
+ ]
+ ],
+ "topStatusBar" => [
+ 'control' => true,
+ 'isShow' => true,
+ 'bgColor' => "#ffffff",
+ 'rollBgColor' => "#ffffff",
+ 'style' => 'style-1',
+ 'styleName' => '风格1',
+ 'textColor' => "#333333",
+ 'rollTextColor' => "#333333",
+ 'textAlign' => 'center',
+ 'inputPlaceholder' => '请输入搜索关键词',
+ 'imgUrl' => '',
+ 'link' => [
+ 'name' => ""
+ ]
+ ],
+ "popWindow" => [
+ "imgUrl" => "",
+ "imgWidth" => "",
+ "imgHeight" => "",
+ "count" => 'once',
+ "show" => 0,
+ "link" => [
+ "name" => ""
+ ]
+ ]
+ ],
+ "value" => [
+ [
+ "path" => "edit-member-info",
+ "id" => "40w5ay4dep00",
+ "componentName" => "MemberInfo",
+ "componentTitle" => "会员信息",
+ "uses" => 1,
+ "ignore" => [],
+ 'pageStartBgColor' => '',
+ 'pageEndBgColor' => '',
+ 'pageGradientAngle' => 'to bottom',
+ 'componentBgUrl' => '',
+ 'componentBgAlpha' => 2,
+ "componentStartBgColor" => "",
+ "componentEndBgColor" => "",
+ "componentGradientAngle" => "to bottom",
+ "topRounded" => 0,
+ "bottomRounded" => 0,
+ "elementBgColor" => "",
+ "topElementRounded" => 0,
+ "bottomElementRounded" => 0,
+ "margin" => [
+ "top" => 0,
+ "bottom" => 0,
+ "both" => 0
+ ],
+ "textColor" => "#303133",
+ "style" => "style-1",
+ "styleName" => "风格1",
+ "bgUrl" => "",
+ "bgColorStart" => "",
+ "bgColorEnd" => "",
+ "isShowAccount" => true
+ ],
+ [
+ "path" => "edit-horz-blank",
+ "uses" => 0,
+ "id" => "2da0xqyo8zms",
+ "componentName" => "HorzBlank",
+ "componentTitle" => "辅助空白",
+ "ignore" => [
+ "pageBgColor",
+ "componentBgUrl"
+ ],
+ "height" => 10,
+ "textColor" => "#303133",
+ "pageStartBgColor" => "",
+ "pageEndBgColor" => "",
+ "pageGradientAngle" => "to bottom",
+ "componentBgUrl" => "",
+ "componentBgAlpha" => 2,
+ "componentStartBgColor" => "rgba(255, 255, 255, 1)",
+ "componentEndBgColor" => "",
+ "componentGradientAngle" => "to bottom",
+ "topRounded" => 9,
+ "bottomRounded" => 0,
+ "elementBgColor" => "",
+ "topElementRounded" => 0,
+ "bottomElementRounded" => 0,
+ "margin" => [
+ "top" => 0,
+ "bottom" => 0,
+ "both" => 10
+ ]
+ ],
+ [
+ "path" => "edit-text",
+ "uses" => 0,
+ "position" => "",
+ "id" => "1puhgfus8www",
+ "componentName" => "Text",
+ "componentTitle" => "标题",
+ "ignore" => [],
+ "style" => "style-2",
+ "styleName" => "风格2",
+ "text" => "我的订单",
+ "link" => [
+ "name" => "SHOP_ORDER_LIST",
+ "parent" => "SHOP_LINK",
+ "title" => "订单列表",
+ "url" => "/addon/shop/pages/order/list",
+ "action" => ""
+ ],
+ "textColor" => "#303133",
+ "fontSize" => 16,
+ "fontWeight" => "normal",
+ "textAlign" => "center",
+ "subTitle" => [
+ "text" => "",
+ "color" => "#999999",
+ "fontSize" => 14,
+ "control" => true,
+ "fontWeight" => "normal"
+ ],
+ "more" => [
+ "text" => "全部",
+ "control" => true,
+ "isShow" => true,
+ "link" => [
+ "name" => ""
+ ],
+ "color" => "#999999"
+ ],
+ 'pageStartBgColor' => '',
+ 'pageEndBgColor' => '',
+ 'pageGradientAngle' => 'to bottom',
+ 'componentBgUrl' => '',
+ 'componentBgAlpha' => 2,
+ "componentStartBgColor" => "rgba(255, 255, 255, 1)",
+ "componentEndBgColor" => "",
+ "componentGradientAngle" => "to bottom",
+ "topRounded" => 0,
+ "bottomRounded" => 0,
+ "elementBgColor" => "",
+ "topElementRounded" => 0,
+ "bottomElementRounded" => 0,
+ "margin" => [
+ "top" => 0,
+ "bottom" => 0,
+ "both" => 10
+ ]
+ ],
+ [
+ "path" => "edit-graphic-nav",
+ "uses" => 0,
+ "id" => "42bjn10l0ak0",
+ "componentName" => "GraphicNav",
+ "componentTitle" => "图文导航",
+ "ignore" => [],
+ "list" => [
+ [
+ "link" => [
+ "parent" => "DIY_LINK",
+ "title" => "待付款",
+ "url" => "/addon/shop/pages/order/list?status=1",
+ "name" => "DIY_LINK"
+ ],
+ "imageUrl" => "addon/shop/diy/member/nav_wait_pay_order.png",
+ "imgWidth" => 40,
+ "imgHeight" => 40,
+ "id" => "ogkw2mqwvow",
+ "title" => "待付款",
+ "label" => [
+ "control" => false,
+ "text" => "热门",
+ "textColor" => "#FFFFFF",
+ "bgColorStart" => "#F83287",
+ "bgColorEnd" => "#FE3423"
+ ]
+ ],
+ [
+ "title" => "待发货",
+ "link" => [
+ "parent" => "DIY_LINK",
+ "title" => "待发货",
+ "url" => "/addon/shop/pages/order/list?status=2",
+ "name" => "DIY_LINK"
+ ],
+ "imageUrl" => "addon/shop/diy/member/nav_wait_delivery_order.png",
+ "label" => [
+ "control" => false,
+ "text" => "热门",
+ "textColor" => "#FFFFFF",
+ "bgColorStart" => "#F83287",
+ "bgColorEnd" => "#FE3423"
+ ],
+ "id" => "37hnqfvx5va0",
+ "imgWidth" => 40,
+ "imgHeight" => 40
+ ],
+ [
+ "title" => "待收货",
+ "link" => [
+ "parent" => "DIY_LINK",
+ "title" => "待收货",
+ "url" => "/addon/shop/pages/order/list?status=3",
+ "name" => "DIY_LINK"
+ ],
+ "imageUrl" => "addon/shop/diy/member/nav_wait_take_order.png",
+ "label" => [
+ "control" => false,
+ "text" => "热门",
+ "textColor" => "#FFFFFF",
+ "bgColorStart" => "#F83287",
+ "bgColorEnd" => "#FE3423"
+ ],
+ "id" => "63n62guoiug0",
+ "imgWidth" => 40,
+ "imgHeight" => 40
+ ],
+ [
+ "title" => "待评价",
+ "link" => [
+ "parent" => "DIY_LINK",
+ "title" => "待评价",
+ "url" => "/addon/shop/pages/order/list?status=5",
+ "name" => "DIY_LINK"
+ ],
+ "imageUrl" => "addon/shop/diy/member/nav_wait_evaluate_order.png",
+ "label" => [
+ "control" => false,
+ "text" => "热门",
+ "textColor" => "#FFFFFF",
+ "bgColorStart" => "#F83287",
+ "bgColorEnd" => "#FE3423"
+ ],
+ "id" => "4wblhzd14uw0",
+ "imgWidth" => 40,
+ "imgHeight" => 40
+ ],
+ [
+ "id" => "fl2bqfimnuo",
+ "title" => "售后退款",
+ "imageUrl" => "addon/shop/diy/member/nav_refund_order.png",
+ "imgWidth" => 40,
+ "imgHeight" => 40,
+ "link" => [
+ "parent" => "SHOP_LINK",
+ "title" => "退款列表",
+ "url" => "/addon/shop/pages/refund/list",
+ "name" => "SHOP_REFUND_LIST"
+ ],
+ "label" => [
+ "control" => false,
+ "text" => "热门",
+ "textColor" => "#FFFFFF",
+ "bgColorStart" => "#F83287",
+ "bgColorEnd" => "#FE3423"
+ ]
+ ]
+ ],
+ // 轮播图设置
+ 'swiper' => [
+ 'indicatorColor' => 'rgba(0, 0, 0, 0.3)', // 未选中颜色
+ "indicatorActiveColor" => '#FF0E0E',
+ 'indicatorStyle' => 'style-1',
+ 'indicatorAlign' => 'center',
+ ],
+ "textColor" => "#303133",
+ 'pageStartBgColor' => '',
+ 'pageEndBgColor' => '',
+ 'pageGradientAngle' => 'to bottom',
+ 'componentBgUrl' => '',
+ 'componentBgAlpha' => 2,
+ "componentStartBgColor" => "rgba(255, 255, 255, 1)",
+ "componentEndBgColor" => "",
+ "componentGradientAngle" => "to bottom",
+ "topRounded" => 0,
+ "bottomRounded" => 9,
+ "elementBgColor" => "",
+ "topElementRounded" => 0,
+ "bottomElementRounded" => 0,
+ "margin" => [
+ "top" => 0,
+ "bottom" => 12,
+ "both" => 10
+ ],
+ "layout" => "horizontal",
+ "mode" => "graphic",
+ "showStyle" => "fixed",
+ "rowCount" => 5,
+ "pageCount" => 2,
+ "carousel" => [
+ "type" => "circle",
+ "color" => "#FFFFFF"
+ ],
+ "imageSize" => 20,
+ "aroundRadius" => 0,
+ "font" => [
+ "size" => 14,
+ "weight" => "normal",
+ "color" => "rgba(32, 15, 51, 1)"
+ ]
+ ],
+ [
+ "path" => "edit-horz-blank",
+ "uses" => 0,
+ "id" => "5fo173bx5840",
+ "componentName" => "HorzBlank",
+ "componentTitle" => "辅助空白",
+ "ignore" => [
+ "pageBgColor",
+ "componentBgUrl"
+ ],
+ "height" => 10,
+ "textColor" => "#303133",
+ "pageStartBgColor" => "",
+ "pageEndBgColor" => "",
+ "pageGradientAngle" => "to bottom",
+ "componentBgUrl" => "",
+ "componentBgAlpha" => 2,
+ "componentStartBgColor" => "rgba(255, 255, 255, 1)",
+ "componentEndBgColor" => "",
+ "componentGradientAngle" => "to bottom",
+ "topRounded" => 9,
+ "bottomRounded" => 0,
+ "elementBgColor" => "",
+ "topElementRounded" => 0,
+ "bottomElementRounded" => 0,
+ "margin" => [
+ "top" => 0,
+ "bottom" => 0,
+ "both" => 10
+ ]
+ ],
+ [
+ "path" => "edit-text",
+ "uses" => 0,
+ "position" => "",
+ "id" => "629cgb1ygcw0",
+ "componentName" => "Text",
+ "componentTitle" => "标题",
+ "ignore" => [],
+ "style" => "style-1",
+ "styleName" => "风格1",
+ "text" => "常用工具",
+ "link" => [
+ "name" => ""
+ ],
+ "textColor" => "#303133",
+ "fontSize" => 16,
+ "fontWeight" => "normal",
+ "textAlign" => "left",
+ "subTitle" => [
+ "text" => "",
+ "color" => "#999999",
+ "fontSize" => 14,
+ "control" => false,
+ "fontWeight" => "normal"
+ ],
+ "more" => [
+ "text" => "查看更多",
+ "control" => false,
+ "isShow" => false,
+ "link" => [
+ "name" => ""
+ ],
+ "color" => "#999999"
+ ],
+ 'pageStartBgColor' => '',
+ 'pageEndBgColor' => '',
+ 'pageGradientAngle' => 'to bottom',
+ 'componentBgUrl' => '',
+ 'componentBgAlpha' => 2,
+ "componentStartBgColor" => "rgba(255, 255, 255, 1)",
+ "componentEndBgColor" => "",
+ "componentGradientAngle" => "to bottom",
+ "topRounded" => 0,
+ "bottomRounded" => 0,
+ "elementBgColor" => "",
+ "topElementRounded" => 0,
+ "bottomElementRounded" => 0,
+ "margin" => [
+ "top" => 0,
+ "bottom" => 0,
+ "both" => 10
+ ]
+ ],
+ [
+ "path" => "edit-graphic-nav",
+ "uses" => 0,
+ "id" => "1swylyl5fvb4",
+ "componentName" => "GraphicNav",
+ "componentTitle" => "图文导航",
+ "ignore" => [],
+ "list" => [
+ [
+ "title" => "签到",
+ "link" => [
+ "name" => "MEMBER_MY_SIGN_IN",
+ "parent" => "MEMBER_LINK",
+ "title" => "我的签到",
+ "url" => "/app/pages/member/sign_in",
+ "action" => ""
+ ],
+ "imageUrl" => "addon/shop/diy/member/nav_signin.png",
+ "label" => [
+ "control" => false,
+ "text" => "热门",
+ "textColor" => "#FFFFFF",
+ "bgColorStart" => "#F83287",
+ "bgColorEnd" => "#FE3423"
+ ],
+ "imgWidth" => 58,
+ "imgHeight" => 58
+ ],
+ [
+ "title" => "个人资料",
+ "link" => [
+ "parent" => "MEMBER_LINK",
+ "title" => "个人资料",
+ "url" => "/app/pages/member/personal",
+ "name" => "MEMBER_PERSONAL"
+ ],
+ "imageUrl" => "addon/shop/diy/member/nav_info.png",
+ "label" => [
+ "control" => false,
+ "text" => "热门",
+ "textColor" => "#FFFFFF",
+ "bgColorStart" => "#F83287",
+ "bgColorEnd" => "#FE3423"
+ ],
+ "imgWidth" => 58,
+ "imgHeight" => 58
+ ],
+ [
+ "title" => "收货地址",
+ "link" => [
+ "parent" => "MEMBER_LINK",
+ "title" => "收货地址",
+ "url" => "/app/pages/member/address",
+ "name" => "MEMBER_ADDRESS"
+ ],
+ "imageUrl" => "addon/shop/diy/member/nav_address.png",
+ "label" => [
+ "control" => false,
+ "text" => "热门",
+ "textColor" => "#FFFFFF",
+ "bgColorStart" => "#F83287",
+ "bgColorEnd" => "#FE3423"
+ ],
+ "imgWidth" => 58,
+ "imgHeight" => 58
+ ],
+ [
+ "title" => "优惠券",
+ "link" => [
+ "parent" => "SHOP_LINK",
+ "title" => "我的优惠券",
+ "url" => "/addon/shop/pages/member/my_coupon",
+ "name" => "SHOP_MY_COUPON"
+ ],
+ "imageUrl" => "addon/shop/diy/member/nav_coupon.png",
+ "label" => [
+ "control" => false,
+ "text" => "热门",
+ "textColor" => "#FFFFFF",
+ "bgColorStart" => "#F83287",
+ "bgColorEnd" => "#FE3423"
+ ],
+ "imgWidth" => 58,
+ "imgHeight" => 58
+ ],
+ [
+ "id" => "su0vf82y200",
+ "title" => "我的拼单",
+ "imageUrl" => "addon/shop/diy/member/nav_my_pintuan.png",
+ "imgWidth" => 58,
+ "imgHeight" => 58,
+ "link" => [
+ "name" => ""
+ ],
+ "label" => [
+ "control" => false,
+ "text" => "热门",
+ "textColor" => "#FFFFFF",
+ "bgColorStart" => "#F83287",
+ "bgColorEnd" => "#FE3423"
+ ]
+ ],
+ [
+ "id" => "6ba0yct2b3ct",
+ "title" => "我的助力",
+ "imageUrl" => "addon/shop/diy/member/nav_my_help.png",
+ "imgWidth" => 58,
+ "imgHeight" => 58,
+ "link" => [
+ "name" => ""
+ ],
+ "label" => [
+ "control" => false,
+ "text" => "热门",
+ "textColor" => "#FFFFFF",
+ "bgColorStart" => "#F83287",
+ "bgColorEnd" => "#FE3423"
+ ]
+ ],
+ [
+ "id" => "2b0att2b3pq8",
+ "title" => "我的礼物",
+ "imageUrl" => "addon/shop/diy/member/nav_gift.png",
+ "imgWidth" => 58,
+ "imgHeight" => 58,
+ "link" => [
+ "name" => ""
+ ],
+ "label" => [
+ "control" => false,
+ "text" => "热门",
+ "textColor" => "#FFFFFF",
+ "bgColorStart" => "#F83287",
+ "bgColorEnd" => "#FE3423"
+ ]
+ ],
+ [
+ "id" => "z8x7ci5wik0",
+ "title" => "我的足迹",
+ "imageUrl" => "addon/shop/diy/member/nav_footmark.png",
+ "imgWidth" => 58,
+ "imgHeight" => 58,
+ "link" => [
+ "name" => "SHOP_MY_GOODS_BROWSE",
+ "parent" => "SHOP_LINK",
+ "title" => "我的足迹",
+ "url" => "/addon/shop/pages/goods/browse",
+ ],
+ "label" => [
+ "control" => false,
+ "text" => "热门",
+ "textColor" => "#FFFFFF",
+ "bgColorStart" => "#F83287",
+ "bgColorEnd" => "#FE3423"
+ ]
+ ],
+ [
+ "id" => "1sejr0g3h4zk",
+ "title" => "积分兑换",
+ "imageUrl" => "addon/shop/diy/member/nav_point_change.png",
+ "imgWidth" => 58,
+ "imgHeight" => 58,
+ "link" => [
+ "name" => ""
+ ],
+ "label" => [
+ "control" => false,
+ "text" => "热门",
+ "textColor" => "#FFFFFF",
+ "bgColorStart" => "#F83287",
+ "bgColorEnd" => "#FE3423"
+ ]
+ ]
+ ],
+ // 轮播图设置
+ 'swiper' => [
+ 'indicatorColor' => 'rgba(0, 0, 0, 0.3)', // 未选中颜色
+ "indicatorActiveColor" => '#FF0E0E',
+ 'indicatorStyle' => 'style-1',
+ 'indicatorAlign' => 'center',
+ ],
+ "textColor" => "#303133",
+ 'pageStartBgColor' => '',
+ 'pageEndBgColor' => '',
+ 'pageGradientAngle' => 'to bottom',
+ 'componentBgUrl' => '',
+ 'componentBgAlpha' => 2,
+ "componentStartBgColor" => "rgba(255, 255, 255, 1)",
+ "componentEndBgColor" => "",
+ "componentGradientAngle" => "to bottom",
+ "topRounded" => 0,
+ "bottomRounded" => 9,
+ "elementBgColor" => "",
+ "topElementRounded" => 0,
+ "bottomElementRounded" => 0,
+ "margin" => [
+ "top" => 0,
+ "bottom" => 0,
+ "both" => 10
+ ],
+ "layout" => "horizontal",
+ "mode" => "graphic",
+ "showStyle" => "fixed",
+ "rowCount" => 4,
+ "pageCount" => 2,
+ "carousel" => [
+ "type" => "circle",
+ "color" => "#FFFFFF"
+ ],
+ "imageSize" => 29,
+ "aroundRadius" => 0,
+ "font" => [
+ "size" => 14,
+ "weight" => "normal",
+ "color" => "#303133"
+ ]
+ ]
+ ]
+ ]
+ ]
+ ],
+ 'DIY_SHOP_POINT_INDEX' => [
+ 'shop_point_index_style1' => [
+ "title" => "积分商城",
+ 'cover' => 'addon/shop/diy/template/shop_point_index_style1_cover.jpg', // 页面封面图
+ 'preview' => '', // 页面预览图
+ 'desc' => '', // 页面描述
+ 'mode' => 'diy', // 页面模式:diy:自定义,fixed:固定
+ // 页面数据源
+ 'data' => [
+ "global" => [
+ "bgUrl" => "",
+ "imgWidth" => "",
+ "imgHeight" => "",
+ "title" => "积分商城",
+ "pageStartBgColor" => "#F6F6F6",
+ "pageEndBgColor" => "",
+ "pageGradientAngle" => "to bottom",
+ "bgHeightScale" => 0,
+ "topStatusBar" => [
+ 'control' => true,
+ 'isShow' => false,
+ 'bgColor' => "#ffffff",
+ 'rollBgColor' => "#ffffff",
+ 'style' => 'style-1',
+ 'styleName' => '风格1',
+ 'textColor' => "#333333",
+ 'rollTextColor' => "#333333",
+ 'textAlign' => 'center',
+ 'inputPlaceholder' => '请输入搜索关键词',
+ 'imgUrl' => '',
+ 'link' => [
+ 'name' => ""
+ ]
+ ],
+ "bottomTabBar" => [
+ 'control' => true,
+ 'isShow' => true,
+ 'designNav' => [
+ 'title' => '',
+ 'key' => ''
+ ]
+ ],
+ "copyright" => [
+ 'control' => true,
+ 'isShow' => false,
+ 'textColor' =>'#ccc'
+ ],
+ "popWindow" => [
+ "imgUrl" => "",
+ "imgWidth" => "",
+ "imgHeight" => "",
+ "count" => 'once',
+ "show" => 0,
+ "link" => [
+ "name" => ""
+ ]
+ ],
+ "template" => [
+ "textColor" => "#303133",
+ "pageStartBgColor" => "",
+ "pageEndBgColor" => "",
+ "pageGradientAngle" => "to bottom",
+ "componentBgUrl" => "",
+ "componentBgAlpha" => 2,
+ "componentStartBgColor" => "",
+ "componentEndBgColor" => "",
+ "componentGradientAngle" => "to bottom",
+ "topRounded" => 0,
+ "bottomRounded" => 0,
+ "elementBgColor" => "",
+ "topElementRounded" => 0,
+ "bottomElementRounded" => 0,
+ "margin" => [
+ "top" => 0,
+ "bottom" => 0,
+ "both" => 0
+ ]
+ ]
+ ],
+ "value" => [
+ [
+ "id" => "d0ib6565eaw",
+ "componentName" => "ShopExchangeInfo",
+ "componentTitle" => "积分兑换",
+ "path" => "edit-shop-exchange-info",
+ "uses" => 0,
+ "ignore" => [],
+ "bgUrl" => "addon/shop/diy/point/point_index_bg.jpg",
+ "textColor" => "#303133",
+ "pageStartBgColor" => "",
+ "pageEndBgColor" => "",
+ "pageGradientAngle" => "to bottom",
+ "componentBgUrl" => "",
+ "componentBgAlpha" => 2,
+ "componentStartBgColor" => "",
+ "componentEndBgColor" => "",
+ "componentGradientAngle" => "to bottom",
+ "topRounded" => 0,
+ "bottomRounded" => 0,
+ "elementBgColor" => "",
+ "topElementRounded" => 0,
+ "bottomElementRounded" => 0,
+ "margin" => [
+ "top" => 0,
+ "bottom" => 0,
+ "both" => 0
+ ],
+ ],
+ [
+ "id" => "5lml3wp5tow0",
+ "componentName" => "GraphicNav",
+ "componentTitle" => "图文导航",
+ "path" => "edit-graphic-nav",
+ "uses" => 0,
+ "ignore" => [],
+ "layout" => "horizontal",
+ "mode" => "graphic",
+ "showStyle" => "fixed",
+ "rowCount" => 3,
+ "pageCount" => 2,
+ "carousel" => [
+ "type" => "circle",
+ "color" => "#FFFFFF"
+ ],
+ "imageSize" => 40,
+ "aroundRadius" => 0,
+ "font" => [
+ "size" => 13,
+ "weight" => "normal",
+ "color" => "#303133"
+ ],
+ "list" => [
+ [
+ "title" => "我的积分",
+ "link" => [
+ "parent" => "MEMBER_LINK",
+ "name" => "MEMBER_POINT",
+ "title" => "我的积分",
+ "url" => "/app/pages/member/point",
+ "action" => ""
+ ],
+ "imageUrl" => "addon/shop/diy/point/nav_point.png",
+ "label" => [
+ "control" => false,
+ "text" => "热门",
+ "textColor" => "#FFFFFF",
+ "bgColorStart" => "#F83287",
+ "bgColorEnd" => "#FE3423"
+ ],
+ "id" => "4fll6n7lge40",
+ "imgWidth" => 140,
+ "imgHeight" => 140
+ ],
+ [
+ "title" => "我的兑换",
+ "link" => [
+ "parent" => "SHOP_LINK",
+ "name" => "SHOP_POINT_ORDER_LIST",
+ "title" => "积分兑换记录",
+ "url" => "/addon/shop/pages/point/order_list",
+ "action" => ""
+ ],
+ "imageUrl" => "addon/shop/diy/point/nav_my_exchange.png",
+ "label" => [
+ "control" => false,
+ "text" => "热门",
+ "textColor" => "#FFFFFF",
+ "bgColorStart" => "#F83287",
+ "bgColorEnd" => "#FE3423"
+ ],
+ "id" => "4blja5zsv0m0",
+ "imgWidth" => 140,
+ "imgHeight" => 132
+ ],
+ [
+ "title" => "每日签到",
+ "link" => [
+ "name" => "MEMBER_MY_SIGN_IN",
+ "parent" => "MEMBER_LINK",
+ "title" => "我的签到",
+ "url" => "/app/pages/member/sign_in",
+ "action" => ""
+ ],
+ "imageUrl" => "addon/shop/diy/point/nav_sign_in.png",
+ "label" => [
+ "control" => false,
+ "text" => "热门",
+ "textColor" => "#FFFFFF",
+ "bgColorStart" => "#F83287",
+ "bgColorEnd" => "#FE3423"
+ ],
+ "id" => "6v4fptrqano0",
+ "imgWidth" => 134,
+ "imgHeight" => 132
+ ]
+ ],
+ // 轮播图设置
+ 'swiper' => [
+ 'indicatorColor' => 'rgba(0, 0, 0, 0.3)', // 未选中颜色
+ "indicatorActiveColor" => '#FF0E0E',
+ 'indicatorStyle' => 'style-1',
+ 'indicatorAlign' => 'center',
+ ],
+ "textColor" => "#303133",
+ "pageStartBgColor" => "",
+ "pageEndBgColor" => "rgba(255, 255, 255, 1)",
+ "pageGradientAngle" => "to bottom",
+ "componentBgUrl" => "",
+ "componentBgAlpha" => 2,
+ "componentStartBgColor" => "rgba(255, 255, 255, 1)",
+ "componentEndBgColor" => "rgba(255, 255, 255, 1)",
+ "componentGradientAngle" => "to bottom",
+ "topRounded" => 17,
+ "bottomRounded" => 17,
+ "elementBgColor" => "",
+ "topElementRounded" => 0,
+ "bottomElementRounded" => 0,
+ "margin" => [
+ "top" => -40,
+ "bottom" => 0,
+ "both" => 10
+ ]
+ ],
+ [
+ "id" => "6c7y9m3c99o0",
+ "componentName" => "HorzBlank",
+ "componentTitle" => "辅助空白",
+ "path" => "edit-horz-blank",
+ "uses" => 0,
+ "height" => 15,
+ "ignore" => [
+ "pageBgColor",
+ "componentBgUrl"
+ ],
+ "textColor" => "#303133",
+ "pageStartBgColor" => "",
+ "pageEndBgColor" => "",
+ "pageGradientAngle" => "to bottom",
+ "componentBgUrl" => "",
+ "componentBgAlpha" => 2,
+ "componentStartBgColor" => "",
+ "componentEndBgColor" => "",
+ "componentGradientAngle" => "to bottom",
+ "topRounded" => 0,
+ "bottomRounded" => 0,
+ "elementBgColor" => "",
+ "topElementRounded" => 0,
+ "bottomElementRounded" => 0,
+ "margin" => [
+ "top" => 10,
+ "bottom" => 0,
+ "both" => 10
+ ]
+ ],
+ [
+ "id" => "3h6ppt6s1jw0",
+ "componentName" => "Text",
+ "componentTitle" => "标题",
+ "path" => "edit-text",
+ "uses" => 0,
+ "fontSize" => 15,
+ "position" => "",
+ "ignore" => [],
+ "style" => "style-2",
+ "styleName" => "风格2",
+ "text" => "热门推荐",
+ "link" => [
+ "name" => ""
+ ],
+ "textColor" => "#303133",
+ "fontWeight" => "normal",
+ "textAlign" => "center",
+ "subTitle" => [
+ "text" => "",
+ "color" => "#999999",
+ "fontSize" => 13,
+ "control" => true,
+ "fontWeight" => "normal"
+ ],
+ "more" => [
+ "text" => "更多",
+ "control" => true,
+ "isShow" => true,
+ "link" => [
+ "parent" => "SHOP_LINK",
+ "name" => "SHOP_POINT_LIST",
+ "title" => "积分商品列表",
+ "url" => "/addon/shop/pages/point/list",
+ "action" => ""
+ ],
+ "color" => "#999999"
+ ],
+ "pageStartBgColor" => "",
+ "pageEndBgColor" => "",
+ "pageGradientAngle" => "to bottom",
+ "componentBgUrl" => "",
+ "componentBgAlpha" => 2,
+ "componentStartBgColor" => "",
+ "componentEndBgColor" => "",
+ "componentGradientAngle" => "to bottom",
+ "topRounded" => 0,
+ "bottomRounded" => 0,
+ "elementBgColor" => "",
+ "topElementRounded" => 0,
+ "bottomElementRounded" => 0,
+ "margin" => [
+ "top" => 0,
+ "bottom" => 0,
+ "both" => 0
+ ]
+ ],
+ [
+ "id" => "2jeafwoghdk0",
+ "componentName" => "HorzBlank",
+ "componentTitle" => "辅助空白",
+ "path" => "edit-horz-blank",
+ "uses" => 0,
+ "height" => 10,
+ "ignore" => [
+ "pageBgColor",
+ "componentBgUrl"
+ ],
+ "textColor" => "#303133",
+ "pageStartBgColor" => "",
+ "pageEndBgColor" => "",
+ "pageGradientAngle" => "to bottom",
+ "componentBgUrl" => "",
+ "componentBgAlpha" => 2,
+ "componentStartBgColor" => "",
+ "componentEndBgColor" => "",
+ "componentGradientAngle" => "to bottom",
+ "topRounded" => 0,
+ "bottomRounded" => 0,
+ "elementBgColor" => "",
+ "topElementRounded" => 0,
+ "bottomElementRounded" => 0,
+ "margin" => [
+ "top" => 0,
+ "bottom" => 0,
+ "both" => 0
+ ]
+ ],
+ [
+ "id" => "76wf7oom00o0",
+ "componentName" => "ShopExchangeGoods",
+ "componentTitle" => "积分商品",
+ "path" => "edit-shop-exchange-goods",
+ "uses" => 0,
+ "ignore" => [],
+ "style" => "style-2",
+ "source" => "all",
+ "num" => 10,
+ "goods_category" => "",
+ "goods_category_name" => "请选择",
+ "goods_ids" => [],
+ "sortWay" => "total_order_num",
+ "goodsNameStyle" => [
+ "color" => "#333",
+ "control" => true,
+ "fontWeight" => "normal"
+ ],
+ "priceStyle" => [
+ "mainColor" => "#FF4142",
+ "mainControl" => true,
+ "lineColor" => "#999CA7",
+ "lineControl" => true
+ ],
+ "saleStyle" => [
+ "color" => "#999999",
+ "control" => true
+ ],
+ "imgElementRounded" => 0,// 图片圆角
+ "textColor" => "#303133",
+ "pageStartBgColor" => "",
+ "pageEndBgColor" => "",
+ "pageGradientAngle" => "to bottom",
+ "componentBgUrl" => "",
+ "componentBgAlpha" => 2,
+ "componentStartBgColor" => "",
+ "componentEndBgColor" => "",
+ "componentGradientAngle" => "to bottom",
+ "topRounded" => 0,
+ "bottomRounded" => 0,
+ "elementBgColor" => "",
+ "topElementRounded" => 12,
+ "bottomElementRounded" => 12,
+ "margin" => [
+ "top" => 0,
+ "bottom" => 0,
+ "both" => 10
+ ]
+ ]
+ ]
+ ]
+ ]
+ ],
+ 'DIY_SHOP_GOODS_DETAIL' => [
+ 'shop_goods_detail_style1' => [
+ "title" => "商品详情",
+ 'cover' => '', // 页面封面图
+ 'preview' => '', // 页面预览图
+ 'desc' => '', // 页面描述
+ 'mode' => 'diy', // 页面模式:diy:自定义,fixed:固定
+ // 页面数据源
+ 'data' => [
+ 'global' => [
+ 'title' => '商品详情',
+ 'completeLayout' => 'style-1',
+ 'completeAlign' => 'left',
+ 'borderControl' => true,
+ 'pageStartBgColor' => 'rgba(246, 246, 246, 1)',
+ 'pageEndBgColor' => '',
+ 'pageGradientAngle' => 'to bottom',
+ 'bgUrl' => '',
+ 'bgHeightScale' => 100,
+ 'imgWidth' => '',
+ 'imgHeight' => '',
+ 'topStatusBar' => [
+ 'control' => false,
+ 'isShow' => false,
+ 'bgColor' => "#ffffff",
+ 'rollBgColor' => "#ffffff",
+ 'style' => 'style-1',
+ 'styleName' => '风格1',
+ 'textColor' => "#333333",
+ 'rollTextColor' => "#333333",
+ 'textAlign' => 'center',
+ 'inputPlaceholder' => '请输入搜索关键词',
+ 'imgUrl' => '',
+ 'link' => [
+ 'name' => ""
+ ]
+ ],
+ 'bottomTabBar' => [
+ 'control' => false,
+ 'isShow' => false,
+ 'designNav' => [
+ 'title' => '',
+ 'key' => ''
+ ]
+ ],
+ "copyright" => [
+ 'control' => true,
+ 'isShow' => false,
+ 'textColor' =>'#ccc'
+ ],
+ 'popWindow' => [
+ 'imgUrl' => '',
+ 'imgWidth' => '',
+ 'imgHeight' => '',
+ 'count' => 'once',
+ 'show' => false,
+ 'link' => [
+ 'name' => ''
+ ]
+ ],
+ 'template' => [
+ 'textColor' => '#303133',
+ 'pageStartBgColor' => '',
+ 'pageEndBgColor' => '',
+ 'pageGradientAngle' => 'to bottom',
+ 'componentBgUrl' => '',
+ 'componentBgAlpha' => 2,
+ 'componentStartBgColor' => '',
+ 'componentEndBgColor' => '',
+ 'componentGradientAngle' => 'to bottom',
+ 'topRounded' => 0,
+ 'bottomRounded' => 0,
+ 'elementBgColor' => '',
+ 'topElementRounded' => 0,
+ 'bottomElementRounded' => 0,
+ 'margin' => [
+ 'top' => 0,
+ 'bottom' => 0,
+ 'both' => 0
+ ],
+ 'isHidden' => false
+ ]
+ ],
+ 'value' => [
+ [
+ 'path' => 'edit-shop-goods-detail-basic-info',
+ 'uses' => 1,
+ 'position' => 'top_fixed',
+ 'id' => 'j3hqu5tg1zk',
+ 'componentName' => 'ShopGoodsDetailBasicInfo',
+ 'componentTitle' => '基础信息',
+ 'ignore' => [
+ 'pageBgColor',
+ 'componentBgUrl',
+ 'marginTop',
+ 'marginBottom',
+ 'marginBoth',
+ 'topRounded',
+ 'bottomRounded'
+ ],
+ 'menuContent' => 'index,search,cart,member',
+ 'medium' => [
+ 'type' => 'square_img',
+ 'indicator' => true
+ ],
+ 'priceRegion' => [
+ 'showWay' => 'normal',
+ 'bgImg' => 'addon/shop/diy/goods_detail/style_01.jpg',
+ 'marketingBgImg' => 'addon/shop/diy/goods_detail/marketing_style_01.jpg',
+ 'goodsStyle' => [
+ 'title' => '风格1',
+ 'value' => 'style-1'
+ ],
+ 'marketingStyle' => [
+ 'title' => '风格1',
+ 'value' => 'style-1'
+ ]
+ ],
+ 'goodsInfo' => [
+ 'titleColor' => '#333333',
+ 'subTitleColor' => '#999999',
+ 'saleInfoColor' => '#999999',
+ 'priceTopRounded' => 17,
+ 'priceBottomRounded' => 0,
+ 'topRounded' => 12,
+ 'bottomRounded' => 0,
+ 'priceBgColor' => '',
+ "startBgColor" => '#ffffff',
+ "endBgColor" => 'rgba(254, 254, 254, 1)',
+ 'priceAboutMargin' => 0,
+ 'priceTopMargin' => -22,
+ 'topMargin' => -13,
+ 'aboutMargin' => 0
+ ],
+ 'saleInfo' => ['underlined_price', 'sales', 'stock'],
+ 'textColor' => '#303133',
+ 'pageStartBgColor' => '',
+ 'pageEndBgColor' => '',
+ 'pageGradientAngle' => 'to bottom',
+ 'componentBgUrl' => '',
+ 'componentBgAlpha' => 2,
+ 'componentStartBgColor' => '',
+ 'componentEndBgColor' => '',
+ 'componentGradientAngle' => 'to bottom',
+ 'topRounded' => 0,
+ 'bottomRounded' => 0,
+ 'elementBgColor' => '',
+ 'topElementRounded' => 0,
+ 'bottomElementRounded' => 0,
+ 'margin' => [
+ 'top' => 0,
+ 'bottom' => 0,
+ 'both' => 0
+ ],
+ 'isHidden' => false
+ ],
+ [
+ "path" => "edit-horz-blank",
+ "uses" => 0,
+ "id" => "7lc46dh86vw0",
+ "componentName" => "HorzBlank",
+ "componentTitle" => "辅助空白",
+ "ignore" => [
+ "pageBgColor",
+ "componentBgUrl"
+ ],
+ "height" => 100,
+ "textColor" => "#303133",
+ "pageStartBgColor" => "",
+ "pageEndBgColor" => "",
+ "pageGradientAngle" => "to bottom",
+ "componentBgUrl" => "",
+ "componentBgAlpha" => 2,
+ "componentStartBgColor" => "rgba(253, 253, 253, 1)",
+ "componentEndBgColor" => "rgba(246, 246, 246, 1)",
+ "componentGradientAngle" => "to bottom",
+ "topRounded" => 0,
+ "bottomRounded" => 0,
+ "elementBgColor" => "",
+ "topElementRounded" => 0,
+ "bottomElementRounded" => 0,
+ "margin" => [
+ "top" => 0,
+ "bottom" => -100,
+ "both" => 0
+ ],
+ "isHidden" => false
+ ],
+ [
+ 'path' => 'edit-shop-goods-detail-purchase-service',
+ 'uses' => 1,
+ 'id' => 'c4wh1kcz3i0',
+ 'componentName' => 'ShopGoodsDetailPurchaseService',
+ 'componentTitle' => '商品服务',
+ 'ignore' => [],
+ 'serviceConfig' => ['goods_service', 'spec_select', 'delivery_info', 'coupons', 'activity'],
+ 'textColor' => '#303133',
+ 'pageStartBgColor' => '',
+ 'pageEndBgColor' => '',
+ 'pageGradientAngle' => 'to bottom',
+ 'componentBgUrl' => '',
+ 'componentBgAlpha' => 2,
+ 'componentStartBgColor' => '#FFFFFF',
+ 'componentEndBgColor' => '',
+ 'componentGradientAngle' => 'to bottom',
+ 'topRounded' => 12,
+ 'bottomRounded' => 12,
+ 'elementBgColor' => '',
+ 'topElementRounded' => 0,
+ 'bottomElementRounded' => 0,
+ 'margin' => [
+ 'top' => 12,
+ 'bottom' => 0,
+ 'both' => 10
+ ],
+ 'isHidden' => false
+ ],
+ [
+ 'path' => 'edit-shop-goods-detail-sow',
+ 'uses' => 0,
+ 'id' => '1zi5tkyxurpc',
+ 'componentName' => 'ShopGoodsDetailSow',
+ 'componentTitle' => '种草秀',
+ 'ignore' => [],
+ 'isShow' => true,
+ 'textColor' => '#303133',
+ 'pageStartBgColor' => '',
+ 'pageEndBgColor' => '',
+ 'pageGradientAngle' => 'to bottom',
+ 'componentBgUrl' => '',
+ 'componentBgAlpha' => 2,
+ 'componentStartBgColor' => '#FFFFFF',
+ 'componentEndBgColor' => '',
+ 'componentGradientAngle' => 'to bottom',
+ 'topRounded' => 12,
+ 'bottomRounded' => 12,
+ 'elementBgColor' => '',
+ 'topElementRounded' => 0,
+ 'bottomElementRounded' => 0,
+ 'margin' => [
+ 'top' => 12,
+ 'bottom' => 0,
+ 'both' => 10
+ ],
+ 'isHidden' => false
+ ],
+ [
+ 'path' => 'edit-shop-goods-detail-evaluate',
+ 'uses' => 1,
+ 'id' => '1jgv7ysvlh0g',
+ 'componentName' => 'ShopGoodsDetailEvaluate',
+ 'componentTitle' => '商品评价',
+ 'ignore' => [],
+ 'isShow' => true,
+ 'textColor' => '#303133',
+ 'pageStartBgColor' => '',
+ 'pageEndBgColor' => '',
+ 'pageGradientAngle' => 'to bottom',
+ 'componentBgUrl' => '',
+ 'componentBgAlpha' => 2,
+ 'componentStartBgColor' => '#FFFFFF',
+ 'componentEndBgColor' => '',
+ 'componentGradientAngle' => 'to bottom',
+ 'topRounded' => 12,
+ 'bottomRounded' => 12,
+ 'elementBgColor' => '',
+ 'topElementRounded' => 0,
+ 'bottomElementRounded' => 0,
+ 'margin' => [
+ 'top' => 12,
+ 'bottom' => 0,
+ 'both' => 10
+ ],
+ 'isHidden' => false
+ ],
+ [
+ 'path' => 'edit-shop-goods-detail-attr',
+ 'uses' => 1,
+ 'id' => '19m7738ofq68',
+ 'componentName' => 'ShopGoodsDetailAttr',
+ 'componentTitle' => '商品属性',
+ 'ignore' => [],
+ 'isShow' => true,
+ 'textColor' => '#303133',
+ 'pageStartBgColor' => '',
+ 'pageEndBgColor' => '',
+ 'pageGradientAngle' => 'to bottom',
+ 'componentBgUrl' => '',
+ 'componentBgAlpha' => 2,
+ 'componentStartBgColor' => '#FFFFFF',
+ 'componentEndBgColor' => '',
+ 'componentGradientAngle' => 'to bottom',
+ 'topRounded' => 12,
+ 'bottomRounded' => 12,
+ 'elementBgColor' => '',
+ 'topElementRounded' => 0,
+ 'bottomElementRounded' => 0,
+ 'margin' => [
+ 'top' => 12,
+ 'bottom' => 0,
+ 'both' => 10
+ ],
+ 'isHidden' => false
+ ],
+ [
+ 'path' => 'edit-shop-goods-detail-desc',
+ 'uses' => 1,
+ 'id' => '37i90so3cly0',
+ 'componentName' => 'ShopGoodsDetailDesc',
+ 'componentTitle' => '商品详情',
+ 'ignore' => [],
+ 'isShow' => true,
+ 'textColor' => '#303133',
+ 'pageStartBgColor' => '',
+ 'pageEndBgColor' => '',
+ 'pageGradientAngle' => 'to bottom',
+ 'componentBgUrl' => '',
+ 'componentBgAlpha' => 2,
+ 'componentStartBgColor' => '#FFFFFF',
+ 'componentEndBgColor' => '',
+ 'componentGradientAngle' => 'to bottom',
+ 'topRounded' => 12,
+ 'bottomRounded' => 12,
+ 'elementBgColor' => '',
+ 'topElementRounded' => 0,
+ 'bottomElementRounded' => 0,
+ 'margin' => [
+ 'top' => 12,
+ 'bottom' => 20,
+ 'both' => 10
+ ],
+ 'isHidden' => false
+ ],
+ [
+ 'path' => 'edit-shop-goods-detail-bottom',
+ 'position' => 'bottom_fixed',
+ 'uses' => 1,
+ 'id' => 'p313pc2eduo',
+ 'componentName' => 'ShopGoodsDetailBottom',
+ 'componentTitle' => '底部菜单',
+ 'ignore' => [
+ 'pageBgColor',
+ 'componentBgUrl',
+ 'marginTop',
+ 'marginBottom',
+ 'marginBoth',
+ 'topRounded',
+ 'bottomRounded'
+ ],
+ 'menuContent' => ['index', 'service', 'cart'],
+ 'cartName' => '加入购物车',
+ 'buyName' => '立即购买',
+ 'cartIsShow' => true,
+ 'cartStyle' => [
+ 'textColor' => '#FFFFFF',
+ 'fontSize' => 12,
+ 'gradientAngle' => 'to right',
+ 'startColor' => '#FFB000',
+ 'endColor' => '#FFA029'
+ ],
+ 'buyStyle' => [
+ 'textColor' => '#FFFFFF',
+ 'fontSize' => 12,
+ 'gradientAngle' => 'to right',
+ 'startColor' => '#FB7939',
+ 'endColor' => '#FF4142'
+ ],
+ 'textColor' => '#303133',
+ 'pageStartBgColor' => '',
+ 'pageEndBgColor' => '',
+ 'pageGradientAngle' => 'to bottom',
+ 'componentBgUrl' => '',
+ 'componentBgAlpha' => 2,
+ 'componentStartBgColor' => '#FFFFFF',
+ 'componentEndBgColor' => '',
+ 'componentGradientAngle' => 'to bottom',
+ 'topRounded' => 0,
+ 'bottomRounded' => 0,
+ 'elementBgColor' => '',
+ 'topElementRounded' => 0,
+ 'bottomElementRounded' => 0,
+ 'margin' => [
+ 'top' => 0,
+ 'bottom' => 0,
+ 'both' => 0
+ ],
+ 'isHidden' => false
+ ]
+ ]
+ ]
+ ]
+ ]
+];
\ No newline at end of file
diff --git a/niucloud/addon/shop/app/dict/diy/template.php b/niucloud/addon/shop/app/dict/diy/template.php
new file mode 100644
index 000000000..ea9fd60e3
--- /dev/null
+++ b/niucloud/addon/shop/app/dict/diy/template.php
@@ -0,0 +1,49 @@
+ [
+ 'title' => get_lang('dict_diy.page_shop_index'),
+ 'page' => '/addon/shop/pages/index',
+ 'action' => 'decorate',
+ 'type' => 'index'
+ ],
+ 'DIY_SHOP_MEMBER_INDEX' => [
+ 'title' => get_lang('dict_diy.page_shop_member_index'),
+ 'page' => '/addon/shop/pages/member/index',
+ 'action' => 'decorate',
+ 'type' => 'member_index'
+ ],
+ 'DIY_SHOP_POINT_INDEX' => [
+ 'title' => get_lang('dict_diy.page_shop_point_index'),
+ 'page' => '/addon/shop/pages/point/index',
+ 'action' => 'decorate',
+ 'type' => ''
+ ],
+ 'DIY_SHOP_GOODS_DETAIL' => [
+ 'title' => get_lang('dict_diy.page_shop_detail'),
+ 'page' => '/addon/shop/pages/goods/detail',
+ 'action' => 'decorate',
+ 'type' => '',
+ 'ignoreComponents' => ['CarouselSearch'], // 忽略组件名单,商品详情不支持添加轮播搜索组件
+ // 页面数据结构,初始化时覆盖
+ 'global' => [
+ 'topStatusBar' => [
+ 'control' => false, // 隐藏顶部导航栏,禁止编辑
+ ],
+ 'bottomTabBar' => [
+ 'control' => false, // 隐藏底部导航,禁止编辑
+ 'isShow' => false,
+ 'designNav' => [
+ 'title' => '',
+ 'key' => ''
+ ]
+ ],
+ "copyright" => [
+ 'control' => true,
+ 'isShow' => false,
+ 'textColor' =>'#ccc'
+ ],
+ ],
+
+ ],
+];
diff --git a/niucloud/addon/shop/app/dict/diy_form/components.php b/niucloud/addon/shop/app/dict/diy_form/components.php
new file mode 100644
index 000000000..ece5556d8
--- /dev/null
+++ b/niucloud/addon/shop/app/dict/diy_form/components.php
@@ -0,0 +1,23 @@
+ [
+// 'title' => get_lang('dict_diy_form.shop_component_type_basic'),
+// 'list' => [
+// 'GoodsInput' => [
+// 'title' => '商品文本',
+// 'icon' => 'iconfont iconbiaotipc',
+// 'path' => 'edit-goods-input', // 编辑组件属性名称
+// 'uses' => 0, // 最大添加数量
+// 'sort' => 10001,
+// 'value' => [
+// 'label' => '商品文本',
+// 'type' => 'text', // 文本、手机号、身份证号码、邮箱、数字、带小数点数字
+// 'placeholder' => '请输入文本内容', // 提示语
+// 'default' => '',
+// 'required' => true // 这个是公共字段
+// ]
+// ],
+// ]
+// ]
+];
diff --git a/niucloud/addon/shop/app/dict/diy_form/template.php b/niucloud/addon/shop/app/dict/diy_form/template.php
new file mode 100644
index 000000000..f2b833e0c
--- /dev/null
+++ b/niucloud/addon/shop/app/dict/diy_form/template.php
@@ -0,0 +1,437 @@
+ [
+ 'shop_goods_detail_form_data' => [ // 页面标识
+ "title" => "商品表单", // 页面名称
+ 'cover' => '', // 页面封面图
+ 'preview' => '', // 页面预览图
+ 'desc' => '', // 页面描述
+ // 页面数据源
+ "data" => [
+ "global" => [
+ "title" => "商品表单",
+ "pageStartBgColor" => "",
+ "pageEndBgColor" => "",
+ "pageGradientAngle" => "to bottom",
+ "bgUrl" => "",
+ "bgHeightScale" => 100,
+ "imgWidth" => "",
+ "imgHeight" => "",
+ "topStatusBar" => [
+ 'control' => true,
+ "isShow" => true,
+ "bgColor" => "#ffffff",
+ "style" => "style-1",
+ "textColor" => "#333333",
+ "textAlign" => "center",
+ "rollBgColor" => "#ffffff",
+ "styleName" => "风格1",
+ "rollTextColor" => "#333333",
+ "inputPlaceholder" => "请输入搜索关键词",
+ "imgUrl" => "",
+ "link" => [
+ "name" => ""
+ ]
+ ],
+ "bottomTabBar" => [
+ 'control' => true,
+ 'isShow' => true,
+ 'designNav' => [
+ 'title' => '',
+ 'key' => ''
+ ]
+ ],
+ "copyright" => [
+ 'control' => true,
+ 'isShow' => false,
+ 'textColor' =>'#ccc'
+ ],
+ "popWindow" => [
+ "imgUrl" => "",
+ "imgWidth" => "",
+ "imgHeight" => "",
+ "count" => 'once',
+ "show" => 0,
+ "link" => [
+ "name" => ""
+ ]
+ ],
+ "template" => [
+ "textColor" => "#303133",
+ "pageStartBgColor" => "",
+ "pageEndBgColor" => "",
+ "pageGradientAngle" => "to bottom",
+ "componentBgUrl" => "",
+ "componentBgAlpha" => 2,
+ "componentStartBgColor" => "",
+ "componentEndBgColor" => "",
+ "componentGradientAngle" => "to bottom",
+ "topRounded" => 0,
+ "bottomRounded" => 0,
+ "elementBgColor" => "",
+ "topElementRounded" => 0,
+ "bottomElementRounded" => 0,
+ "margin" => [
+ "top" => 0,
+ "bottom" => 0,
+ "both" => 0
+ ],
+ "isHidden" => false
+ ],
+ "completeLayout" => "style-2",
+ "completeAlign" => "left",
+ "borderControl" => false,
+ ],
+ "value" => [
+ [
+ "path" => "edit-form-input",
+ "uses" => 0,
+ "id" => "4n7ik4t1dsa0",
+ "componentName" => "FormInput",
+ "componentTitle" => "单行文本",
+ "ignore" => [
+ "componentBgUrl"
+ ],
+ "textColor" => "#303133",
+ "pageStartBgColor" => "#FFFFFF",
+ "pageEndBgColor" => "",
+ "pageGradientAngle" => "to bottom",
+ "componentBgUrl" => "",
+ "componentBgAlpha" => 2,
+ "componentEndBgColor" => "",
+ "componentGradientAngle" => "to bottom",
+ "topRounded" => 0,
+ "bottomRounded" => 0,
+ "elementBgColor" => "",
+ "topElementRounded" => 0,
+ "bottomElementRounded" => 0,
+ "margin" => [
+ "top" => 0,
+ "bottom" => 0,
+ "both" => 0
+ ],
+ "fontSize" => 14,
+ "fontWeight" => "normal",
+ "position" => "",
+ "componentType" => "diy_form",
+ "field" => [
+ "name" => "姓名",
+ "remark" => [
+ "text" => "",
+ "color" => "#999999",
+ "fontSize" => 14
+ ],
+ "required" => false,
+ "unique" => false,
+ "autofill" => false,
+ "privacyProtection" => false,
+ 'cache' => true,
+ "default" => "",
+ "value" => ""
+ ],
+ "placeholder" => "请输入姓名",
+ "componentStartBgColor" => "",
+ "isHidden" => false
+ ],
+ [
+ "path" => "edit-form-mobile",
+ "uses" => 1,
+ "componentType" => "diy_form",
+ "id" => "1dufay5r2h7k",
+ "componentName" => "FormMobile",
+ "componentTitle" => "手机号",
+ "ignore" => [
+ "componentBgUrl"
+ ],
+ "field" => [
+ "name" => "联系电话",
+ "remark" => [
+ "text" => "",
+ "color" => "#999999",
+ "fontSize" => 14
+ ],
+ "required" => false,
+ "unique" => true,
+ "autofill" => false,
+ "privacyProtection" => false,
+ 'cache' => true,
+ "default" => "",
+ "value" => ""
+ ],
+ "placeholder" => "请输入联系电话",
+ "fontSize" => 14,
+ "fontWeight" => "normal",
+ "textColor" => "#303133",
+ "pageStartBgColor" => "#FFFFFF",
+ "pageEndBgColor" => "",
+ "pageGradientAngle" => "to bottom",
+ "componentBgUrl" => "",
+ "componentBgAlpha" => 2,
+ "componentStartBgColor" => "",
+ "componentEndBgColor" => "",
+ "componentGradientAngle" => "to bottom",
+ "topRounded" => 0,
+ "bottomRounded" => 0,
+ "elementBgColor" => "",
+ "topElementRounded" => 0,
+ "bottomElementRounded" => 0,
+ "margin" => [
+ "top" => 0,
+ "bottom" => 0,
+ "both" => 0
+ ],
+ "isHidden" => false
+ ],
+ [
+ "path" => "edit-form-identity",
+ "uses" => 1,
+ "componentType" => "diy_form",
+ "id" => "46n4aaxy0uc0",
+ "componentName" => "FormIdentity",
+ "componentTitle" => "身份证号",
+ "ignore" => [
+ "componentBgUrl"
+ ],
+ "field" => [
+ "name" => "身份证号",
+ "remark" => [
+ "text" => "",
+ "color" => "#999999",
+ "fontSize" => 14
+ ],
+ "required" => false,
+ "unique" => false,
+ "autofill" => false,
+ "privacyProtection" => false,
+ 'cache' => true,
+ "default" => "",
+ "value" => ""
+ ],
+ "placeholder" => "请输入身份证号",
+ "fontSize" => 14,
+ "fontWeight" => "normal",
+ "textColor" => "#303133",
+ "pageStartBgColor" => "#FFFFFF",
+ "pageEndBgColor" => "",
+ "pageGradientAngle" => "to bottom",
+ "componentBgUrl" => "",
+ "componentBgAlpha" => 2,
+ "componentStartBgColor" => "",
+ "componentEndBgColor" => "",
+ "componentGradientAngle" => "to bottom",
+ "topRounded" => 0,
+ "bottomRounded" => 0,
+ "elementBgColor" => "",
+ "topElementRounded" => 0,
+ "bottomElementRounded" => 0,
+ "margin" => [
+ "top" => 0,
+ "bottom" => 0,
+ "both" => 0
+ ],
+ "isHidden" => false
+ ]
+ ]
+ ]
+ ],
+ ],
+ 'DIY_FROM_ORDER_PAYMENT' => [
+ 'shop_order_form_data' => [ // 页面标识
+ "title" => "待付款表单", // 页面名称
+ 'cover' => '', // 页面封面图
+ 'preview' => '', // 页面预览图
+ 'desc' => '', // 页面描述
+ // 页面数据源
+ "data" => [
+ "global" => [
+ "title" => "待付款表单",
+ "pageStartBgColor" => "",
+ "pageEndBgColor" => "",
+ "pageGradientAngle" => "to bottom",
+ "bgUrl" => "",
+ "bgHeightScale" => 100,
+ "imgWidth" => "",
+ "imgHeight" => "",
+ "topStatusBar" => [
+ 'control' => true,
+ "isShow" => true,
+ "bgColor" => "#ffffff",
+ "style" => "style-1",
+ "textColor" => "#333333",
+ "textAlign" => "center",
+ "rollBgColor" => "#ffffff",
+ "styleName" => "风格1",
+ "rollTextColor" => "#333333",
+ "inputPlaceholder" => "请输入搜索关键词",
+ "imgUrl" => "",
+ "link" => [
+ "name" => ""
+ ]
+ ],
+ "bottomTabBar" => [
+ 'control' => true,
+ 'isShow' => true,
+ 'designNav' => [
+ 'title' => '',
+ 'key' => ''
+ ]
+ ],
+ "copyright" => [
+ 'control' => true,
+ 'isShow' => false,
+ 'textColor' =>'#ccc'
+ ],
+ "popWindow" => [
+ "imgUrl" => "",
+ "imgWidth" => "",
+ "imgHeight" => "",
+ "count" => 'once',
+ "show" => 0,
+ "link" => [
+ "name" => ""
+ ]
+ ],
+ "template" => [
+ "textColor" => "#303133",
+ "pageStartBgColor" => "",
+ "pageEndBgColor" => "",
+ "pageGradientAngle" => "to bottom",
+ "componentBgUrl" => "",
+ "componentBgAlpha" => 2,
+ "componentStartBgColor" => "",
+ "componentEndBgColor" => "",
+ "componentGradientAngle" => "to bottom",
+ "topRounded" => 0,
+ "bottomRounded" => 0,
+ "elementBgColor" => "",
+ "topElementRounded" => 0,
+ "bottomElementRounded" => 0,
+ "margin" => [
+ "top" => 0,
+ "bottom" => 0,
+ "both" => 0
+ ],
+ "isHidden" => false
+ ],
+ "completeLayout" => "style-2",
+ "completeAlign" => "left",
+ "borderControl" => false
+ ],
+ "value" => [
+ [
+ "path" => "edit-form-mobile",
+ "uses" => 1,
+ "id" => "pe5nd1wsn28",
+ "componentName" => "FormMobile",
+ "componentTitle" => "手机号",
+ "ignore" => [
+ "componentBgUrl"
+ ],
+ "textColor" => "#303133",
+ "pageStartBgColor" => "#FFFFFF",
+ "pageEndBgColor" => "",
+ "pageGradientAngle" => "to bottom",
+ "componentBgUrl" => "",
+ "componentBgAlpha" => 2,
+ "componentEndBgColor" => "",
+ "componentGradientAngle" => "to bottom",
+ "topRounded" => 0,
+ "bottomRounded" => 0,
+ "elementBgColor" => "",
+ "topElementRounded" => 0,
+ "bottomElementRounded" => 0,
+ "margin" => [
+ "top" => 1,
+ "bottom" => 0,
+ "both" => 0
+ ],
+ "fontSize" => 14,
+ "fontWeight" => "normal",
+ "componentType" => "diy_form",
+ "field" => [
+ "name" => "联系电话",
+ "remark" => [
+ "text" => "",
+ "color" => "#999999",
+ "fontSize" => 14
+ ],
+ "required" => false,
+ "unique" => false,
+ "autofill" => false,
+ "privacyProtection" => false,
+ 'cache' => true,
+ "default" => "",
+ "value" => ""
+ ],
+ "placeholder" => "请输入联系电话",
+ "componentStartBgColor" => "",
+ "isHidden" => false,
+ "sort" => 10008,
+ "pageStyle" => "background-color:#FFFFFF;padding-top:2rpx;padding-bottom:0rpx;padding-right:0rpx;padding-left:0rpx;"
+ ],
+ [
+ "path" => "edit-form-date",
+ "uses" => 0,
+ "componentType" => "diy_form",
+ "id" => "2230h04r8za8",
+ "componentName" => "FormDate",
+ "componentTitle" => "日期",
+ "ignore" => [
+ "componentBgUrl"
+ ],
+ "field" => [
+ "name" => "配送日期",
+ "remark" => [
+ "text" => "",
+ "color" => "#999999",
+ "fontSize" => 14
+ ],
+ "required" => false,
+ "unique" => false,
+ "autofill" => false,
+ "privacyProtection" => false,
+ 'cache' => true,
+ "default" => [
+ "date" => "2025-01-15",
+ "timestamp" => 1736913088.477
+ ],
+ "value" => [
+ "date" => "2025/01/15",
+ "timestamp" => 1736870400
+ ]
+ ],
+ "placeholder" => "请选择",
+ "fontSize" => 14,
+ "fontWeight" => "normal",
+ "textColor" => "#303133",
+ "pageStartBgColor" => "#FFFFFF",
+ "pageEndBgColor" => "",
+ "pageGradientAngle" => "to bottom",
+ "componentBgUrl" => "",
+ "componentBgAlpha" => 2,
+ "componentStartBgColor" => "",
+ "componentEndBgColor" => "",
+ "componentGradientAngle" => "to bottom",
+ "topRounded" => 0,
+ "bottomRounded" => 0,
+ "elementBgColor" => "",
+ "topElementRounded" => 0,
+ "bottomElementRounded" => 0,
+ "margin" => [
+ "top" => 1,
+ "bottom" => 0,
+ "both" => 0
+ ],
+ "isHidden" => false,
+ "convert" => [],
+ "dateFormat" => "YYYY/MM/DD",
+ "dateWay" => "current",
+ "defaultControl" => true,
+ "pageStyle" => "background-color:#FFFFFF;padding-top:2rpx;padding-bottom:0rpx;padding-right:0rpx;padding-left:0rpx;"
+ ]
+ ]
+ ]
+ ]
+ ]
+];
diff --git a/niucloud/addon/shop/app/dict/diy_form/type.php b/niucloud/addon/shop/app/dict/diy_form/type.php
new file mode 100644
index 000000000..394ac0255
--- /dev/null
+++ b/niucloud/addon/shop/app/dict/diy_form/type.php
@@ -0,0 +1,16 @@
+ [
+ 'title' => get_lang('dict_diy_form.type_goods_detail'),
+ 'preview' => 'addon/shop/diy_form/goods_detail_preview.jpg', // 预览图
+ 'sort' => 10005,
+ 'addon'=>'shop'
+ ],
+ 'DIY_FROM_ORDER_PAYMENT' => [
+ 'title' => get_lang('dict_diy_form.type_order_payment'),
+ 'preview' => 'addon/shop/diy_form/order_payment_preview.jpg', // 预览图
+ 'sort' => 10006,
+ 'addon'=>'shop'
+ ],
+];
diff --git a/niucloud/addon/shop/app/dict/goods/EvaluateDict.php b/niucloud/addon/shop/app/dict/goods/EvaluateDict.php
new file mode 100644
index 000000000..1e8b3910f
--- /dev/null
+++ b/niucloud/addon/shop/app/dict/goods/EvaluateDict.php
@@ -0,0 +1,39 @@
+ get_lang('dict_shop_goods_evaluate.audit_no'), // 无需审核
+ self::AUDIT => get_lang('dict_shop_goods_evaluate.audit'), // 待审核
+ self::AUDIT_ADOPT => get_lang('dict_shop_goods_evaluate.audit_adopt'), // 审核通过
+ self::AUDIT_REFUSE => get_lang('dict_shop_goods_evaluate.audit_refuse'), // 审核拒绝
+ ];
+ if (!$type) {
+ return $data;
+ }
+ return $data[ $type ] ?? '';
+ }
+}
diff --git a/niucloud/addon/shop/app/dict/goods/GoodsDict.php b/niucloud/addon/shop/app/dict/goods/GoodsDict.php
new file mode 100644
index 000000000..4d152f179
--- /dev/null
+++ b/niucloud/addon/shop/app/dict/goods/GoodsDict.php
@@ -0,0 +1,143 @@
+ [
+ 'type' => self::REAL,
+ 'name' => get_lang('dict_shop_goods.real'),
+ 'desc' => get_lang('dict_shop_goods.real_desc'),
+ 'path' => '/shop/goods/real_edit',
+ ],
+ self::VIRTUAL => [
+ 'type' => self::VIRTUAL,
+ 'name' => get_lang('dict_shop_goods.virtual'),
+ 'desc' => get_lang('dict_shop_goods.virtual_desc'),
+ 'path' => '/shop/goods/virtual_edit',
+ ]
+ ];
+ if ($type == '') return $list;
+ return $list[ $type ];
+ }
+
+ /**
+ * 批量设置
+ * @param $type
+ * @return array|mixed|string
+ */
+ public static function getBatchSetDict($type = '')
+ {
+ $data = [
+ self::LABEL => get_lang('dict_shop_goods_batch_set.label'),
+ self::SERVICE => get_lang('dict_shop_goods_batch_set.service'),
+ self::VIRTUAL_SALE_NUM => get_lang('dict_shop_goods_batch_set.virtual_sale_num'),
+ self::CATEGORY => get_lang('dict_shop_goods_batch_set.category'),
+ self::BRAND => get_lang('dict_shop_goods_batch_set.brand'),
+ self::POSTER => get_lang('dict_shop_goods_batch_set.poster'),
+ self::GIFT => get_lang('dict_shop_goods_batch_set.gift'),
+ self::DELIVERY => get_lang('dict_shop_goods_batch_set.delivery'),
+ self::STOCK => get_lang('dict_shop_goods_batch_set.stock'),
+ self::MEMBER_DISCOUNT => get_lang('dict_shop_goods_batch_set.member_discount'),
+ self::DIY_FORM => get_lang('dict_shop_goods_batch_set.diy_form'),
+ self::DIY_DETAIL => get_lang('dict_shop_goods_batch_set.diy_detail'),
+ ];
+ if (!$type) {
+ return $data;
+ }
+ return $data[ $type ] ?? '';
+ }
+
+ /**
+ * 商品排序展示配置
+ * @param $sort_type
+ * @return array|mixed|string
+ */
+ public static function getSortTypeConfig($sort_type = '')
+ {
+ $data = [
+ self::SORT_TYPE_ASC => get_lang('dict_shop_goods_sort_config.asc'),
+ self::SORT_TYPE_DESC => get_lang('dict_shop_goods_sort_config.desc'),
+ ];
+ if (!$sort_type) {
+ return $data;
+ }
+ return $data[ $sort_type ] ?? '';
+ }
+ /**
+ * 商品排序展示配置
+ * @param $sort_type
+ * @return array|mixed|string
+ */
+ public static function getSortColumnConfig($sort_type = '')
+ {
+ $data = [
+ self::SORT_COLUMN_SORT => get_lang('dict_shop_goods_sort_config.sort'),
+ self::SORT_COLUMN_PRICE => get_lang('dict_shop_goods_sort_config.price'),
+ self::SORT_COLUMN_SALE_NUM => get_lang('dict_shop_goods_sort_config.sale_num'),
+ self::SORT_COLUMN_CREATE_TIME => get_lang('dict_shop_goods_sort_config.create_time'),
+ ];
+ if (!$sort_type) {
+ return $data;
+ }
+ return $data[ $sort_type ] ?? '';
+ }
+}
diff --git a/niucloud/addon/shop/app/dict/goods/LabelDict.php b/niucloud/addon/shop/app/dict/goods/LabelDict.php
new file mode 100644
index 000000000..6b112aa64
--- /dev/null
+++ b/niucloud/addon/shop/app/dict/goods/LabelDict.php
@@ -0,0 +1,20 @@
+ get_lang('dict_shop_goods_rank_rank_type.day'), // 天
+ self::WEEK => get_lang('dict_shop_goods_rank_rank_type.week'), // 周
+ self::MONTH => get_lang('dict_shop_goods_rank_rank_type.month'), // 月
+ self::QUARTER => get_lang('dict_shop_goods_rank_rank_type.quarter'), // 季度
+ ];
+ if (!$type) {
+ return $data;
+ }
+ return $data[ $type ] ?? '';
+ }
+
+ /**
+ * 来源类型
+ * @param $type
+ * @return array|mixed|string
+ */
+ public static function getGoodsSource($type = '')
+ {
+ $data = [
+ self::ALL => get_lang('dict_shop_goods_rank_goods_source.all'), // 全部
+ self::GOODS => get_lang('dict_shop_goods_rank_goods_source.goods'), // 指定商品
+ self::CATEGORY => get_lang('dict_shop_goods_rank_goods_source.category'), // 指定分类
+ self::BRAND => get_lang('dict_shop_goods_rank_goods_source.brand'), // 指定品牌
+ self::LABEL => get_lang('dict_shop_goods_rank_goods_source.label'), // 指定标签
+ ];
+ if (!$type) {
+ return $data;
+ }
+ return $data[ $type ] ?? '';
+ }
+
+ /**
+ * 排序规则
+ * @param $type
+ * @return array|mixed|string
+ */
+ public static function getRuleType($type = '')
+ {
+ $data = [
+ self::SALE => get_lang('dict_shop_goods_rank_rule_type.sale'), // 按销量
+ self::COLLECT => get_lang('dict_shop_goods_rank_rule_type.collect'), // 按收藏数
+ self::EVALUATE => get_lang('dict_shop_goods_rank_rule_type.evaluate'), // 按评价数
+ self::ACCESS => get_lang('dict_shop_goods_rank_rule_type.access'), // 按浏览量
+ ];
+ if (!$type) {
+ return $data;
+ }
+ return $data[ $type ] ?? '';
+ }
+}
diff --git a/niucloud/addon/shop/app/dict/goods/StatisticsDict.php b/niucloud/addon/shop/app/dict/goods/StatisticsDict.php
new file mode 100644
index 000000000..c51726865
--- /dev/null
+++ b/niucloud/addon/shop/app/dict/goods/StatisticsDict.php
@@ -0,0 +1,48 @@
+加入购物车数量 sale_num=商品销量(下单数)pay_num=支付件数 collect_num=收藏数量 pay_money=支付总金额
+ const ACCESS_NUM = 'access_num';
+ const CART_NUM = 'cart_num';
+ const SALE_NUM = 'sale_num';
+ const PAY_NUM = 'pay_num';
+ const COLLECT_NUM = 'collect_num';
+ const PAY_MONEY = 'pay_money';
+ const GOODS_VISIT_MEMBER_COUNT = 'goods_visit_member_count';
+
+ /**
+ * 排行周期
+ * @param $type
+ * @return array|mixed|string
+ */
+ public static function getType($type = '')
+ {
+ $data = [
+ self::ACCESS_NUM => get_lang('dict_shop_goods_statistics_type.access_num'), // 访问次数(浏览量)
+ self::GOODS_VISIT_MEMBER_COUNT => get_lang('dict_shop_goods_statistics_type.goods_visit_member_count'), // 访客数
+ self::CART_NUM => get_lang('dict_shop_goods_statistics_type.cart_num'), // 加入购物车数量
+ self::SALE_NUM => get_lang('dict_shop_goods_statistics_type.sale_num'), // 商品销量(下单数)
+ self::PAY_NUM => get_lang('dict_shop_goods_statistics_type.pay_num'), // 支付件数
+ self::PAY_MONEY => get_lang('dict_shop_goods_statistics_type.pay_money'), // 支付总金额
+ self::COLLECT_NUM => get_lang('dict_shop_goods_statistics_type.collect_num'), // 收藏数量
+ ];
+ if (!$type) {
+ return $data;
+ }
+ return $data[ $type ] ?? '';
+ }
+
+}
diff --git a/niucloud/addon/shop/app/dict/member/account_change_type.php b/niucloud/addon/shop/app/dict/member/account_change_type.php
new file mode 100644
index 000000000..7ba3b8b7c
--- /dev/null
+++ b/niucloud/addon/shop/app/dict/member/account_change_type.php
@@ -0,0 +1,115 @@
+ [
+ //兑换订单
+ 'account_point_exchange_close' => [
+ //名称
+ 'name' => get_lang('dict_member.account_point_exchange_close'),
+ //是否增加
+ 'inc' => 0,
+ //是否减少
+ 'dec' => 1,
+ ],
+ //兑换订单关闭
+ 'account_point_exchange_order' => [
+ //名称
+ 'name' => get_lang('dict_member.account_point_exchange_order'),
+ //是否增加
+ 'inc' => 1,
+ //是否减少
+ 'dec' => 0,
+ ],
+ //兑换订单售后
+ 'account_point_exchange_refund' => [
+ //名称
+ 'name' => get_lang('dict_member.account_point_exchange_refund'),
+ //是否增加
+ 'inc' => 1,
+ //是否减少
+ 'dec' => 0,
+ ],
+ //消费奖励
+ 'consume_reward' => [
+ //名称
+ 'name' => get_lang('dict_member.account_point_consume_reward'),
+ //是否增加
+ 'inc' => 1,
+ //是否减少
+ 'dec' => 0,
+ ],
+ //满减送活动赠品发放
+ 'manjian_gift_give' => [
+ //名称
+ 'name' => get_lang('dict_member.account_point_manjian_gift_give'),
+ //是否增加
+ 'inc' => 1,
+ //是否减少
+ 'dec' => 0,
+ ],
+ //满减送活动赠品退还
+ 'manjian_gift_back' => [
+ //名称
+ 'name' => get_lang('dict_member.account_point_manjian_gift_back'),
+ //是否增加
+ 'inc' => 0,
+ //是否减少
+ 'dec' => 1,
+ ],
+ //会员充值赠品发放
+ 'recharge' => [
+ //名称
+ 'name' => get_lang('dict_member.recharge_point_give'),
+ //是否增加
+ 'inc' => 1,
+ //是否减少
+ 'dec' => 0,
+ //是否累增
+ 'is_change_get' => 1,
+ ],
+ //种草奖励发放
+ 'sow_community' => [
+ //名称
+ 'name' => get_lang('dict_member.account_point_sow_community_settle_reward'),
+ //是否增加
+ 'inc' => 1,
+ //是否减少
+ 'dec' => 0,
+ //是否累增
+ 'is_change_get' => 1,
+ ]
+ ],
+ MemberAccountTypeDict::BALANCE => [
+ //满减送活动赠品发放
+ 'manjian_gift_give' => [
+ //名称
+ 'name' => get_lang('dict_member.account_balance_manjian_gift_give'),
+ //是否增加
+ 'inc' => 1,
+ //是否减少
+ 'dec' => 0,
+ ],
+ //满减送活动赠品退还
+ 'manjian_gift_back' => [
+ //名称
+ 'name' => get_lang('dict_member.account_balance_manjian_gift_back'),
+ //是否增加
+ 'inc' => 0,
+ //是否减少
+ 'dec' => 1,
+ ],
+ //种草奖励发放
+ 'sow_community' => [
+ //名称
+ 'name' => get_lang('dict_member.account_balance_sow_community_settle_reward'),
+ //是否增加
+ 'inc' => 1,
+ //是否减少
+ 'dec' => 0,
+ //是否累增
+ 'is_change_get' => 1,
+ ]
+ ]
+];
diff --git a/niucloud/addon/shop/app/dict/member/benefits.php b/niucloud/addon/shop/app/dict/member/benefits.php
new file mode 100644
index 000000000..b48a429f6
--- /dev/null
+++ b/niucloud/addon/shop/app/dict/member/benefits.php
@@ -0,0 +1,22 @@
+ [
+ 'key' => 'shop_free_shipping',
+ 'name' => '包邮', // 权益名称
+ 'desc' => '商品购买时可享受免邮服务', // 权益说明
+ 'component' => '/src/addon/shop/views/member/components/benefits-free-shipping.vue',
+ "content" => [
+ 'admin' => function($config) {
+ return '下单享受包邮';
+ },
+ 'member_level' => function($config) {
+ return [
+ 'title' => '商品包邮',
+ 'desc' => '下单免运费',
+ 'icon' => '/static/resource/images/member/benefits/benefits_pinkage.png'
+ ];
+ }
+ ]
+ ]
+];
diff --git a/niucloud/addon/shop/app/dict/member/gift.php b/niucloud/addon/shop/app/dict/member/gift.php
new file mode 100644
index 000000000..0dc7103e1
--- /dev/null
+++ b/niucloud/addon/shop/app/dict/member/gift.php
@@ -0,0 +1,91 @@
+ [
+ 'key' => 'shop_coupon',
+ 'name' => '优惠券', // 礼包名称
+ 'desc' => '发放优惠券', // 礼包说明
+ 'component' => '/src/addon/shop/views/member/components/gift-coupon.vue',
+ // 礼包发放调用方法
+ 'grant' => function ($member_id, $config) {
+ if (!empty($config[ 'coupon_id' ])) {
+ $service = new \addon\shop\app\service\core\coupon\CoreCouponMemberService();
+ foreach ($config[ 'coupon_id' ] as $coupon_id) {
+ if (!isset($config[ 'coupon_list' ][ 'id_' . $coupon_id ])) continue;
+ $service->sendCoupon($member_id, $coupon_id, $config[ 'coupon_list' ][ 'id_' . $coupon_id ]);
+ }
+ }
+ },
+ "content" => [
+ // 管理端
+ 'admin' => function ($config) {
+ if (empty($config[ 'coupon_id' ])) {
+ return '';
+ }
+ $content = [];
+ $model = ( new addon\shop\app\model\coupon\Coupon() );
+ $coupon_list = $model->where([ [ 'id', 'in', $config[ 'coupon_id' ] ] ])->field('id,title')->select()->toArray();
+ if (!empty($coupon_list)) {
+ foreach ($coupon_list as $item) {
+ $content[] = $item[ 'title' ] . '*' . $config[ 'coupon_list' ][ 'id_' . $item[ 'id' ] ];
+ }
+ }
+ return implode(',', $content);
+ },
+ // 会员等级
+ 'member_level' => function ($config) {
+ if (empty($config[ 'coupon_id' ])) {
+ return '';
+ }
+ $content = [];
+ $model = ( new addon\shop\app\model\coupon\Coupon() );
+ $coupon_list = $model->where([ [ 'id', 'in', $config[ 'coupon_id' ] ] ])->field('id,price')->select()->toArray();
+ if (!empty($coupon_list)) {
+ foreach ($coupon_list as $item) {
+ $content[] = [
+ 'text' => round($item[ 'price' ]) . "元优惠券",
+ 'background' => '/addon/shop/gift/gift_coupon_bg.png'
+ ];
+ }
+ }
+ return $content;
+ },
+ // 会员签到(日签)
+ 'member_sign' => function ($config) {
+ if (empty($config[ 'coupon_id' ])) {
+ return [];
+ }
+ $content = [];
+ $model = ( new addon\shop\app\model\coupon\Coupon() );
+ $coupon_list = $model->where([ [ 'id', 'in', $config[ 'coupon_id' ] ] ])->field('id,price')->select()->toArray();
+ if (!empty($coupon_list)) {
+ foreach ($coupon_list as $item) {
+ $content[] = [
+ 'text' => round($item[ 'price' ]) . "元优惠券",
+ 'icon' => '/addon/shop/sign/coupon.png'
+ ];
+ }
+ }
+ return $content;
+ },
+ // 会员签到(连签)
+ 'member_sign_continue' => function ($config) {
+ if (empty($config[ 'coupon_id' ])) {
+ return [];
+ }
+ $content = [];
+ $model = ( new addon\shop\app\model\coupon\Coupon() );
+ $coupon_list = $model->where([ [ 'id', 'in', $config[ 'coupon_id' ] ] ])->field('id,price')->select()->toArray();
+ if (!empty($coupon_list)) {
+ foreach ($coupon_list as $item) {
+ $content[] = [
+ 'text' => round($item[ 'price' ]) . "元优惠券",
+ 'icon' => '/addon/shop/sign/coupon01.png'
+ ];
+ }
+ }
+ return $content;
+ }
+ ]
+ ]
+];
diff --git a/niucloud/addon/shop/app/dict/member/growth_rule.php b/niucloud/addon/shop/app/dict/member/growth_rule.php
new file mode 100644
index 000000000..5f1c27dc8
--- /dev/null
+++ b/niucloud/addon/shop/app/dict/member/growth_rule.php
@@ -0,0 +1,57 @@
+ [
+ 'key' => 'shop_buy_goods',
+ 'name' => '购买商品',
+ 'desc' => '订单交易成功后按订单交易金额发放成长值',
+ 'component' => '/src/addon/shop/views/member/components/growth-rule-buygoods.vue',
+ 'calculate' => function (array $config, array $data) {
+ $order_money = (float)($data['order_money'] ?? 0);
+ if ($order_money <= 0) return 0;
+ $growth = ((float)$config['money'] * (float)$config['growth']);
+ if ($growth <= 0) return 0;
+ return (int) round($order_money / $config[ 'money' ] * $config[ 'growth' ]);
+
+ },
+ 'content' => [
+ 'admin' => function ($config) {
+ return "购买商品可获得{$config['growth']}成长值/{$config['money']}元";
+ },
+ 'task' => function ($config) {
+ return [
+ 'icon' => '/addon/shop/rule/growth-rule-cart.png',
+ 'title' => '购买商品',
+ 'desc' => "购买商品可获得{$config['growth']}成长值/{$config['money']}元",
+ 'button' => [
+ 'text' => '去购买',
+ 'wap_redirect' => '/addon/shop/pages/index'
+ ]
+ ];
+ }
+ ]
+ ],
+ 'shop_buy_order' => [
+ 'key' => 'shop_buy_order',
+ 'name' => '完成下单',
+ 'desc' => '订单交易成功后发放成长值',
+ 'component' => '/src/addon/shop/views/member/components/growth-rule-buyorder.vue',
+ 'calculate' => '', // 计算成长值 可以是匿名函数 也可以是类
+ 'content' => [
+ 'admin' => function ($config) {
+ return "订单交易成功后可获得{$config['growth']}成长值/单";
+ },
+ 'task' => function ($config) {
+ return [
+ 'icon' => '/addon/shop/rule/growth-rule-buy.png',
+ 'title' => '完成下单',
+ 'desc' => "订单交易成功后可获得{$config['growth']}成长值/单",
+ 'button' => [
+ 'text' => '去下单',
+ 'wap_redirect' => '/addon/shop/pages/index'
+ ]
+ ];
+ }
+ ]
+ ],
+];
diff --git a/niucloud/addon/shop/app/dict/member/point_rule.php b/niucloud/addon/shop/app/dict/member/point_rule.php
new file mode 100644
index 000000000..2820d3e64
--- /dev/null
+++ b/niucloud/addon/shop/app/dict/member/point_rule.php
@@ -0,0 +1,48 @@
+ [
+ 'shop_buy_goods' => [
+ 'key' => 'shop_buy_goods',
+ 'name' => '购买商品',
+ 'desc' => '订单交易成功后按订单交易金额发放积分',
+ 'component' => '/src/addon/shop/views/member/components/point-rule-buygoods.vue',
+ 'calculate' => function (array $config, array $data) {
+ $order_money = (float)($data['order_money'] ?? 0);
+ if ($order_money <= 0) return 0;
+ $point = ((float)$config['money'] * (float)$config['point']);
+ if ($point <= 0) return 0;
+ return (int) round($order_money / $config[ 'money' ] * $config[ 'point' ]);
+ },
+ 'content' => [
+ 'admin' => function ($config) {
+ return "购买商品可获得{$config['point']}积分/{$config['money']}元";
+ },
+ 'task' => function ($config) {
+ return [
+ 'icon' => '/addon/shop/rule/growth-rule-cart.png',
+ 'title' => '购买商品',
+ 'desc' => "每消费{$config['money']}元,可获得{$config['point']}积分",
+ 'button' => [
+ 'text' => '去购买',
+ 'wap_redirect' => '/addon/shop/pages/index'
+ ]
+ ];
+ }
+ ]
+ ],
+ ],
+ 'consume' => [
+// 'shop_order_deduction' => [
+// 'key' => 'shop_order_deduction',
+// 'name' => '积分抵现',
+// 'desc' => '订单交易时积分可抵部分现金',
+// 'component' => '/src/addon/shop/views/member/components/point-rule-orderdeduction.vue',
+// 'content' => [
+// 'admin' => function($config) {
+// return "订单交易时{$config['point']}积分可抵{$config['money']}元";
+// }
+// ]
+// ]
+ ]
+];
diff --git a/niucloud/addon/shop/app/dict/menu/admin.php b/niucloud/addon/shop/app/dict/menu/admin.php
new file mode 100644
index 000000000..5fa7e0802
--- /dev/null
+++ b/niucloud/addon/shop/app/dict/menu/admin.php
@@ -0,0 +1,2403 @@
+ '商城系统',
+ 'menu_key' => 'shop',
+ 'menu_short_name' => '商城',
+ 'parent_key' => '',
+ 'menu_type' => '0',
+ 'icon' => 'iconfont iconshangchengshequ',
+ 'api_url' => '',
+ 'router_path' => 'shop/index',
+ 'view_path' => '',
+ 'methods' => '',
+ 'sort' => '110',
+ 'status' => '1',
+ 'is_show' => '1',
+ 'children' => [
+ [
+ 'menu_name' => '概况',
+ 'menu_key' => 'shop_index',
+ 'menu_short_name' => '概况',
+ 'menu_type' => '1',
+ 'icon' => 'iconfont icongaikuang1',
+ 'api_url' => 'shop/index',
+ 'router_path' => 'shop/index',
+ 'view_path' => 'index/index',
+ 'methods' => 'get',
+ 'sort' => '100',
+ 'status' => '1',
+ 'is_show' => '1',
+ ],
+ [
+ 'menu_name' => '商品管理',
+ 'menu_key' => 'shop_goods',
+ 'menu_short_name' => '商品',
+ 'menu_type' => '0',
+ 'icon' => 'iconfont iconshangpinguanli1',
+ 'api_url' => '',
+ 'router_path' => 'shop/goods/list',
+ 'view_path' => '',
+ 'methods' => 'get',
+ 'sort' => '95',
+ 'status' => '1',
+ 'is_show' => '1',
+ 'children' => [
+ [
+ 'menu_name' => '商品列表',
+ 'menu_key' => 'shop_goods_list',
+ 'menu_short_name' => '商品列表',
+ 'menu_type' => '1',
+ 'icon' => 'iconfont iconshangpinliebiao1',
+ 'api_url' => 'shop/goods',
+ 'router_path' => 'shop/goods/list',
+ 'view_path' => 'goods/list',
+ 'methods' => 'get',
+ 'sort' => '100',
+ 'status' => '1',
+ 'is_show' => '1',
+ ],
+ [
+ 'menu_name' => '商品分类',
+ 'menu_key' => 'shop_goods_category_list',
+ 'menu_short_name' => '商品分类',
+ 'menu_type' => '1',
+ 'icon' => 'iconfont iconshangpinfenlei',
+ 'api_url' => 'shop/goods/category',
+ 'router_path' => 'shop/goods/category',
+ 'view_path' => 'goods/category',
+ 'methods' => 'get',
+ 'sort' => '99',
+ 'status' => '1',
+ 'is_show' => '1',
+ 'children' => [
+ [
+ 'menu_name' => '商品分类添加',
+ 'menu_key' => 'shop_goods_category_add',
+ 'menu_short_name' => '商品分类添加',
+ 'menu_type' => '2',
+ 'icon' => '',
+ 'api_url' => 'shop/goods/category',
+ 'router_path' => '',
+ 'view_path' => '',
+ 'methods' => 'post',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ [
+ 'menu_name' => '商品分类编辑',
+ 'menu_key' => 'shop_goods_category_edit',
+ 'menu_short_name' => '商品分类编辑',
+ 'menu_type' => '2',
+ 'icon' => '',
+ 'api_url' => 'shop/goods/category/',
+ 'router_path' => '',
+ 'view_path' => '',
+ 'methods' => 'put',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ [
+ 'menu_name' => '商品分类删除',
+ 'menu_key' => 'shop_goods_category_delete',
+ 'menu_short_name' => '商品分类删除',
+ 'menu_type' => '2',
+ 'icon' => '',
+ 'api_url' => 'shop/goods/category/',
+ 'router_path' => '',
+ 'view_path' => '',
+ 'methods' => 'delete',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ [
+ 'menu_name' => '商品分类拖拽排序',
+ 'menu_key' => 'shop_goods_category_sort',
+ 'menu_short_name' => '商品分类拖拽排序',
+ 'menu_type' => '2',
+ 'icon' => '',
+ 'api_url' => 'shop/goods/category/update',
+ 'router_path' => '',
+ 'view_path' => '',
+ 'methods' => 'post',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ ],
+ ],
+ [
+ 'menu_name' => '分类设置',
+ 'menu_key' => 'shop_goods_category_config',
+ 'menu_short_name' => '分类设置',
+ 'menu_type' => '1',
+ 'icon' => 'iconfont iconfenleishezhi',
+ 'api_url' => '',
+ 'router_path' => 'shop/goods/category/config',
+ 'view_path' => 'goods/category_config',
+ 'methods' => '',
+ 'sort' => '88',
+ 'status' => '1',
+ 'is_show' => '0',
+ 'children' => [
+ [
+ 'menu_name' => '分类设置编辑',
+ 'menu_key' => 'shop_goods_category_config_set',
+ 'menu_short_name' => '分类设置编辑',
+ 'menu_type' => '2',
+ 'icon' => '',
+ 'api_url' => 'shop/goods/category/config',
+ 'router_path' => '',
+ 'view_path' => '',
+ 'methods' => 'post',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ ],
+ ],
+ [
+ 'menu_name' => '商品标签分组',
+ 'menu_key' => 'shop_goods_label_group_list',
+ 'menu_short_name' => '商品标签分组',
+ 'menu_type' => '1',
+ 'icon' => 'iconfont iconshangpinbiaoqian',
+ 'api_url' => 'shop/goods/label/group',
+ 'router_path' => 'shop/goods/label/group',
+ 'view_path' => 'goods/label_group_list',
+ 'methods' => 'get',
+ 'sort' => '88',
+ 'status' => '1',
+ 'is_show' => '0',
+ 'children' => [
+ [
+ 'menu_name' => '商品标签分组添加',
+ 'menu_key' => 'shop_goods_label_group_add',
+ 'menu_short_name' => '商品标签分组添加',
+ 'menu_type' => '2',
+ 'icon' => '',
+ 'api_url' => 'shop/goods/label/group',
+ 'router_path' => '',
+ 'view_path' => '',
+ 'methods' => 'post',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ [
+ 'menu_name' => '商品标签分组编辑',
+ 'menu_key' => 'shop_goods_label_group_edit',
+ 'menu_short_name' => '商品标签分组编辑',
+ 'menu_type' => '2',
+ 'icon' => '',
+ 'api_url' => 'shop/goods/label/group/',
+ 'router_path' => '',
+ 'view_path' => '',
+ 'methods' => 'put',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ [
+ 'menu_name' => '商品标签分组删除',
+ 'menu_key' => 'shop_goods_label_group_delete',
+ 'menu_short_name' => '商品标签分组删除',
+ 'menu_type' => '2',
+ 'icon' => '',
+ 'api_url' => 'shop/goods/label/group/',
+ 'router_path' => '',
+ 'view_path' => '',
+ 'methods' => 'delete',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ ],
+ ],
+ [
+ 'menu_name' => '商品标签',
+ 'menu_key' => 'shop_goods_label_list',
+ 'menu_short_name' => '商品标签',
+ 'menu_type' => '1',
+ 'icon' => 'iconfont iconshangpinbiaoqian',
+ 'api_url' => 'shop/goods/label',
+ 'router_path' => 'shop/goods/label',
+ 'view_path' => 'goods/label_list',
+ 'methods' => 'get',
+ 'sort' => '98',
+ 'status' => '1',
+ 'is_show' => '1',
+ 'children' => [
+ [
+ 'menu_name' => '商品标签添加',
+ 'menu_key' => 'shop_goods_label_add',
+ 'menu_short_name' => '商品标签添加',
+ 'menu_type' => '2',
+ 'icon' => '',
+ 'api_url' => 'shop/goods/label',
+ 'router_path' => '',
+ 'view_path' => '',
+ 'methods' => 'post',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ [
+ 'menu_name' => '商品标签编辑',
+ 'menu_key' => 'shop_goods_label_edit',
+ 'menu_short_name' => '商品标签编辑',
+ 'menu_type' => '2',
+ 'icon' => '',
+ 'api_url' => 'shop/goods/label/',
+ 'router_path' => '',
+ 'view_path' => '',
+ 'methods' => 'put',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ [
+ 'menu_name' => '商品标签删除',
+ 'menu_key' => 'shop_goods_label_delete',
+ 'menu_short_name' => '商品标签删除',
+ 'menu_type' => '2',
+ 'icon' => '',
+ 'api_url' => 'shop/goods/label/',
+ 'router_path' => '',
+ 'view_path' => '',
+ 'methods' => 'delete',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ [
+ 'menu_name' => '商品标签复制',
+ 'menu_key' => 'shop_goods_label_copy',
+ 'menu_short_name' => '商品标签复制',
+ 'menu_type' => '2',
+ 'icon' => '',
+ 'api_url' => 'shop/goods/label/copy/',
+ 'router_path' => '',
+ 'view_path' => '',
+ 'methods' => 'post',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ ],
+ ],
+ [
+ 'menu_name' => '商品品牌',
+ 'menu_key' => 'shop_goods_brand_list',
+ 'menu_short_name' => '商品品牌',
+ 'menu_type' => '1',
+ 'icon' => 'iconfont iconshangpinpinpai',
+ 'api_url' => 'shop/goods/brand',
+ 'router_path' => 'shop/goods/brand',
+ 'view_path' => 'goods/brand_list',
+ 'methods' => 'get',
+ 'sort' => '97',
+ 'status' => '1',
+ 'is_show' => '1',
+ 'children' => [
+ [
+ 'menu_name' => '商品品牌添加',
+ 'menu_key' => 'shop_goods_brand_add',
+ 'menu_short_name' => '商品品牌添加',
+ 'menu_type' => '2',
+ 'icon' => '',
+ 'api_url' => 'shop/goods/brand',
+ 'router_path' => '',
+ 'view_path' => '',
+ 'methods' => 'post',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ [
+ 'menu_name' => '商品品牌编辑',
+ 'menu_key' => 'shop_goods_brand_edit',
+ 'menu_short_name' => '商品品牌编辑',
+ 'menu_type' => '2',
+ 'icon' => '',
+ 'api_url' => 'shop/goods/brand/',
+ 'router_path' => '',
+ 'view_path' => '',
+ 'methods' => 'put',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ [
+ 'menu_name' => '商品品牌删除',
+ 'menu_key' => 'shop_goods_brand_delete',
+ 'menu_short_name' => '商品品牌删除',
+ 'menu_type' => '2',
+ 'icon' => '',
+ 'api_url' => 'shop/goods/brand/',
+ 'router_path' => '',
+ 'view_path' => '',
+ 'methods' => 'delete',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ ],
+ ],
+ [
+ 'menu_name' => '商品服务',
+ 'menu_key' => 'shop_goods_service_list',
+ 'menu_short_name' => '商品服务',
+ 'menu_type' => '1',
+ 'icon' => 'iconfont iconshangpinfuwu',
+ 'api_url' => 'shop/goods/service',
+ 'router_path' => 'shop/goods/service',
+ 'view_path' => 'goods/service',
+ 'methods' => 'get',
+ 'sort' => '96',
+ 'status' => '1',
+ 'is_show' => '1',
+ 'children' => [
+ [
+ 'menu_name' => '商品服务添加',
+ 'menu_key' => 'shop_goods_service_add',
+ 'menu_short_name' => '商品服务添加',
+ 'menu_type' => '2',
+ 'icon' => '',
+ 'api_url' => 'shop/goods/service',
+ 'router_path' => '',
+ 'view_path' => '',
+ 'methods' => 'post',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ [
+ 'menu_name' => '商品服务编辑',
+ 'menu_key' => 'shop_goods_service_edit',
+ 'menu_short_name' => '商品服务编辑',
+ 'menu_type' => '2',
+ 'icon' => '',
+ 'api_url' => 'shop/goods/service/',
+ 'router_path' => '',
+ 'view_path' => '',
+ 'methods' => 'put',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ [
+ 'menu_name' => '商品服务删除',
+ 'menu_key' => 'shop_goods_service_delete',
+ 'menu_short_name' => '商品服务删除',
+ 'menu_type' => '2',
+ 'icon' => '',
+ 'api_url' => 'shop/goods/service/',
+ 'router_path' => '',
+ 'view_path' => '',
+ 'methods' => 'delete',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ ],
+ ],
+ [
+ 'menu_name' => '参数模板',
+ 'menu_key' => 'shop_goods_attr_list',
+ 'menu_short_name' => '参数模板',
+ 'menu_type' => '1',
+ 'icon' => 'iconfont iconshangpinfuwu',
+ 'api_url' => 'shop/goods/attr',
+ 'router_path' => 'shop/goods/attr',
+ 'view_path' => 'goods/attr',
+ 'methods' => 'get',
+ 'sort' => '95',
+ 'status' => '1',
+ 'is_show' => '1',
+ 'children' => [
+ [
+ 'menu_name' => '修改参数模板排序号',
+ 'menu_key' => 'shop_goods_attr_sort_edit',
+ 'menu_short_name' => '修改参数模板排序号',
+ 'menu_type' => '2',
+ 'icon' => '',
+ 'api_url' => 'shop/goods/attr/sort',
+ 'router_path' => '',
+ 'view_path' => '',
+ 'methods' => 'put',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ [
+ 'menu_name' => '修改参数模板名称',
+ 'menu_key' => 'shop_goods_attr_name_edit',
+ 'menu_short_name' => '修改参数模板名称',
+ 'menu_type' => '2',
+ 'icon' => '',
+ 'api_url' => 'shop/goods/attr/attr_name',
+ 'router_path' => '',
+ 'view_path' => '',
+ 'methods' => 'put',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ [
+ 'menu_name' => '修改参数模板值',
+ 'menu_key' => 'shop_goods_attr_value_edit',
+ 'menu_short_name' => '修改参数模板值',
+ 'menu_type' => '2',
+ 'icon' => '',
+ 'api_url' => 'shop/goods/attr/attr_value',
+ 'router_path' => '',
+ 'view_path' => '',
+ 'methods' => 'put',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ ],
+ ],
+ [
+ 'menu_name' => '商品统计',
+ 'menu_key' => 'shop_stat_goods',
+ 'menu_short_name' => '商品统计',
+ 'menu_type' => '1',
+ 'icon' => 'iconfont icona-dingdanliebiao',
+ 'api_url' => 'stat/goods',
+ 'router_path' => 'shop/stat/goods',
+ 'view_path' => 'stat/goods',
+ 'methods' => 'get',
+ 'sort' => '94',
+ 'status' => '1',
+ 'is_show' => '1',
+ ],
+ [
+ 'menu_name' => '商品设置',
+ 'menu_key' => 'shop_goods_search_config',
+ 'menu_short_name' => '搜索设置',
+ 'menu_type' => '1',
+ 'icon' => '',
+ 'api_url' => 'shop/goods/config/search',
+ 'router_path' => 'shop/goods/search_config',
+ 'view_path' => 'goods/search_config',
+ 'methods' => 'post',
+ 'sort' => '93',
+ 'status' => '1',
+ 'is_show' => '1',
+ ],
+ [
+ 'menu_name' => '编码唯一性设置',
+ 'menu_key' => 'shop_goods_unique_config',
+ 'menu_short_name' => '编码唯一性设置',
+ 'menu_type' => '1',
+ 'icon' => '',
+ 'api_url' => 'shop/goods/config/unique',
+ 'router_path' => 'shop/goods/unique_config',
+ 'view_path' => 'goods/unique_config',
+ 'methods' => 'post',
+ 'sort' => '93',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ [
+ 'menu_name' => '商品排序设置',
+ 'menu_key' => 'shop_goods_sort_config',
+ 'menu_short_name' => '排序设置',
+ 'menu_type' => '1',
+ 'icon' => '',
+ 'api_url' => 'shop/goods/config/sort',
+ 'router_path' => 'shop/goods/sort_config',
+ 'view_path' => 'goods/sort_config',
+ 'methods' => 'post',
+ 'sort' => '93',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ [
+ 'menu_name' => '回收站',
+ 'menu_key' => 'shop_goods_recycle_list',
+ 'menu_short_name' => '回收站',
+ 'menu_type' => '1',
+ 'icon' => 'iconfont iconhuishouzhan',
+ 'api_url' => 'shop/goods/recycle',
+ 'router_path' => 'shop/goods/recycle',
+ 'view_path' => 'goods/recycle',
+ 'methods' => 'get',
+ 'sort' => '92',
+ 'status' => '1',
+ 'is_show' => '1',
+ 'children' => [
+ [
+ 'menu_name' => '商品恢复',
+ 'menu_key' => 'shop_goods_recycle',
+ 'menu_short_name' => '商品恢复',
+ 'menu_type' => '2',
+ 'icon' => '',
+ 'api_url' => 'shop/goods/recycle',
+ 'router_path' => '',
+ 'view_path' => '',
+ 'methods' => 'put',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ ],
+ ],
+ [
+ 'menu_name' => '商品添加',
+ 'menu_key' => 'shop_goods_virtual_add',
+ 'menu_short_name' => '商品添加',
+ 'parent_select_key' => 'shop_goods_list',
+ 'menu_type' => '1',
+ 'icon' => '',
+ 'api_url' => 'shop/goods/virtual',
+ 'router_path' => 'shop/goods/virtual_edit',
+ 'view_path' => 'goods/virtual_edit',
+ 'methods' => 'post',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ [
+ 'menu_name' => '商品编辑',
+ 'menu_key' => 'shop_goods_virtual_edit',
+ 'menu_short_name' => '商品编辑',
+ 'parent_select_key' => 'shop_goods_list',
+ 'menu_type' => '1',
+ 'icon' => '',
+ 'api_url' => 'shop/goods/virtual/',
+ 'router_path' => 'shop/goods/virtual_edit',
+ 'view_path' => 'goods/virtual_edit',
+ 'methods' => 'put',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ [
+ 'menu_name' => '商品删除',
+ 'menu_key' => 'shop_goods_delete',
+ 'menu_short_name' => '商品删除',
+ 'parent_select_key' => 'shop_goods_list',
+ 'menu_type' => '2',
+ 'icon' => '',
+ 'api_url' => 'shop/goods/delete',
+ 'router_path' => '',
+ 'view_path' => '',
+ 'methods' => 'put',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ [
+ 'menu_name' => '商品排序号修改',
+ 'menu_key' => 'shop_goods_sort_edit',
+ 'menu_short_name' => '商品排序号修改',
+ 'parent_select_key' => 'shop_goods_list',
+ 'menu_type' => '2',
+ 'icon' => '',
+ 'api_url' => 'shop/goods/sort',
+ 'router_path' => '',
+ 'view_path' => '',
+ 'methods' => 'put',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ [
+ 'menu_name' => '商品上下架状态修改',
+ 'menu_key' => 'shop_goods_status_edit',
+ 'menu_short_name' => '商品上下架状态修改',
+ 'parent_select_key' => 'shop_goods_list',
+ 'menu_type' => '2',
+ 'icon' => '',
+ 'api_url' => 'shop/goods/status',
+ 'router_path' => '',
+ 'view_path' => '',
+ 'methods' => 'put',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ [
+ 'menu_name' => '商品复制',
+ 'menu_key' => 'shop_goods_copy',
+ 'menu_short_name' => '商品复制',
+ 'parent_select_key' => 'shop_goods_list',
+ 'menu_type' => '2',
+ 'icon' => '',
+ 'api_url' => 'shop/goods/copy/',
+ 'router_path' => '',
+ 'view_path' => '',
+ 'methods' => 'put',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ [
+ 'menu_name' => '商品规格列表库存编辑',
+ 'menu_key' => 'shop_goods_sku_stock_edit',
+ 'menu_short_name' => '商品规格列表库存编辑',
+ 'parent_select_key' => 'shop_goods_list',
+ 'menu_type' => '2',
+ 'icon' => '',
+ 'api_url' => 'shop/goods/sku/stock',
+ 'router_path' => '',
+ 'view_path' => '',
+ 'methods' => 'put',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ [
+ 'menu_name' => '商品规格列表价格编辑',
+ 'menu_key' => 'shop_goods_sku_price_edit',
+ 'menu_short_name' => '商品规格列表价格编辑',
+ 'parent_select_key' => 'shop_goods_list',
+ 'menu_type' => '2',
+ 'icon' => '',
+ 'api_url' => 'shop/goods/sku/price',
+ 'router_path' => '',
+ 'view_path' => '',
+ 'methods' => 'put',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ [
+ 'menu_name' => '商品规格列表会员价格编辑',
+ 'menu_key' => 'shop_goods_sku_member_price_edit',
+ 'menu_short_name' => '商品规格列表会员价格编辑',
+ 'parent_select_key' => 'shop_goods_list',
+ 'menu_type' => '2',
+ 'icon' => '',
+ 'api_url' => 'shop/goods/sku/member_price',
+ 'router_path' => '',
+ 'view_path' => '',
+ 'methods' => 'put',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ [
+ 'menu_name' => '删除参数模板',
+ 'menu_key' => 'shop_goods_attr_delete',
+ 'menu_short_name' => '删除参数模板',
+ 'parent_select_key' => 'shop_goods_attr_list',
+ 'menu_type' => '2',
+ 'icon' => '',
+ 'api_url' => 'shop/goods/attr/',
+ 'router_path' => '',
+ 'view_path' => '',
+ 'methods' => 'delete',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ [
+ 'menu_name' => '编辑参数模板',
+ 'menu_key' => 'shop_goods_attr_edit',
+ 'menu_short_name' => '编辑参数模板',
+ 'parent_select_key' => 'shop_goods_attr_list',
+ 'menu_type' => '1',
+ 'icon' => '',
+ 'api_url' => 'shop/goods/attr/',
+ 'router_path' => 'shop/goods/attr_edit',
+ 'view_path' => 'goods/attr_edit',
+ 'methods' => 'put',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ [
+ 'menu_name' => '添加参数模板',
+ 'menu_key' => 'shop_goods_attr_add',
+ 'menu_short_name' => '添加参数模板',
+ 'parent_select_key' => 'shop_goods_attr_list',
+ 'menu_type' => '1',
+ 'icon' => '',
+ 'api_url' => 'shop/goods/attr',
+ 'router_path' => 'shop/goods/attr_edit',
+ 'view_path' => 'goods/attr_edit',
+ 'methods' => 'post',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ [
+ 'menu_name' => '商品添加',
+ 'menu_key' => 'shop_goods_real_add',
+ 'menu_short_name' => '商品添加',
+ 'parent_select_key' => 'shop_goods_list',
+ 'menu_type' => '1',
+ 'icon' => '',
+ 'api_url' => 'shop/goods',
+ 'router_path' => 'shop/goods/real_edit',
+ 'view_path' => 'goods/real_edit',
+ 'methods' => 'post',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ [
+ 'menu_name' => '商品编辑',
+ 'menu_key' => 'shop_goods_real_edit',
+ 'menu_short_name' => '商品编辑',
+ 'parent_select_key' => 'shop_goods_list',
+ 'menu_type' => '1',
+ 'icon' => '',
+ 'api_url' => 'shop/goods/',
+ 'router_path' => 'shop/goods/real_edit',
+ 'view_path' => 'goods/real_edit',
+ 'methods' => 'put',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ ],
+ ],
+ [
+ 'menu_name' => '订单管理',
+ 'menu_key' => 'shop_order',
+ 'menu_short_name' => '订单',
+ 'menu_type' => '0',
+ 'icon' => 'iconfont icondingdanguanli',
+ 'api_url' => '',
+ 'router_path' => 'shop/order/index',
+ 'view_path' => '',
+ 'methods' => 'get',
+ 'sort' => '90',
+ 'status' => '1',
+ 'is_show' => '1',
+ 'children' => [
+ [
+ 'menu_name' => '商城订单',
+ 'menu_key' => 'shop_order_list',
+ 'menu_short_name' => '商城订单',
+ 'menu_type' => '1',
+ 'icon' => 'iconfont icona-dingdanliebiao',
+ 'api_url' => 'shop/order/list',
+ 'router_path' => 'shop/order/index',
+ 'view_path' => 'order/list',
+ 'methods' => 'get',
+ 'sort' => '100',
+ 'status' => '1',
+ 'is_show' => '1',
+ 'children' => [
+ [
+ 'menu_name' => '订单关闭',
+ 'menu_key' => 'shop_order_close',
+ 'menu_short_name' => '订单关闭',
+ 'menu_type' => '2',
+ 'icon' => '',
+ 'api_url' => 'shop/order/close/',
+ 'router_path' => '',
+ 'view_path' => '',
+ 'methods' => 'put',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ [
+ 'menu_name' => '订单改价',
+ 'menu_key' => 'shop_order_edit_price',
+ 'menu_short_name' => '订单改价',
+ 'menu_type' => '2',
+ 'icon' => '',
+ 'api_url' => 'shop/order/edit_price',
+ 'router_path' => '',
+ 'view_path' => '',
+ 'methods' => 'put',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ [
+ 'menu_name' => '订单配送修改',
+ 'menu_key' => 'shop_order_edit_delivery',
+ 'menu_short_name' => '订单配送修改',
+ 'menu_type' => '2',
+ 'icon' => '',
+ 'api_url' => 'shop/order/edit_delivery',
+ 'router_path' => '',
+ 'view_path' => '',
+ 'methods' => 'put',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ [
+ 'menu_name' => '订单发货',
+ 'menu_key' => 'shop_order_delivery',
+ 'menu_short_name' => '订单发货',
+ 'menu_type' => '2',
+ 'icon' => '',
+ 'api_url' => 'shop/order/delivery',
+ 'router_path' => '',
+ 'view_path' => '',
+ 'methods' => 'put',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ [
+ 'menu_name' => '订单项发货',
+ 'menu_key' => 'shop_order_goods_delivery',
+ 'menu_short_name' => '订单项发货',
+ 'menu_type' => '2',
+ 'icon' => '',
+ 'api_url' => 'shop/order/goods/delivery/',
+ 'router_path' => '',
+ 'view_path' => '',
+ 'methods' => 'put',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ [
+ 'menu_name' => '商家留言',
+ 'menu_key' => 'shop_order_remark',
+ 'menu_short_name' => '商家留言',
+ 'menu_type' => '2',
+ 'icon' => '',
+ 'api_url' => 'shop/order/shop_remark',
+ 'router_path' => '',
+ 'view_path' => '',
+ 'methods' => 'put',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ [
+ 'menu_name' => '订单完成',
+ 'menu_key' => 'shop_order_finish',
+ 'menu_short_name' => '订单完成',
+ 'menu_type' => '2',
+ 'icon' => '',
+ 'api_url' => 'shop/order/finish/',
+ 'router_path' => '',
+ 'view_path' => '',
+ 'methods' => 'put',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ ],
+ ],
+ [
+ 'menu_name' => '退款售后',
+ 'menu_key' => 'shop_order_refund',
+ 'menu_short_name' => '退款售后',
+ 'menu_type' => '1',
+ 'icon' => 'iconfont icondingdanweiquan',
+ 'api_url' => '',
+ 'router_path' => 'shop/order/refund',
+ 'view_path' => 'order/refund',
+ 'methods' => 'get',
+ 'sort' => '99',
+ 'status' => '1',
+ 'is_show' => '1',
+ 'children' => [
+ [
+ 'menu_name' => '退款审核',
+ 'menu_key' => 'shop_order_refund_audit',
+ 'menu_short_name' => '退款审核',
+ 'menu_type' => '2',
+ 'icon' => '',
+ 'api_url' => 'shop/order/refund/audit/',
+ 'router_path' => '',
+ 'view_path' => '',
+ 'methods' => 'put',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ [
+ 'menu_name' => '退款收货审核',
+ 'menu_key' => 'shop_order_refund_delivery',
+ 'menu_short_name' => '退款收货审核',
+ 'menu_type' => '2',
+ 'icon' => '',
+ 'api_url' => 'shop/order/refund/delivery/',
+ 'router_path' => '',
+ 'view_path' => '',
+ 'methods' => 'put',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ ],
+ ],
+ [
+ 'menu_name' => '批量发货',
+ 'menu_key' => 'shop_order_batch_delivery',
+ 'menu_short_name' => '批量发货',
+ 'menu_type' => '1',
+ 'icon' => 'iconfont icona-dingdanliebiao',
+ 'api_url' => '',
+ 'router_path' => 'shop/order/batch/delivery',
+ 'view_path' => 'order/batch_delivery',
+ 'methods' => 'get',
+ 'sort' => '98',
+ 'status' => '1',
+ 'is_show' => '1',
+ ],
+ [
+ 'menu_name' => '发票管理',
+ 'menu_key' => 'shop_invoice',
+ 'menu_short_name' => '发票管理',
+ 'menu_type' => '1',
+ 'icon' => 'iconfont iconfapiaoguanli',
+ 'api_url' => '',
+ 'router_path' => 'shop/order/invoice',
+ 'view_path' => 'order/invoice',
+ 'methods' => 'get',
+ 'sort' => '97',
+ 'status' => '1',
+ 'is_show' => '1',
+ 'children' => [
+ [
+ 'menu_name' => '开票',
+ 'menu_key' => 'shop_invoice_open',
+ 'menu_short_name' => '开票',
+ 'menu_type' => '2',
+ 'icon' => '',
+ 'api_url' => 'shop/invoice/',
+ 'router_path' => '',
+ 'view_path' => '',
+ 'methods' => 'put',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ ],
+ ],
+ [
+ 'menu_name' => '商品评价',
+ 'menu_key' => 'shop_goods_evaluate',
+ 'menu_short_name' => '商品评价',
+ 'menu_type' => '1',
+ 'icon' => 'iconfont iconshangpinpinglun',
+ 'api_url' => 'shop/goods/evaluate',
+ 'router_path' => 'shop/order/evaluate',
+ 'view_path' => 'goods/evaluate',
+ 'methods' => 'get',
+ 'sort' => '96',
+ 'status' => '1',
+ 'is_show' => '1',
+ 'children' => [
+ [
+ 'menu_name' => '商品评价删除',
+ 'menu_key' => 'shop_goods_evaluate_delete',
+ 'menu_short_name' => '商品评价删除',
+ 'menu_type' => '2',
+ 'icon' => '',
+ 'api_url' => 'shop/goods/evaluate/',
+ 'router_path' => '',
+ 'view_path' => '',
+ 'methods' => 'delete',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ [
+ 'menu_name' => '商品评价回复',
+ 'menu_key' => 'shop_goods_evaluate_reply',
+ 'menu_short_name' => '商品评价回复',
+ 'menu_type' => '2',
+ 'icon' => '',
+ 'api_url' => 'shop/goods/evaluate/reply/',
+ 'router_path' => '',
+ 'view_path' => '',
+ 'methods' => 'put',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ [
+ 'menu_name' => '商品评价通过',
+ 'menu_key' => 'shop_goods_evaluate_adopt',
+ 'menu_short_name' => '商品评价通过',
+ 'menu_type' => '2',
+ 'icon' => '',
+ 'api_url' => 'shop/goods/evaluate/adopt/',
+ 'router_path' => '',
+ 'view_path' => '',
+ 'methods' => 'put',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ [
+ 'menu_name' => '商品评价拒绝',
+ 'menu_key' => 'shop_goods_evaluate_refuse',
+ 'menu_short_name' => '商品评价拒绝',
+ 'menu_type' => '2',
+ 'icon' => '',
+ 'api_url' => 'shop/goods/evaluate/refuse/',
+ 'router_path' => '',
+ 'view_path' => '',
+ 'methods' => 'put',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ [
+ 'menu_name' => '商品评价置顶',
+ 'menu_key' => 'shop_goods_evaluate_topping',
+ 'menu_short_name' => '商品评价置顶',
+ 'menu_type' => '2',
+ 'icon' => '',
+ 'api_url' => 'shop/goods/evaluate/topping/',
+ 'router_path' => '',
+ 'view_path' => '',
+ 'methods' => 'put',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ [
+ 'menu_name' => '商品评价取消置顶',
+ 'menu_key' => 'shop_goods_evaluate_cancel_topping',
+ 'menu_short_name' => '商品评价取消置顶',
+ 'menu_type' => '2',
+ 'icon' => '',
+ 'api_url' => 'shop/goods/evaluate/cancel_topping/',
+ 'router_path' => '',
+ 'view_path' => '',
+ 'methods' => 'put',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ ],
+ ],
+ [
+ 'menu_name' => '订单设置',
+ 'menu_key' => 'shop_config_order',
+ 'menu_short_name' => '订单设置',
+ 'menu_type' => '1',
+ 'icon' => 'iconfont iconjiaoyishezhi',
+ 'api_url' => 'shop/order/config',
+ 'router_path' => 'shop/order/order/config',
+ 'view_path' => 'order/config',
+ 'methods' => '',
+ 'sort' => '95',
+ 'status' => '1',
+ 'is_show' => '1',
+ 'children' => [
+ [
+ 'menu_name' => '订单设置编辑',
+ 'menu_key' => 'shop_config_order_set',
+ 'menu_short_name' => '订单设置编辑',
+ 'menu_type' => '2',
+ 'icon' => '',
+ 'api_url' => 'shop/order/config',
+ 'router_path' => '',
+ 'view_path' => '',
+ 'methods' => 'post',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ ],
+ ],
+ [
+ 'menu_name' => '商家地址库',
+ 'menu_key' => 'shop_address',
+ 'menu_short_name' => '商家地址库',
+ 'menu_type' => '1',
+ 'icon' => 'iconfont iconshangjiadizhiku',
+ 'api_url' => '',
+ 'router_path' => 'shop/order/address',
+ 'view_path' => 'address/list',
+ 'methods' => 'get',
+ 'sort' => '94',
+ 'status' => '1',
+ 'is_show' => '1',
+ 'children' => [
+ [
+ 'menu_name' => '删除商家地址库',
+ 'menu_key' => 'shop_address_delete',
+ 'menu_short_name' => '删除商家地址库',
+ 'menu_type' => '2',
+ 'icon' => '',
+ 'api_url' => 'shop/shop_address/',
+ 'router_path' => '',
+ 'view_path' => '',
+ 'methods' => 'delete',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ ],
+ ],
+ [
+ 'menu_name' => '配送设置',
+ 'menu_key' => 'shop_config_delivery',
+ 'menu_short_name' => '配送设置',
+ 'menu_type' => '1',
+ 'icon' => 'iconfont iconpaisongshezhi',
+ 'api_url' => '',
+ 'router_path' => 'shop/order/delivery',
+ 'view_path' => 'delivery/config',
+ 'methods' => '',
+ 'sort' => '93',
+ 'status' => '1',
+ 'is_show' => '1',
+ 'children' => [
+ [
+ 'menu_name' => '配送设置编辑',
+ 'menu_key' => 'shop_config_delivery_set',
+ 'menu_short_name' => '配送设置编辑',
+ 'menu_type' => '2',
+ 'icon' => '',
+ 'api_url' => 'shop/delivery/setConfig',
+ 'router_path' => '',
+ 'view_path' => '',
+ 'methods' => 'put',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ ],
+ ],
+ [
+ 'menu_name' => '电子面单',
+ 'menu_key' => 'shop_delivery_electronic_sheet',
+ 'menu_short_name' => '电子面单',
+ 'menu_type' => '1',
+ 'icon' => 'iconfont icondiscount',
+ 'api_url' => '',
+ 'router_path' => 'shop/delivery/electronic_sheet',
+ 'view_path' => 'delivery/electronic_sheet',
+ 'methods' => 'get',
+ 'sort' => '92',
+ 'status' => '1',
+ 'is_show' => '1',
+ 'children' => [
+ [
+ 'menu_name' => '删除电子面单模板',
+ 'menu_key' => 'shop_delivery_electronic_sheet_del',
+ 'menu_short_name' => '删除电子面单模板',
+ 'menu_type' => '2',
+ 'icon' => '',
+ 'api_url' => 'shop/electronic_sheet',
+ 'router_path' => '',
+ 'view_path' => '',
+ 'methods' => 'delete',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ ],
+ ],
+ [
+ 'menu_name' => '添加评价',
+ 'menu_key' => 'shop_goods_evaluate_add',
+ 'menu_short_name' => '添加评价',
+ 'parent_select_key' => 'shop_goods_evaluate',
+ 'menu_type' => '1',
+ 'icon' => '',
+ 'api_url' => 'shop/goods/evaluate',
+ 'router_path' => 'shop/order/evaluate/add',
+ 'view_path' => 'goods/evaluate_edit',
+ 'methods' => 'get',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ [
+ 'menu_name' => '添加/编辑地址库',
+ 'menu_key' => 'shop_address_add_edit',
+ 'menu_short_name' => '添加/编辑地址库',
+ 'parent_select_key' => 'shop_address',
+ 'menu_type' => '1',
+ 'icon' => '',
+ 'api_url' => '',
+ 'router_path' => 'shop/order/address/edit',
+ 'view_path' => 'address/edit',
+ 'methods' => 'get',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ 'children' => [
+ [
+ 'menu_name' => '地址库添加',
+ 'menu_key' => 'shop_address_add',
+ 'menu_short_name' => '地址库添加',
+ 'parent_select_key' => 'shop_address',
+ 'menu_type' => '2',
+ 'icon' => '',
+ 'api_url' => 'shop/shop_address',
+ 'router_path' => '',
+ 'view_path' => '',
+ 'methods' => 'post',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ [
+ 'menu_name' => '地址库编辑',
+ 'menu_key' => 'shop_address_edit',
+ 'menu_short_name' => '地址库编辑',
+ 'parent_select_key' => 'shop_address',
+ 'menu_type' => '2',
+ 'icon' => '',
+ 'api_url' => 'shop/shop_address/',
+ 'router_path' => '',
+ 'view_path' => '',
+ 'methods' => 'put',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ ],
+ ],
+ [
+ 'menu_name' => '物流公司',
+ 'menu_key' => 'shop_config_delivery_company',
+ 'menu_short_name' => '物流公司',
+ 'menu_type' => '1',
+ 'icon' => '',
+ 'api_url' => 'shop/delivery/company',
+ 'router_path' => 'shop/order/delivery/company',
+ 'view_path' => 'delivery/company',
+ 'methods' => 'get',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ 'children' => [
+ [
+ 'menu_name' => '物流公司删除',
+ 'menu_key' => 'shop_config_delivery_company_delete',
+ 'menu_short_name' => '物流公司删除',
+ 'menu_type' => '2',
+ 'icon' => '',
+ 'api_url' => 'shop/delivery/company/',
+ 'router_path' => '',
+ 'view_path' => '',
+ 'methods' => 'delete',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ ],
+ ],
+ [
+ 'menu_name' => '添加物流公司',
+ 'menu_key' => 'shop_config_delivery_company_add',
+ 'menu_short_name' => '添加物流公司',
+ 'parent_select_key' => 'shop_config_delivery_company',
+ 'menu_type' => '1',
+ 'icon' => '',
+ 'api_url' => 'shop/delivery/company',
+ 'router_path' => 'shop/order/delivery/company_add',
+ 'view_path' => 'delivery/company_edit',
+ 'methods' => 'post',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ [
+ 'menu_name' => '编辑物流公司',
+ 'menu_key' => 'shop_config_delivery_company_edit',
+ 'menu_short_name' => '编辑物流公司',
+ 'parent_select_key' => 'shop_config_delivery_company',
+ 'menu_type' => '1',
+ 'icon' => '',
+ 'api_url' => 'shop/delivery/company',
+ 'router_path' => 'shop/order/delivery/company_edit',
+ 'view_path' => 'delivery/company_edit',
+ 'methods' => 'put',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ [
+ 'menu_name' => '同城配送',
+ 'menu_key' => 'shop_config_delivery_local',
+ 'menu_short_name' => '同城配送',
+ 'menu_type' => '1',
+ 'icon' => '',
+ 'api_url' => '',
+ 'router_path' => 'shop/order/delivery/local',
+ 'view_path' => 'delivery/local',
+ 'methods' => 'get',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ 'children' => [
+ [
+ 'menu_name' => '同城配送设置',
+ 'menu_key' => 'shop_config_delivery_local_set',
+ 'menu_short_name' => '同城配送设置',
+ 'menu_type' => '2',
+ 'icon' => '',
+ 'api_url' => 'shop/local',
+ 'router_path' => '',
+ 'view_path' => '',
+ 'methods' => 'put',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ ],
+ ],
+ [
+ 'menu_name' => '运费模版',
+ 'menu_key' => 'shop_config_delivery_shipping_template',
+ 'menu_short_name' => '运费模版',
+ 'menu_type' => '1',
+ 'icon' => '',
+ 'api_url' => 'shop/shipping/template',
+ 'router_path' => 'shop/order/shipping/template',
+ 'view_path' => 'delivery/template',
+ 'methods' => 'get',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ 'children' => [
+ [
+ 'menu_name' => '运费模版删除',
+ 'menu_key' => 'shop_config_delivery_shipping_template_delete',
+ 'menu_short_name' => '运费模版列表',
+ 'menu_type' => '2',
+ 'icon' => '',
+ 'api_url' => 'shop/shipping/template/',
+ 'router_path' => '',
+ 'view_path' => '',
+ 'methods' => 'delete',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ ],
+ ],
+ [
+ 'menu_name' => '运费模版添加/编辑',
+ 'menu_key' => 'shop_config_delivery_shipping_template_add_edit',
+ 'menu_short_name' => '运费模版添加/编辑',
+ 'parent_select_key' => 'shop_config_delivery_shipping_template',
+ 'menu_type' => '1',
+ 'icon' => '',
+ 'api_url' => '',
+ 'router_path' => 'shop/order/shipping/template_edit',
+ 'view_path' => 'delivery/template_edit',
+ 'methods' => 'get',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ 'children' => [
+ [
+ 'menu_name' => '运费模版添加',
+ 'menu_key' => 'shop_config_delivery_shipping_template_add',
+ 'menu_short_name' => '运费模版添加',
+ 'menu_type' => '2',
+ 'icon' => '',
+ 'api_url' => 'shop/shipping/template',
+ 'router_path' => '',
+ 'view_path' => '',
+ 'methods' => 'post',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ [
+ 'menu_name' => '运费模版编辑',
+ 'menu_key' => 'shop_config_delivery_shipping_template_edit',
+ 'menu_short_name' => '运费模版编辑',
+ 'menu_type' => '2',
+ 'icon' => '',
+ 'api_url' => 'shop/shipping/template/',
+ 'router_path' => '',
+ 'view_path' => '',
+ 'methods' => 'put',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ ],
+ ],
+ [
+ 'menu_name' => '配送员',
+ 'menu_key' => 'shop_config_delivery_staff',
+ 'menu_short_name' => '配送员',
+ 'parent_select_key' => 'shop_config_delivery',
+ 'menu_type' => '1',
+ 'icon' => '',
+ 'api_url' => '',
+ 'router_path' => 'shop/order/delivery/staff',
+ 'view_path' => 'delivery/staff',
+ 'methods' => '',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ 'children' => [
+ [
+ 'menu_name' => '配送员添加',
+ 'menu_key' => 'shop_config_delivery_staff_add',
+ 'menu_short_name' => '配送员添加',
+ 'menu_type' => '2',
+ 'icon' => '',
+ 'api_url' => 'shop/delivery/staff',
+ 'router_path' => '',
+ 'view_path' => '',
+ 'methods' => 'post',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ [
+ 'menu_name' => '配送员编辑',
+ 'menu_key' => 'shop_config_delivery_staff_edit',
+ 'menu_short_name' => '配送员编辑',
+ 'menu_type' => '2',
+ 'icon' => '',
+ 'api_url' => 'shop/delivery/staff/',
+ 'router_path' => '',
+ 'view_path' => '',
+ 'methods' => 'put',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ [
+ 'menu_name' => '配送员删除',
+ 'menu_key' => 'shop_config_delivery_staff_delete',
+ 'menu_short_name' => '配送员删除',
+ 'menu_type' => '2',
+ 'icon' => '',
+ 'api_url' => 'shop/delivery/staff/',
+ 'router_path' => '',
+ 'view_path' => '',
+ 'methods' => 'delete',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ ],
+ ],
+ [
+ 'menu_name' => '订单详情',
+ 'menu_key' => 'shop_order_detail',
+ 'menu_short_name' => '订单详情',
+ 'parent_select_key' => 'shop_order_list',
+ 'menu_type' => '1',
+ 'icon' => 'iconfont iconshangpinguanli',
+ 'api_url' => 'shop/order/detail/',
+ 'router_path' => 'shop/order/detail',
+ 'view_path' => 'order/detail',
+ 'methods' => 'get',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ [
+ 'menu_name' => '物流跟踪',
+ 'menu_key' => 'shop_config_delivery_search',
+ 'menu_short_name' => '物流跟踪',
+ 'parent_select_key' => 'shop_config_delivery',
+ 'menu_type' => '1',
+ 'icon' => 'iconfont iconwuliugenzong',
+ 'api_url' => '',
+ 'router_path' => 'shop/order/delivery/search',
+ 'view_path' => 'delivery/search',
+ 'methods' => 'get',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ 'children' => [
+ [
+ 'menu_name' => '物流跟踪设置',
+ 'menu_key' => 'shop_config_delivery_search_set',
+ 'menu_short_name' => '物流跟踪设置',
+ 'menu_type' => '2',
+ 'icon' => '',
+ 'api_url' => 'shop/delivery/search',
+ 'router_path' => '',
+ 'view_path' => '',
+ 'methods' => 'post',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ ],
+ ],
+ [
+ 'menu_name' => '自提点',
+ 'menu_key' => 'shop_config_shop_delivery_store',
+ 'menu_short_name' => '自提点',
+ 'menu_type' => '1',
+ 'icon' => '',
+ 'api_url' => 'shop/delivery/store',
+ 'router_path' => 'shop/order/delivery/store',
+ 'view_path' => 'delivery/store',
+ 'methods' => 'get',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ 'children' => [
+ [
+ 'menu_name' => '自提点删除',
+ 'menu_key' => 'shop_config_delete_delivery_store',
+ 'menu_short_name' => '自提点删除',
+ 'menu_type' => '2',
+ 'icon' => '',
+ 'api_url' => 'shop/delivery/store/',
+ 'router_path' => '',
+ 'view_path' => '',
+ 'methods' => 'delete',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ ],
+ ],
+ [
+ 'menu_name' => '自提点添加/编辑',
+ 'menu_key' => 'shop_config_add_edit_delivery_store',
+ 'menu_short_name' => '自提点添加/编辑',
+ 'parent_select_key' => 'shop_config_shop_delivery_store',
+ 'menu_type' => '1',
+ 'icon' => '',
+ 'api_url' => '',
+ 'router_path' => 'shop/order/delivery/store/edit',
+ 'view_path' => 'delivery/store_edit',
+ 'methods' => 'post',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ 'children' => [
+ [
+ 'menu_name' => '自提点添加',
+ 'menu_key' => 'shop_config_add_delivery_store',
+ 'menu_short_name' => '自提点添加',
+ 'menu_type' => '2',
+ 'icon' => '',
+ 'api_url' => 'shop/delivery/store',
+ 'router_path' => '',
+ 'view_path' => '',
+ 'methods' => 'post',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ [
+ 'menu_name' => '自提点编辑',
+ 'menu_key' => 'shop_config_edit_delivery_store',
+ 'menu_short_name' => '自提点编辑',
+ 'menu_type' => '2',
+ 'icon' => '',
+ 'api_url' => 'shop/delivery/store/',
+ 'router_path' => '',
+ 'view_path' => '',
+ 'methods' => 'put',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ ],
+ ],
+ [
+ 'menu_name' => '售后详情',
+ 'menu_key' => 'shop_order_refund_detail',
+ 'menu_short_name' => '售后详情',
+ 'parent_select_key' => 'shop_order_refund',
+ 'menu_type' => '1',
+ 'icon' => 'iconfont iconshangpinguanli',
+ 'api_url' => '',
+ 'router_path' => 'shop/order/refund/detail',
+ 'view_path' => 'order/refund_detail',
+ 'methods' => 'get',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ [
+ 'menu_name' => '电子面单设置',
+ 'menu_key' => 'shop_delivery_electronic_sheet_config',
+ 'menu_short_name' => '电子面单设置',
+ 'parent_select_key' => 'shop_delivery_electronic_sheet',
+ 'menu_type' => '1',
+ 'icon' => 'iconfont icondiscount',
+ 'api_url' => 'shop/electronic_sheet/config',
+ 'router_path' => 'shop/delivery/electronic_sheet/config',
+ 'view_path' => 'delivery/electronic_sheet_config',
+ 'methods' => 'get',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ [
+ 'menu_name' => '添加模板',
+ 'menu_key' => 'shop_delivery_electronic_sheet_add',
+ 'menu_short_name' => '添加电子面单模板',
+ 'parent_select_key' => 'shop_delivery_electronic_sheet',
+ 'menu_type' => '1',
+ 'icon' => '',
+ 'api_url' => 'shop/electronic_sheet',
+ 'router_path' => 'shop/delivery/electronic_sheet_add',
+ 'view_path' => 'delivery/electronic_sheet_edit',
+ 'methods' => 'post',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ [
+ 'menu_name' => '编辑模板',
+ 'menu_key' => 'shop_delivery_electronic_sheet_edit',
+ 'menu_short_name' => '编辑电子面单模板',
+ 'parent_select_key' => 'shop_delivery_electronic_sheet',
+ 'menu_type' => '1',
+ 'icon' => '',
+ 'api_url' => 'shop/electronic_sheet/',
+ 'router_path' => 'shop/delivery/electronic_sheet_edit',
+ 'view_path' => 'delivery/electronic_sheet_edit',
+ 'methods' => 'put',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ ],
+ ],
+ [
+ 'menu_name' => '数据统计',
+ 'menu_key' => 'shop_stat',
+ 'menu_short_name' => '数据',
+ 'menu_type' => '0',
+ 'icon' => 'iconfont iconshujutongji',
+ 'api_url' => '',
+ 'router_path' => 'shop/stat/index',
+ 'view_path' => '',
+ 'methods' => 'get',
+ 'sort' => '85',
+ 'status' => '1',
+ 'is_show' => '0',
+ 'children' => [
+ [
+ 'menu_name' => '数据概况',
+ 'menu_key' => 'shop_stat_index',
+ 'menu_short_name' => '数据概况',
+ 'menu_type' => '1',
+ 'icon' => 'iconfont icona-dingdanliebiao',
+ 'api_url' => 'shop/stat/index',
+ 'router_path' => 'shop/stat/index',
+ 'view_path' => 'stat/index',
+ 'methods' => 'get',
+ 'sort' => '90',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ [
+ 'menu_name' => '会员数据',
+ 'menu_key' => 'shop_stat_member',
+ 'menu_short_name' => '会员数据',
+ 'menu_type' => '1',
+ 'icon' => 'iconfont icona-dingdanliebiao',
+ 'api_url' => 'shop/stat/member',
+ 'router_path' => 'shop/stat/member',
+ 'view_path' => 'stat/member',
+ 'methods' => 'get',
+ 'sort' => '89',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ [
+ 'menu_name' => '交易数据',
+ 'menu_key' => 'shop_stat_order',
+ 'menu_short_name' => '交易数据',
+ 'menu_type' => '1',
+ 'icon' => 'iconfont icona-dingdanliebiao',
+ 'api_url' => '',
+ 'router_path' => 'shop/stat/order',
+ 'view_path' => 'stat/order',
+ 'methods' => 'get',
+ 'sort' => '88',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ [
+ 'menu_name' => '流量数据',
+ 'menu_key' => 'shop_stat_visit',
+ 'menu_short_name' => '流量数据',
+ 'menu_type' => '1',
+ 'icon' => 'iconfont icona-dingdanliebiao',
+ 'api_url' => 'shop/stat/visit',
+ 'router_path' => 'shop/stat/visit',
+ 'view_path' => 'stat/visit',
+ 'methods' => 'get',
+ 'sort' => '87',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ ],
+ ],
+ ],
+ ],
+ [
+ 'menu_name' => '优惠券',
+ 'menu_key' => 'shop_goods_coupon',
+ 'menu_short_name' => '优惠券',
+ 'parent_key' => 'addon',
+ 'menu_type' => '0',
+ 'icon' => 'element Help',
+ 'api_url' => '',
+ 'router_path' => 'shop/marketing/coupon/list',
+ 'view_path' => '',
+ 'methods' => '',
+ 'sort' => '150',
+ 'status' => '1',
+ 'is_show' => '1',
+ 'children' => [
+ [
+ 'menu_name' => '优惠券列表',
+ 'menu_key' => 'shop_goods_coupon_list',
+ 'menu_short_name' => '优惠券',
+ 'menu_type' => '1',
+ 'icon' => 'iconfont iconyouhuiquan',
+ 'api_url' => '',
+ 'router_path' => 'shop/marketing/coupon/list',
+ 'view_path' => 'marketing/coupon/list',
+ 'methods' => 'get',
+ 'sort' => '90',
+ 'status' => '1',
+ 'is_show' => '1',
+ 'children' => [
+ [
+ 'menu_name' => '优惠券删除',
+ 'menu_key' => 'shop_goods_coupon_delete',
+ 'menu_short_name' => '优惠券删除',
+ 'menu_type' => '2',
+ 'icon' => '',
+ 'api_url' => 'shop/goods/coupon/delete',
+ 'router_path' => '',
+ 'view_path' => '',
+ 'methods' => 'post',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ [
+ 'menu_name' => '优惠券设置状态',
+ 'menu_key' => 'shop_goods_coupon_set_status',
+ 'menu_short_name' => '优惠券设置状态',
+ 'menu_type' => '2',
+ 'icon' => '',
+ 'api_url' => 'shop/goods/coupon/setstatus/',
+ 'router_path' => '',
+ 'view_path' => '',
+ 'methods' => 'put',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ [
+ 'menu_name' => '发券记录',
+ 'menu_key' => 'shop_goods_coupon_send_list',
+ 'menu_short_name' => '发券记录',
+ 'menu_type' => '2',
+ 'icon' => '',
+ 'api_url' => 'shop/goods/coupon/send/pages/',
+ 'router_path' => 'shop/marketing/coupon/send_list',
+ 'view_path' => 'marketing/coupon/send_list',
+ 'methods' => 'get',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ [
+ 'menu_name' => '发券',
+ 'menu_key' => 'shop_goods_coupon_send',
+ 'menu_short_name' => '发券',
+ 'menu_type' => '2',
+ 'icon' => '',
+ 'api_url' => 'shop/goods/coupon/send/',
+ 'router_path' => 'shop/marketing/coupon/send',
+ 'view_path' => 'marketing/coupon/send',
+ 'methods' => 'post',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ ],
+ ],
+ [
+ 'menu_name' => '优惠券添加',
+ 'menu_key' => 'shop_goods_coupon_add',
+ 'menu_short_name' => '优惠券添加',
+ 'parent_select_key' => 'shop_goods_coupon_list',
+ 'menu_type' => '1',
+ 'icon' => '',
+ 'api_url' => 'shop/goods/coupon',
+ 'router_path' => 'shop/marketing/coupon/add',
+ 'view_path' => 'marketing/coupon/add',
+ 'methods' => 'post',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ [
+ 'menu_name' => '优惠券编辑',
+ 'menu_key' => 'shop_goods_coupon_edit',
+ 'menu_short_name' => '优惠券编辑',
+ 'parent_select_key' => 'shop_goods_coupon_list',
+ 'menu_type' => '1',
+ 'icon' => '',
+ 'api_url' => 'shop/goods/coupon/edit/',
+ 'router_path' => 'shop/marketing/coupon/edit',
+ 'view_path' => 'marketing/coupon/edit',
+ 'methods' => 'put',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ [
+ 'menu_name' => '优惠券领取记录',
+ 'menu_key' => 'shop_goods_coupon_collection',
+ 'menu_short_name' => '优惠券领取记录',
+ 'parent_select_key' => 'shop_goods_coupon_list',
+ 'menu_type' => '1',
+ 'icon' => '',
+ 'api_url' => 'shop/goods/coupon/records',
+ 'router_path' => 'shop/marketing/coupon/collection',
+ 'view_path' => 'marketing/coupon/collection',
+ 'methods' => 'get',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ ],
+ ],
+ [
+ 'menu_name' => '满减送',
+ 'menu_key' => 'shop_goods_manjian',
+ 'menu_short_name' => '满减送',
+ 'parent_key' => 'addon',
+ 'menu_type' => '0',
+ 'icon' => 'element Help',
+ 'api_url' => '',
+ 'router_path' => 'shop/marketing/manjian/list',
+ 'view_path' => '',
+ 'methods' => '',
+ 'sort' => '151',
+ 'status' => '1',
+ 'is_show' => '1',
+ 'children' => [
+ [
+ 'menu_name' => '满减送',
+ 'menu_key' => 'shop_goods_manjian_list',
+ 'menu_short_name' => '满减送',
+ 'menu_type' => '1',
+ 'icon' => 'iconfont icondiscount',
+ 'api_url' => 'shop/manjian',
+ 'router_path' => 'shop/marketing/manjian/list',
+ 'view_path' => 'marketing/manjian/list',
+ 'methods' => 'get',
+ 'sort' => '89',
+ 'status' => '1',
+ 'is_show' => '1',
+ 'children' => [
+ [
+ 'menu_name' => '活动关闭',
+ 'menu_key' => 'shop_goods_manjian_close',
+ 'menu_short_name' => '活动关闭',
+ 'menu_type' => '2',
+ 'icon' => '',
+ 'api_url' => 'shop/manjian/close/',
+ 'router_path' => '',
+ 'view_path' => '',
+ 'methods' => 'put',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ [
+ 'menu_name' => '活动删除',
+ 'menu_key' => 'shop_goods_manjian_delete',
+ 'menu_short_name' => '活动删除',
+ 'menu_type' => '2',
+ 'icon' => '',
+ 'api_url' => 'shop/manjian/',
+ 'router_path' => '',
+ 'view_path' => '',
+ 'methods' => 'delete',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ ],
+ ],
+ [
+ 'menu_name' => '活动详情',
+ 'menu_key' => 'shop_goods_manjian_detail',
+ 'menu_short_name' => '活动详情',
+ 'parent_select_key' => 'shop_goods_manjian_list',
+ 'menu_type' => '1',
+ 'icon' => '',
+ 'api_url' => 'shop/manjian/',
+ 'router_path' => 'shop/marketing/manjian/detail',
+ 'view_path' => 'marketing/manjian/detail',
+ 'methods' => 'get',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ [
+ 'menu_name' => '编辑满减送活动',
+ 'menu_key' => 'shop_goods_manjian_edit',
+ 'menu_short_name' => '编辑满减送活动',
+ 'parent_select_key' => 'shop_goods_manjian_list',
+ 'menu_type' => '1',
+ 'icon' => '',
+ 'api_url' => 'shop/manjian/',
+ 'router_path' => 'shop/marketing/manjian/edit',
+ 'view_path' => 'marketing/manjian/edit',
+ 'methods' => 'put',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ [
+ 'menu_name' => '添加满减送活动',
+ 'menu_key' => 'shop_goods_manjian_add',
+ 'menu_short_name' => '添加满减送活动',
+ 'parent_select_key' => 'shop_goods_manjian_list',
+ 'menu_type' => '1',
+ 'icon' => '',
+ 'api_url' => 'shop/manjian',
+ 'router_path' => 'shop/marketing/manjian/add',
+ 'view_path' => 'marketing/manjian/edit',
+ 'methods' => 'post',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ ],
+ ],
+ [
+ 'menu_name' => '限时折扣',
+ 'menu_key' => 'shop_goods_discount',
+ 'menu_short_name' => '限时折扣',
+ 'parent_key' => 'addon',
+ 'menu_type' => '0',
+ 'icon' => 'iconfont icondiscount',
+ 'api_url' => '',
+ 'router_path' => 'shop/marketing/discount/list',
+ 'view_path' => 'marketing/discount/list',
+ 'methods' => 'get',
+ 'sort' => '152',
+ 'status' => '1',
+ 'is_show' => '1',
+ 'children' => [
+ [
+ 'menu_name' => '活动列表',
+ 'menu_key' => 'shop_goods_discount_list',
+ 'menu_short_name' => '活动列表',
+ 'menu_type' => '1',
+ 'icon' => 'iconfont icondiscount',
+ 'api_url' => 'shop/active/discount',
+ 'router_path' => 'shop/marketing/discount/list',
+ 'view_path' => 'marketing/discount/list',
+ 'methods' => 'get',
+ 'sort' => '90',
+ 'status' => '1',
+ 'is_show' => '1',
+ 'children' => [
+ [
+ 'menu_name' => '活动关闭',
+ 'menu_key' => 'shop_goods_discount_close',
+ 'menu_short_name' => '活动关闭',
+ 'menu_type' => '2',
+ 'icon' => '',
+ 'api_url' => 'shop/active/discount/close/',
+ 'router_path' => '',
+ 'view_path' => '',
+ 'methods' => 'put',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ [
+ 'menu_name' => '活动删除',
+ 'menu_key' => 'shop_goods_discount_delete',
+ 'menu_short_name' => '活动删除',
+ 'menu_type' => '2',
+ 'icon' => '',
+ 'api_url' => 'shop/active/discount/',
+ 'router_path' => '',
+ 'view_path' => '',
+ 'methods' => 'delete',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ ],
+ ],
+ [
+ 'menu_name' => '活动设置',
+ 'menu_key' => 'shop_goods_discount_config',
+ 'menu_short_name' => '活动设置',
+ 'menu_type' => '1',
+ 'icon' => 'iconfont icondiscount',
+ 'api_url' => '',
+ 'router_path' => 'shop/marketing/discount/config',
+ 'view_path' => 'marketing/discount/config',
+ 'methods' => 'get',
+ 'sort' => '80',
+ 'status' => '1',
+ 'is_show' => '1',
+ 'children' => [
+ [
+ 'menu_name' => '活动设置编辑',
+ 'menu_key' => 'shop_goods_discount_config_set',
+ 'menu_short_name' => '活动设置编辑',
+ 'menu_type' => '2',
+ 'icon' => '',
+ 'api_url' => 'shop/active/discount/config',
+ 'router_path' => '',
+ 'view_path' => '',
+ 'methods' => 'put',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ ],
+ ],
+ [
+ 'menu_name' => '活动详情',
+ 'menu_key' => 'shop_goods_discount_detail',
+ 'menu_short_name' => '活动详情',
+ 'parent_select_key' => 'shop_goods_discount_list',
+ 'menu_type' => '1',
+ 'icon' => '',
+ 'api_url' => 'shop/active/discount/',
+ 'router_path' => 'shop/marketing/discount/detail',
+ 'view_path' => 'marketing/discount/detail',
+ 'methods' => 'get',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ [
+ 'menu_name' => '编辑限时折扣',
+ 'menu_key' => 'shop_goods_discount_edit',
+ 'menu_short_name' => '编辑限时折扣',
+ 'parent_select_key' => 'shop_goods_discount_list',
+ 'menu_type' => '1',
+ 'icon' => '',
+ 'api_url' => 'shop/active/discount/',
+ 'router_path' => 'shop/marketing/discount/edit',
+ 'view_path' => 'marketing/discount/edit',
+ 'methods' => 'put',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ [
+ 'menu_name' => '添加限时折扣',
+ 'menu_key' => 'shop_goods_discount_add',
+ 'menu_short_name' => '添加限时折扣',
+ 'parent_select_key' => 'shop_goods_discount_list',
+ 'menu_type' => '1',
+ 'icon' => '',
+ 'api_url' => 'shop/active/discount',
+ 'router_path' => 'shop/marketing/discount/add',
+ 'view_path' => 'marketing/discount/add',
+ 'methods' => 'post',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ ],
+ ],
+ [
+ 'menu_name' => '积分商城',
+ 'menu_key' => 'shop_point_goods',
+ 'menu_short_name' => '积分商城',
+ 'parent_key' => 'addon',
+ 'menu_type' => '0',
+ 'icon' => 'iconfont iconpointshop',
+ 'api_url' => '',
+ 'router_path' => 'shop/marketing/exchange/goods_list',
+ 'view_path' => '',
+ 'methods' => 'get',
+ 'sort' => '153',
+ 'status' => '1',
+ 'is_show' => '1',
+ 'children' => [
+ [
+ 'menu_name' => '积分商品',
+ 'menu_key' => 'shop_point_goods_list',
+ 'menu_short_name' => '积分商品',
+ 'menu_type' => '1',
+ 'icon' => 'iconfont iconpointgoods',
+ 'api_url' => 'shop/active/exchange',
+ 'router_path' => 'shop/marketing/exchange/goods_list',
+ 'view_path' => 'marketing/exchange/goods_list',
+ 'methods' => 'get',
+ 'sort' => '90',
+ 'status' => '1',
+ 'is_show' => '1',
+ 'children' => [
+ [
+ 'menu_name' => '修改上下架状态',
+ 'menu_key' => 'shop_point_goods_status_edit',
+ 'menu_short_name' => '修改上下架状态',
+ 'menu_type' => '2',
+ 'icon' => '',
+ 'api_url' => 'shop/active/exchange/status/',
+ 'router_path' => '',
+ 'view_path' => '',
+ 'methods' => 'put',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ [
+ 'menu_name' => '删除积分商品',
+ 'menu_key' => 'shop_point_goods_delete',
+ 'menu_short_name' => '删除积分商品',
+ 'menu_type' => '2',
+ 'icon' => '',
+ 'api_url' => 'shop/active/exchange/',
+ 'router_path' => '',
+ 'view_path' => '',
+ 'methods' => 'delete',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ [
+ 'menu_name' => '修改排序号',
+ 'menu_key' => 'shop_point_goods_sort_edit',
+ 'menu_short_name' => '修改排序号',
+ 'menu_type' => '2',
+ 'icon' => '',
+ 'api_url' => 'shop/active/exchange/sort/',
+ 'router_path' => '',
+ 'view_path' => '',
+ 'methods' => 'put',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ ],
+ ],
+ [
+ 'menu_name' => '兑换记录',
+ 'menu_key' => 'shop_point_exchange_list',
+ 'menu_short_name' => '兑换记录',
+ 'parent_select_key' => 'shop_point_goods_list',
+ 'menu_type' => '1',
+ 'icon' => 'iconfont iconpointexchange',
+ 'api_url' => '',
+ 'router_path' => 'shop/marketing/exchange/order_list',
+ 'view_path' => 'marketing/exchange/order_list',
+ 'methods' => 'get',
+ 'sort' => '89',
+ 'status' => '1',
+ 'is_show' => '1',
+ ],
+ [
+ 'menu_name' => '添加商品',
+ 'menu_key' => 'shop_point_goods_add',
+ 'menu_short_name' => '添加商品',
+ 'parent_select_key' => 'shop_point_goods_list',
+ 'menu_type' => '1',
+ 'icon' => '',
+ 'api_url' => 'shop/active/exchange',
+ 'router_path' => 'shop/marketing/exchange/goods_add',
+ 'view_path' => 'marketing/exchange/goods_add',
+ 'methods' => 'post',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ [
+ 'menu_name' => '编辑商品',
+ 'menu_key' => 'shop_point_goods_edit',
+ 'menu_short_name' => '编辑商品',
+ 'parent_select_key' => 'shop_point_goods_list',
+ 'menu_type' => '1',
+ 'icon' => '',
+ 'api_url' => 'shop/active/exchange/',
+ 'router_path' => 'shop/marketing/exchange/goods_edit',
+ 'view_path' => 'marketing/exchange/goods_edit',
+ 'methods' => 'put',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ ],
+ ],
+ [
+ 'menu_name' => '新人专享',
+ 'menu_key' => 'shop_goods_newcomer_discount',
+ 'menu_short_name' => '新人专享',
+ 'parent_key' => 'addon',
+ 'menu_type' => '0',
+ 'icon' => 'iconfont icondiscount',
+ 'api_url' => '',
+ 'router_path' => 'shop/marketing/newcomer/config',
+ 'view_path' => '',
+ 'methods' => 'get',
+ 'sort' => '154',
+ 'status' => '1',
+ 'is_show' => '1',
+ 'children' => [
+ [
+ 'menu_name' => '新人设置',
+ 'menu_key' => 'shop_goods_newcomer_discount_config',
+ 'menu_short_name' => '新人设置',
+ 'menu_type' => '1',
+ 'icon' => 'iconfont icondiscount',
+ 'api_url' => 'shop/active/newcomer/config',
+ 'router_path' => 'shop/marketing/newcomer/config',
+ 'view_path' => 'marketing/newcomer/config',
+ 'methods' => 'put',
+ 'sort' => '90',
+ 'status' => '1',
+ 'is_show' => '1',
+ ],
+ [
+ 'menu_name' => '购买记录',
+ 'menu_key' => 'shop_goods_newcomer_discount_order_list',
+ 'menu_short_name' => '购买记录',
+ 'menu_type' => '1',
+ 'icon' => 'iconfont icondiscount',
+ 'api_url' => 'shop/active/newcomer/order',
+ 'router_path' => 'shop/marketing/newcomer/order_list',
+ 'view_path' => 'marketing/newcomer/order_list',
+ 'methods' => 'get',
+ 'sort' => '80',
+ 'status' => '1',
+ 'is_show' => '1',
+ ],
+ ],
+ ],
+ [
+ 'menu_name' => '商品榜单',
+ 'menu_key' => 'shop_goods_rank',
+ 'menu_short_name' => '商品榜单',
+ 'parent_key' => 'addon',
+ 'menu_type' => '0',
+ 'icon' => 'iconfont icondiscount',
+ 'api_url' => '',
+ 'router_path' => 'shop/marketing/goods_rank/config',
+ 'view_path' => '',
+ 'methods' => 'get',
+ 'sort' => '155',
+ 'status' => '1',
+ 'is_show' => '1',
+ 'children' => [
+ [
+ 'menu_name' => '榜单设置',
+ 'menu_key' => 'shop_goods_rank_config',
+ 'menu_short_name' => '榜单设置',
+ 'menu_type' => '1',
+ 'icon' => 'iconfont icondiscount',
+ 'api_url' => 'shop/good/rank/config',
+ 'router_path' => 'shop/marketing/goods_rank/config',
+ 'view_path' => 'marketing/goods_rank/config',
+ 'methods' => 'get',
+ 'sort' => '90',
+ 'status' => '1',
+ 'is_show' => '1',
+ ],
+ [
+ 'menu_name' => '榜单管理',
+ 'menu_key' => 'shop_goods_rank_list',
+ 'menu_short_name' => '榜单管理',
+ 'menu_type' => '1',
+ 'icon' => 'iconfont icondiscount',
+ 'api_url' => 'shop/good/rank',
+ 'router_path' => 'shop/marketing/goods_rank/list',
+ 'view_path' => 'marketing/goods_rank/list',
+ 'methods' => 'get',
+ 'sort' => '80',
+ 'status' => '1',
+ 'is_show' => '1',
+ 'children' => [
+ [
+ 'menu_name' => '删除榜单',
+ 'menu_key' => 'shop_goods_rank_delete',
+ 'menu_short_name' => '删除榜单',
+ 'menu_type' => '2',
+ 'icon' => '',
+ 'api_url' => 'shop/good/rank/',
+ 'router_path' => '',
+ 'view_path' => '',
+ 'methods' => 'delete',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ [
+ 'menu_name' => '批量删除榜单',
+ 'menu_key' => 'shop_goods_rank_batch_delete',
+ 'menu_short_name' => '批量删除榜单',
+ 'menu_type' => '2',
+ 'icon' => '',
+ 'api_url' => 'shop/good/rank/batchdelete',
+ 'router_path' => '',
+ 'view_path' => '',
+ 'methods' => 'put',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ [
+ 'menu_name' => '榜单排序号修改',
+ 'menu_key' => 'shop_goods_rank_sort_edit',
+ 'menu_short_name' => '榜单排序号修改',
+ 'menu_type' => '2',
+ 'icon' => '',
+ 'api_url' => 'shop/good/rank/sort',
+ 'router_path' => '',
+ 'view_path' => '',
+ 'methods' => 'put',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ ],
+ ],
+ [
+ 'menu_name' => '榜单添加',
+ 'menu_key' => 'shop_goods_rank_add',
+ 'menu_short_name' => '榜单添加',
+ 'parent_select_key' => 'shop_goods_rank_list',
+ 'menu_type' => '1',
+ 'icon' => '',
+ 'api_url' => 'shop/good/rank',
+ 'router_path' => 'shop/marketing/goods_rank/edit',
+ 'view_path' => 'marketing/goods_rank/edit',
+ 'methods' => 'post',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ [
+ 'menu_name' => '榜单编辑',
+ 'menu_key' => 'shop_goods_rank_edit',
+ 'menu_short_name' => '榜单编辑',
+ 'parent_select_key' => 'shop_goods_rank_list',
+ 'menu_type' => '1',
+ 'icon' => '',
+ 'api_url' => 'shop/good/rank/',
+ 'router_path' => 'shop/marketing/goods_rank/edit',
+ 'view_path' => 'marketing/goods_rank/edit',
+ 'methods' => 'put',
+ 'sort' => '0',
+ 'status' => '1',
+ 'is_show' => '0',
+ ],
+ ],
+ ],
+];
diff --git a/niucloud/addon/shop/app/dict/notice/notice.php b/niucloud/addon/shop/app/dict/notice/notice.php
new file mode 100644
index 000000000..9f5acebae
--- /dev/null
+++ b/niucloud/addon/shop/app/dict/notice/notice.php
@@ -0,0 +1,58 @@
+ [
+ 'addon' => 'shop',
+ 'key' => 'shop_order_pay',
+ 'receiver_type' => 1,
+ 'name' => '商城订单支付成功通知',
+ 'title' => '订单支付成功后发送',
+ 'async' => true,
+ 'variable' => [
+ 'order_money' => '订单总额',
+ 'pay_time' => '支付时间',
+ 'create_time' => '支付时间',
+ 'body' => '订单内容',
+ 'order_no' => '订单编号',
+ 'url' => '订单链接'
+ ],
+ ],
+ 'shop_order_delivery' => [
+ 'addon' => 'shop',
+ 'key' => 'shop_order_delivery',
+ 'receiver_type' => 1,
+ 'name' => '商城订单发货通知',
+ 'title' => '订单发货之后通知买家',
+ 'async' => true,
+ 'variable' => [
+ 'delivery_time' => '发货时间',
+ 'order_money' => '订单总额',
+ 'body' => '订单内容',
+ 'order_no' => '订单编号',
+ 'url' => '订单链接'
+ ],
+ ],
+ 'shop_refund_agree' => [
+ 'addon' => 'shop',
+ 'key' => 'shop_refund_agree',
+ 'receiver_type' => 1,
+ 'name' => '商城商家同意退款申请',
+ 'title' => '商家同意买家退款申请后发送',
+ 'async' => true,
+ 'variable' => [
+ 'order_no' => '订单编号',
+ 'refund_money' => '退款金额',
+ ],
+ ],
+ 'shop_refund_refuse' => [
+ 'addon' => 'shop',
+ 'key' => 'shop_refund_refuse',
+ 'receiver_type' => 1,
+ 'name' => '商城商家拒绝退款申请',
+ 'title' => '商家拒绝买家退款申请后发送',
+ 'async' => true,
+ 'variable' => [
+ 'order_no' => '订单编号',
+ 'refund_money' => '退款金额',
+ ]
+ ]
+];
diff --git a/niucloud/addon/shop/app/dict/notice/sms.php b/niucloud/addon/shop/app/dict/notice/sms.php
new file mode 100644
index 000000000..67e3ed65c
--- /dev/null
+++ b/niucloud/addon/shop/app/dict/notice/sms.php
@@ -0,0 +1,34 @@
+ [
+ 'is_need_closure_content' => 1,//是否需要闭包处理content
+ 'content' => function ($data) {
+ $sms_type = $data['sms_type'];
+ if ($sms_type == SmsDict::NIUSMS) {
+ return "您的订单{order_no}已支付成功";
+ }
+ return "您购买的“{body}”已支付成功。查看详情{url}";
+ }
+ ],
+ 'shop_order_delivery' => [
+ 'is_need_closure_content' => 1,//是否需要闭包处理content
+ 'content' => function ($data) {
+ $sms_type = $data['sms_type'];
+ if ($sms_type == SmsDict::NIUSMS) {
+ return "您的订单{order_no}已于{delivery_time}发货";
+ }
+ return "您购买的“{body}”已于{delivery_time}发货。查看详情{url}";
+ }
+ ],
+ 'shop_refund_agree' => [
+ 'is_need_closure_content' => 0,
+ 'content' => '商家已同意您订单编号为{order_no}的退款申请,请关注具体的退款情况',
+ ],
+ 'shop_refund_refuse' => [
+ 'is_need_closure_content' => 0,
+ 'content' => '很抱歉,您订单编号为{order_no}的退款申请未被同意,请您联系商家并修改申请',
+ ],
+];
diff --git a/niucloud/addon/shop/app/dict/notice/weapp.php b/niucloud/addon/shop/app/dict/notice/weapp.php
new file mode 100644
index 000000000..847949da9
--- /dev/null
+++ b/niucloud/addon/shop/app/dict/notice/weapp.php
@@ -0,0 +1,49 @@
+ [
+ 'tid' => '30808',
+ 'content' => [
+ ['订单编号', '{order_no}', 'character_string1'],
+ ['下单时间', '{create_time}', 'time2'],
+ ['商品名称', '{body}', 'thing4'],
+ ['订单金额', '{order_money}', 'amount3'],
+ ],
+ 'kid_list' => [1, 2, 4, 3],
+ 'scene_desc' => '订单支付之后通知',
+ 'tips' => '使用该消息请在小程序的服务类目中添加类目:一级类目:商业服务 二级类目:软件/建站/技术开发'
+ ],
+ 'shop_order_delivery' => [
+ 'tid' => '30766',
+ 'content' => [
+ ['订单编号', '{order_no}', 'character_string2'],
+ ['商品名称', '{body}', 'thing1'],
+ ['订单金额', '{order_money}', 'amount7'],
+ ['发货时间', '{delivery_time}', 'date3'],
+ ],
+ 'kid_list' => [2, 1, 7, 3],
+ 'scene_desc' => '订单发货通知',
+ 'tips' => '使用该消息请在小程序的服务类目中添加类目:一级类目:商业服务 二级类目:软件/建站/技术开发'
+ ],
+ 'shop_refund_agree' => [
+ 'tid' => '30825',
+ 'content' => [
+ ['订单编号', '{order_no}', 'character_string3'],
+ ['退款金额', '{refund_money}', 'amount1'],
+ ['申请结果', '{result}', 'phrase7'],
+ ],
+ 'kid_list' => [3, 1, 7],
+ 'scene_desc' => '商家同意退款',
+ 'tips' => '使用该消息请在小程序的服务类目中添加类目:一级类目:商业服务 二级类目:软件/建站/技术开发'
+ ],
+ 'shop_refund_refuse' => [
+ 'tid' => '30825',
+ 'content' => [
+ ['订单编号', '{order_no}', 'character_string3'],
+ ['退款金额', '{refund_money}', 'amount1'],
+ ['申请结果', '{result}', 'phrase7'],
+ ],
+ 'kid_list' => [3, 1, 7],
+ 'scene_desc' => '商家拒绝退款',
+ 'tips' => '使用该消息请在小程序的服务类目中添加类目:一级类目:商业服务 二级类目:软件/建站/技术开发'
+ ]
+];
diff --git a/niucloud/addon/shop/app/dict/notice/wechat.php b/niucloud/addon/shop/app/dict/notice/wechat.php
new file mode 100644
index 000000000..578e794b8
--- /dev/null
+++ b/niucloud/addon/shop/app/dict/notice/wechat.php
@@ -0,0 +1,42 @@
+ [
+ 'temp_key' => '43216',
+ 'content' => [
+ ['下单时间', '{create_time}', 'time4'],
+ ['订单编号', '{order_no}', 'character_string2'],
+ ['商品信息', '{body}', 'thing3'],
+ ['订单金额', '{order_money}', 'amount5']
+ ],
+ 'keyword_name_list' => ["下单时间", "订单号", "商品名称", "支付金额"],
+ 'tips' => '使用该消息请将微信公众号服务类目选择为:生活服务——>百货/超市/便利店'
+ ],
+ 'shop_order_delivery' => [
+ 'temp_key' => '42984',
+ 'content' => [
+ ['订单编号', '{order_no}', 'character_string2'],
+ ['商品名称', '{body}', 'thing4'],
+ ['发货时间', '{delivery_time}', 'time12']
+ ],
+ 'keyword_name_list' => ["订单编号", "商品名称", "发货时间"],
+ 'tips' => '使用该消息请将微信公众号服务类目选择为:生活服务——>百货/超市/便利店'
+ ],
+ 'shop_refund_agree' => [
+ 'temp_key' => '48058',
+ 'content' => [
+ ['订单编号', '{order_no}', 'character_string5'],
+ ['退款金额', '{refund_money}', 'amount2'],
+ ],
+ 'keyword_name_list' => ["订单编号", "退款金额"],
+ 'tips' => '使用该消息请将微信公众号服务类目选择为:商业服务——>软件/建站/技术开发'
+ ],
+ 'shop_refund_refuse' => [
+ 'temp_key' => '49580',
+ 'content' => [
+ ['订单编号', '{order_no}', 'character_string1'],
+ ['退款金额', '{refund_money}', 'amount2']
+ ],
+ 'keyword_name_list' => ["订单编号", "退款金额"],
+ 'tips' => '使用该消息请将微信公众号服务类目选择为:商业服务——>软件/建站/技术开发'
+ ],
+];
diff --git a/niucloud/addon/shop/app/dict/order/InvoiceDict.php b/niucloud/addon/shop/app/dict/order/InvoiceDict.php
new file mode 100644
index 000000000..cfe3a145b
--- /dev/null
+++ b/niucloud/addon/shop/app/dict/order/InvoiceDict.php
@@ -0,0 +1,94 @@
+ get_lang('dict_shop_invoice.header_type_company'),
+ self::PERSON => get_lang('dict_shop_invoice.header_type_person'),
+ ];
+ }
+
+ public static function getType()
+ {
+ return [
+ self::COMMON => get_lang('dict_shop_invoice.common'),
+ self::SPECIAL => get_lang('dict_shop_invoice.sprcial'),
+ ];
+ }
+
+ public static function getStatus()
+ {
+ return [
+ self::WAIT_OPEN => get_lang('dict_shop_invoice.wait_open'),
+ self::OPEN => get_lang('dict_shop_invoice.open'),
+ ];
+ }
+
+ public static function getIsInvoice()
+ {
+ return [
+ self::WAIT_INVOICE => get_lang('dict_shop_invoice.wait_invoice'),
+ self::INVOICED => get_lang('dict_shop_invoice.invoiced'),
+ self::WAIT_AUDIT => get_lang('dict_shop_invoice.wait_audit'),
+ ];
+ }
+
+}
diff --git a/niucloud/addon/shop/app/dict/order/OrderBatchDeliveryDict.php b/niucloud/addon/shop/app/dict/order/OrderBatchDeliveryDict.php
new file mode 100644
index 000000000..cd0bb478e
--- /dev/null
+++ b/niucloud/addon/shop/app/dict/order/OrderBatchDeliveryDict.php
@@ -0,0 +1,63 @@
+ get_lang('dict_shop_batch_delivery_status.processing'),
+ self::FINISH => get_lang('dict_shop_batch_delivery_status.finish'),
+ self::FAIL => get_lang('dict_shop_batch_delivery_status.fail'),
+ ];
+
+ if ($status == '') {
+ return $data;
+ }
+ return $data[ $status ] ?? '';
+ }
+
+}
diff --git a/niucloud/addon/shop/app/dict/order/OrderDeliveryDict.php b/niucloud/addon/shop/app/dict/order/OrderDeliveryDict.php
new file mode 100644
index 000000000..e5cee270b
--- /dev/null
+++ b/niucloud/addon/shop/app/dict/order/OrderDeliveryDict.php
@@ -0,0 +1,106 @@
+ [
+ self::EXPRESS => get_lang('dict_shop_delivery_type.express'),
+ self::NONE_EXPRESS => get_lang('dict_shop_delivery_type.none_express')
+ ],
+ DeliveryDict::LOCAL_DELIVERY => [
+ self::LOCAL_DELIVERY => get_lang('dict_shop_delivery_type.local_delivery')
+ ],
+ DeliveryDict::STORE => [
+ self::STORE => get_lang('dict_shop_delivery_type.store')
+ ],
+ self::VIRTUAL => [
+ self::VIRTUAL => get_lang('dict_shop_delivery_type.virtual'),
+ ],
+ ];
+
+ if ($type == '') {
+ return $data;
+ }
+ return $data[$type] ?? '';
+ }
+
+ const WAIT_DELIVERY = 'wait_delivery';
+ const DELIVERYING = 'delivery';
+ const DELIVERY_FINISH = 'delivery_finish';
+ const TAKED = 'taked';
+
+ const EXPIRE = 'expire';//失效
+ /**
+ * 配送状态(订单项)
+ * @param string $status
+ * @return array|mixed|string
+ */
+ public static function getStatus(string $status = '')
+ {
+ $data = [
+ self::WAIT_DELIVERY => get_lang('dict_shop_delivery_status.wait_delivery'),
+ self::DELIVERYING => get_lang('dict_shop_delivery_status.delivery'),
+ self::DELIVERY_FINISH => get_lang('dict_shop_delivery_status.delivery_finish'),
+ self::TAKED => get_lang('dict_shop_delivery_status.taked'),
+ ];
+
+ if ($status == '') {
+ return $data;
+ }
+ return $data[$status] ?? '';
+ }
+
+}
diff --git a/niucloud/addon/shop/app/dict/order/OrderDict.php b/niucloud/addon/shop/app/dict/order/OrderDict.php
new file mode 100644
index 000000000..1b773bb95
--- /dev/null
+++ b/niucloud/addon/shop/app/dict/order/OrderDict.php
@@ -0,0 +1,217 @@
+ self::TYPE,
+ 'name' => get_lang('dict_shop_order.order_type_shop')
+ ];
+ }//买家主动关闭
+
+ public static function getStatus($status = '', $delivery_type = '')
+ {
+ $data = [
+ self::WAIT_PAY => [
+ 'name' => get_lang('dict_shop_order.status_wait_pay'),//待支付
+ 'status' => self::WAIT_PAY,
+ 'is_refund' => 0,
+ 'action' => [],
+ 'member_action' => [
+ [
+ 'name' => '支付',
+ 'class' => '',
+ 'params' => ''
+ ],
+ ],
+ ],
+ self::WAIT_DELIVERY => [
+ 'name' => $delivery_type == OrderDeliveryDict::STORE ? get_lang('dict_shop_order.status_wait_pickup') : get_lang('dict_shop_order.status_wait_shipping'),//待发货
+ 'status' => self::WAIT_DELIVERY,
+ 'is_refund' => 0,
+ 'action' => [],
+ 'member_action' => [
+ [
+ 'name' => '支付',
+ 'class' => '',
+ 'params' => ''
+ ],
+ ],
+ ],
+ self::WAIT_TAKE => [
+ 'name' => get_lang('dict_shop_order.status_wait_take'),//待收货
+ 'status' => self::WAIT_TAKE,
+ 'is_refund' => 0,
+ 'action' => [],
+ 'member_action' => [
+ [
+ 'name' => '支付',
+ 'class' => '',
+ 'params' => ''
+ ],
+ ],
+ ],
+ self::FINISH => [
+ 'name' => get_lang('dict_shop_order.status_finish'),//已完成
+ 'status' => self::FINISH,
+ 'is_refund' => 0,
+ 'action' => [],
+ 'member_action' => [
+ ],
+ ],
+ self::CLOSE => [
+ 'name' => get_lang('dict_shop_order.status_close'),//已关闭
+ 'status' => self::CLOSE,
+ 'is_refund' => 0,
+ 'action' => [],
+ 'member_action' => [
+ ],
+ ]
+
+ ];
+ if ($status == '') {
+ return $data;
+ }
+ return $data[$status] ?? '';
+ }//自动关闭
+
+ /**
+ * 订单操作类型
+ * @param string $type
+ * @return array|mixed|string
+ */
+ public static function getActionType(string $type = '')
+ {
+ $data = [
+ self::ORDER_CREATE_ACTION => get_lang('dict_shop_order_action.order_create_action'),
+ self::ORDER_PAY_ACTION => get_lang('dict_shop_order_action.order_pay_action'),
+ self::ORDER_CLOSE_ACTION => get_lang('dict_shop_order_action.order_close_action'),
+ self::ORDER_DELIVERY_PART_ACTION => get_lang('dict_shop_order_action.order_part_delivery'),
+ self::ORDER_DELIVERY_ACTION => get_lang('dict_shop_order_action.order_delivery_action'),
+ self::ORDER_FINISH_ACTION => get_lang('dict_shop_order_action.order_finish_action'),
+ self::ORDER_REMARK_ACTION => get_lang('dict_shop_order_action.order_remark_action'),
+ self::ORDER_CLOSE_ALLOW_REFUND_ACTION => get_lang('dict_shop_order_action.order_close_allow_refund'),
+ self::ORDER_EDIT_PRICE_ACTION => get_lang('dict_shop_order_action.order_edit_price_action'),
+ ];
+ if (!$type) {
+ return $data;
+ }
+ return $data[$type] ?? '';
+ }
+
+ /**
+ * 关闭方式
+ * @param string $type
+ * @return array|mixed|string
+ */
+ public static function getCloseType(string $type = '')
+ {
+ $data = [
+ self::SHOP_CLOSE => get_lang('dict_shop_order_close_type.shop_close'),
+ self::BUYER_CLOSE => get_lang('dict_shop_order_close_type.buyer_close'),
+ self::AUTO_CLOSE => get_lang('dict_shop_order_close_type.auto_close'),
+ self::REFUND_CLOSE => get_lang('dict_shop_order_close_type.refund_close'),
+ ];
+ if (!$type) {
+ return $data;
+ }
+ return $data[$type] ?? '';
+ }
+
+ /**
+ * @param $type
+ * @return string
+ */
+ public static function getOrderActiveTypeName($type)
+ {
+ if (empty($type)) {
+ $type = self::TYPE;
+ }
+ $data = [
+ 'pintuan' => '拼团',
+ 'seckill' => '秒杀',
+ self::TYPE => '商城',
+ 'exchange' => '兑换',
+ 'giftcard' => '礼品卡',
+ 'newcomer_discount' => '新人专享',
+ 'discount' => '限时折扣',
+ 'manjiansong' => '满减送',
+ 'friend_help' => '好友助力',
+ ];
+ return $data[$type] ?? '';
+ }
+}
diff --git a/niucloud/addon/shop/app/dict/order/OrderDiscountDict.php b/niucloud/addon/shop/app/dict/order/OrderDiscountDict.php
new file mode 100644
index 000000000..465c435d8
--- /dev/null
+++ b/niucloud/addon/shop/app/dict/order/OrderDiscountDict.php
@@ -0,0 +1,51 @@
+ get_lang('dict_shop_order_discount.type_discount'),//优惠
+ self::GIFT => get_lang('dict_shop_order_discount.type_gift'),//礼物
+ ];
+ }
+
+ /**
+ * 优惠类型
+ * @return array
+ */
+ public static function getDiscountType()
+ {
+ return [
+ self::COUPON => get_lang('dict_shop_order_discount.discount_type_coupon'),//优惠券
+ self::POINT => get_lang('dict_shop_order_discount.discount_type_point'),//积分
+ ];
+ }
+
+}
diff --git a/niucloud/addon/shop/app/dict/order/OrderGoodsDict.php b/niucloud/addon/shop/app/dict/order/OrderGoodsDict.php
new file mode 100644
index 000000000..3ec3eea83
--- /dev/null
+++ b/niucloud/addon/shop/app/dict/order/OrderGoodsDict.php
@@ -0,0 +1,52 @@
+ get_lang('dict_shop_order_refund.normal'),
+ self::REFUNDING => get_lang('dict_shop_order_refund.refunding'),
+ self::REFUND_FINISH => get_lang('dict_shop_order_refund.refund_finish'),
+ ];
+ if ($status == '') {
+ return $data;
+ }
+ return $data[$status] ?? '';
+ }
+
+
+}
diff --git a/niucloud/addon/shop/app/dict/order/OrderLogDict.php b/niucloud/addon/shop/app/dict/order/OrderLogDict.php
new file mode 100644
index 000000000..c37c24cbb
--- /dev/null
+++ b/niucloud/addon/shop/app/dict/order/OrderLogDict.php
@@ -0,0 +1,44 @@
+ get_lang('dict_shop_order_log.store'),//商家
+ self::MEMBER => get_lang('dict_shop_order_log.member'),//会员
+ self::SYSTEM => get_lang('dict_shop_order_log.system'),//系统
+ ];
+ if (!$type) {
+ return $data;
+ }
+ return $data[$type] ?? '';
+ }
+
+}
diff --git a/niucloud/addon/shop/app/dict/order/OrderRefundDict.php b/niucloud/addon/shop/app/dict/order/OrderRefundDict.php
new file mode 100644
index 000000000..d9c8f54aa
--- /dev/null
+++ b/niucloud/addon/shop/app/dict/order/OrderRefundDict.php
@@ -0,0 +1,160 @@
+ get_lang('dict_shop_order_refund_status.buyer_apply_wait_store'),
+ self::STORE_AGREE_REFUND_GOODS_APPLY_WAIT_BUYER => get_lang('dict_shop_order_refund_status.store_agree_refund_goods_apply_wait_buyer'),
+ self::STORE_REFUSE_REFUND_GOODS_APPLY_WAIT_BUYER => get_lang('dict_shop_order_refund_status.store_refuse_refund_goods_apply_wait_buyer'),
+ self::BUYER_REFUND_GOODS_WAIT_STORE => get_lang('dict_shop_order_refund_status.buyer_refund_goods_wait_store'),
+ self::STORE_REFUSE_TAKE_REFUND_GOODS_WAIT_BUYER => get_lang('dict_shop_order_refund_status.store_refuse_take_refund_goods_wait_buyer'),
+ self::STORE_AGREE_REFUND_WAIT_TRANSFER => get_lang('dict_shop_order_refund_status.store_agree_refund_wait_transfer'),
+ self::STORE_REFUND_TRANSFERING => get_lang('dict_shop_order_refund_status.store_refund_transfering'),
+ self::FINISH => get_lang('dict_shop_order_refund_status.finish'),
+ self::CLOSE => get_lang('dict_shop_order_refund_status.close'),
+ self::SHOP_ACTIVE_CLOSE_REFUND => get_lang('dict_shop_order_refund_status.shop_active_close_refund'),
+ ];
+ if ($status == '') {
+ return $data;
+ }
+ return $data[$status] ?? [];
+ }//卖家拒绝退货
+
+ public static function getRefundType(string $type = '')
+ {
+ $data = [
+ self::ONLY_REFUND => get_lang('dict_shop_order_refund_type.only_refund'),
+ self::RETURN_AND_REFUND_GOODS => get_lang('dict_shop_order_refund_type.return_and_refund_goods'),
+ ];
+ if (!$type) {
+ return $data;
+ }
+ return $data[$type] ?? [];
+ }//卖家主动退款
+
+ /**
+ * 退款来源方式
+ * @param string $type
+ * @return array|mixed
+ */
+ public static function getSource(string $type = '')
+ {
+ $data = [
+ self::APPLY => get_lang('dict_shop_order_refund_source.apply'),
+ self::ACTIVE_REFUND => get_lang('dict_shop_order_refund_source.active_refund'),
+ ];
+ if (!$type) {
+ return $data;
+ }
+ return $data[$type] ?? [];
+ }//退款完成
+
+ /**
+ * 拒绝理由
+ * @return array
+ */
+ public static function getRefundReason()
+ {
+ return [
+ get_lang('dict_shop_order_refund_reason.delivery_timeout'),//未按约定时间发货
+ get_lang('dict_shop_order_refund_reason.buy_more_or_dislike'),//拍错/多拍/不喜欢
+ get_lang('dict_shop_order_refund_reason.negotiation_completed'),//协商一致退款
+ get_lang('dict_shop_order_refund_reason.other'),//其他
+ ];
+ }//关闭退款
+
+ /**
+ * 退款操作类型
+ * @param string $type
+ * @return array|mixed|string
+ */
+ public static function getActionType(string $type = '')
+ {
+ $data = [
+ self::APPLY_ACTION => get_lang('dict_shop_order_refund_action.apply'),
+ self::EDIT_APPLY_ACTION => get_lang('dict_shop_order_refund_action.edit_apply'),
+ self::CLOSE_ACTION => get_lang('dict_shop_order_refund_action.close'),
+ self::DELIVERY_ACTION => get_lang('dict_shop_order_refund_action.delivery'),
+ self::EDIT_DELIVERY_ACTION => get_lang('dict_shop_order_refund_action.edit_delivery'),
+ self::AGREE_AUDIT_APPLY_ACTION => get_lang('dict_shop_order_refund_action.agree_audit_apply'),
+ self::REFUSE_AUDIT_APPLY_ACTION => get_lang('dict_shop_order_refund_action.refuse_audit_apply_action'),
+ self::AGREE_AUDIT_REFUND_GOODS_ACTION => get_lang('dict_shop_order_refund_action.agree_audit_refund_goods'),
+ self::REFUSE_AUDIT_REFUND_GOODS_ACTION => get_lang('dict_shop_order_refund_action.refuse_audit_refund_goods'),
+ self::FINISH_ACTION => get_lang('dict_shop_order_refund_action.finish'),
+ self::ACTIVE_REFUND_ACTION => get_lang('dict_shop_order_refund_action.active_refund'),
+ self::SHOP_ACTIVE_REFUND_ACTION => get_lang('dict_shop_order_refund_action.shop_active_refund'),
+ ];
+ if (!$type) {
+ return $data;
+ }
+ return $data[$type] ?? '';
+ }
+}
diff --git a/niucloud/addon/shop/app/dict/order/OrderRefundLogDict.php b/niucloud/addon/shop/app/dict/order/OrderRefundLogDict.php
new file mode 100644
index 000000000..714961b02
--- /dev/null
+++ b/niucloud/addon/shop/app/dict/order/OrderRefundLogDict.php
@@ -0,0 +1,44 @@
+ get_lang('dict_shop_order_log.store'),//商家
+ self::MEMBER => get_lang('dict_shop_order_log.member'),//会员
+ self::SYSTEM => get_lang('dict_shop_order_log.system'),//系统
+ ];
+ if (!$type) {
+ return $data;
+ }
+ return $data[$type] ?? '';
+ }
+
+}
diff --git a/niucloud/addon/shop/app/dict/poster/components.php b/niucloud/addon/shop/app/dict/poster/components.php
new file mode 100644
index 000000000..b6a2141f2
--- /dev/null
+++ b/niucloud/addon/shop/app/dict/poster/components.php
@@ -0,0 +1,72 @@
+ [
+ 'title' => get_lang('dict_diy_poster.shop_goods_component_type_basic'),
+ 'support' => [ 'fenxiao_goods', 'shop_point_goods'], // 支持的插件
+ 'list' => [
+ 'GoodsImage' => [
+ 'title' => "商品图片",
+ 'type' => 'image',
+ 'icon' => "iconfont iconshangpintupian",
+ 'path' => "goods-image", // 属性编辑
+ 'uses' => 1,
+ 'sort' => 10006,
+ 'relate' => 'goods_img', // 关联字段,空为不处理
+ 'value' => '',
+ 'template' => [
+ "width" => 400, // 宽度
+ 'height' => 400, // 高度
+ 'minWidth' => 60, // 最小宽度
+ 'minHeight' => 60, // 最小高度
+ ],
+ ],
+ 'GoodsName' => [
+ 'title' => "商品名称",
+ 'type' => 'text',
+ 'icon' => "iconfont icona-Group13",
+ 'path' => "goods-name",
+ 'uses' => 1,
+ 'sort' => 10007,
+ 'relate' => 'goods_name', // 关联字段,空为不处理
+ 'value' => '',
+ 'template' => [
+ "width" => 164, // 宽度
+ 'height' => 55, // 高度
+ ]
+
+ ],
+ 'GoodsPrice' => [
+ 'title' => "销售价",
+ 'type' => 'text',
+ 'icon' => "iconfont iconshoujia",
+ 'path' => "goods-price",
+ 'uses' => 1,
+ 'sort' => 10008,
+ 'relate' => 'goods_price', // 关联字段,空为不处理
+ 'value' => '',
+ 'template' => [
+ "fontFamily" => 'static/font/OPLUSSANS3-REGULAR.ttf', // 字体
+ 'width' => 151, // 宽度
+ 'height' => 49, // 高度
+ ],
+ ],
+ 'GoodsMarketPrice' => [
+ 'title' => "划线价",
+ 'type' => 'text',
+ 'icon' => "iconfont iconhuajiaqian",
+ 'path' => "goods-market-price",
+ 'uses' => 1,
+ 'sort' => 10009,
+ 'relate' => 'goods_market_price', // 关联字段,空为不处理
+ 'value' => '',
+ 'template' => [
+ "fontFamily" => 'static/font/OPLUSSANS3-REGULAR.ttf', // 字体
+ 'width' => 170, // 宽度
+ 'height' => 48, // 高度
+ ],
+ ]
+ ]
+ ],
+
+];
\ No newline at end of file
diff --git a/niucloud/addon/shop/app/dict/poster/template.php b/niucloud/addon/shop/app/dict/poster/template.php
new file mode 100644
index 000000000..f18dbc465
--- /dev/null
+++ b/niucloud/addon/shop/app/dict/poster/template.php
@@ -0,0 +1,349 @@
+ "商品模板", // 海报模板名称
+ 'type' => 'shop_goods', // 海报类型
+ "data" => [
+ "global" => [
+ "bgType" => "color",
+ "bgColor" => "#ffffff",
+ "bgUrl" => "",
+ "width" => 720,
+ "height" => 1280
+ ],
+ "value" => [
+ [
+ "id" => "2v1nc497xhc0",
+ "componentName" => "GoodsImage",
+ "componentTitle" => "商品图片",
+ "type" => "image",
+ "path" => "goods-image",
+ "uses" => 1,
+ "relate" => "goods_img",
+ "value" => "",
+ "width" => 720,
+ "height" => 720,
+ "minWidth" => 60,
+ "minHeight" => 60,
+ "x" => 0,
+ "y" => 0,
+ "angle" => 0,
+ "zIndex" => 1
+ ],
+ [
+ "id" => "29f3czpuw134",
+ "componentName" => "GoodsName",
+ "componentTitle" => "商品名称",
+ "type" => "text",
+ "path" => "goods-name",
+ "uses" => 1,
+ "relate" => "goods_name",
+ "value" => "",
+ "width" => 640,
+ "height" => 94,
+ "minWidth" => 120,
+ "minHeight" => 44,
+ "x" => 40,
+ "y" => 760,
+ "angle" => 0,
+ "zIndex" => 2,
+ "fontFamily" => "",
+ "fontSize" => 44,
+ "weight" => false,
+ "space" => 0,
+ "lineHeight" => 1,
+ "fontColor" => "#303133"
+ ],
+ [
+ "id" => "2vmf9ovhene0",
+ "componentName" => "GoodsPrice",
+ "componentTitle" => "商品价格",
+ "type" => "text",
+ "path" => "goods-price",
+ "uses" => 1,
+ "relate" => "goods_price",
+ "value" => "",
+ "width" => 330,
+ "height" => 60,
+ "minWidth" => 120,
+ "minHeight" => 44,
+ "x" => 40,
+ "y" => 940,
+ "weight" => false,
+ "space" => 0,
+ "lineHeight" => 0,
+ "angle" => 0,
+ "zIndex" => 3,
+ "fontFamily" => "static/font/OPLUSSANS3-REGULAR.ttf",
+ "fontSize" => 44,
+ "fontColor" => "#E4163F"
+ ],
+ [
+ "id" => "2vef9ovhene9",
+ "componentName" => "GoodsMarketPrice",
+ "componentTitle" => "划线价",
+ "type" => "text",
+ 'path' => "goods-market-price",
+ "uses" => 1,
+ 'relate' => 'goods_market_price',
+ "value" => "",
+ "width" => 330,
+ "height" => 54,
+ "minWidth" => 120,
+ "minHeight" => 44,
+ "x" => 40,
+ "y" => 1040,
+ "angle" => 0,
+ "zIndex" => 4,
+ "fontFamily" => "static/font/OPLUSSANS3-REGULAR.ttf",
+ "fontSize" => 36,
+ "weight" => false,
+ "space" => 0,
+ "lineHeight" => 0,
+ "fontColor" => "#999999"
+ ],
+ [
+ "id" => "2rlojy3o60i0",
+ "componentName" => "Qrcode",
+ "componentTitle" => "二维码",
+ "type" => "qrcode",
+ "path" => "qrcode",
+ "uses" => 1,
+ "relate" => "url",
+ "value" => "",
+ "width" => 200,
+ "height" => 200,
+ "minWidth" => 60,
+ "minHeight" => 60,
+ "x" => 480,
+ "y" => 940,
+ "angle" => 0,
+ "zIndex" => 5
+ ],
+ [
+ "id" => "7a18udv7t950",
+ "componentName" => "draw",
+ "componentTitle" => "绘画",
+ "type" => "draw",
+ "path" => "draw",
+ "uses" => 1,
+ "relate" => "draw",
+ "value" => "",
+ "width" => 720,
+ "height" => 70,
+ "minWidth" => 60,
+ "minHeight" => 60,
+ "x" => 0,
+ "y" => 1206,
+ "angle" => 0,
+ "zIndex" => 6,
+ "drawType" => "Polygon",
+ "bgColor" => "#eeeeee",
+ "points" => [
+ [
+ 0,
+ 1206
+ ],
+ [
+ 720,
+ 1206
+ ],
+ [
+ 720,
+ 1280
+ ],
+ [
+ 0,
+ 1280
+ ]
+ ]
+ ],
+ [
+ "id" => "6hlj5l3as0w0",
+ "componentName" => "Text",
+ "componentTitle" => "文本",
+ "type" => "text",
+ "path" => "text",
+ "uses" => 0,
+ "relate" => "",
+ "value" => "长按识别图中的二维码查看商品详情",
+ "width" => 512,
+ "height" => 48,
+ "minWidth" => 120,
+ "minHeight" => 44,
+ "x" => 110,
+ "y" => 1230,
+ "angle" => 0,
+ "zIndex" => 7,
+ "weight" => false,
+ "space" => 0,
+ "lineHeight" => 0,
+ "fontFamily" => "",
+ "fontSize" => 32,
+ "fontColor" => "#666666"
+ ],
+ ]
+ ]
+ ],
+ [
+ "name" => "积分商品模板", // 海报模板名称
+ 'type' => 'shop_point_goods', // 海报类型
+ "data" => [
+ "global" => [
+ "bgType" => "color",
+ "bgColor" => "#ffffff",
+ "bgUrl" => "",
+ "width" => 720,
+ "height" => 1280
+ ],
+ "value" => [
+ [
+ "id" => "2v1nc497xhc0",
+ "componentName" => "GoodsImage",
+ "componentTitle" => "商品图片",
+ "type" => "image",
+ "path" => "goods-image",
+ "uses" => 1,
+ "relate" => "goods_img",
+ "value" => "",
+ "width" => 720,
+ "height" => 720,
+ "minWidth" => 60,
+ "minHeight" => 60,
+ "x" => 0,
+ "y" => 0,
+ "angle" => 0,
+ "zIndex" => 1
+ ],
+ [
+ "id" => "29f3czpuw134",
+ "componentName" => "GoodsName",
+ "componentTitle" => "商品名称",
+ "type" => "text",
+ "path" => "goods-name",
+ "uses" => 1,
+ "relate" => "goods_name",
+ "value" => "",
+ "width" => 640,
+ "height" => 94,
+ "minWidth" => 120,
+ "minHeight" => 44,
+ "x" => 40,
+ "y" => 760,
+ "angle" => 0,
+ "zIndex" => 2,
+ "fontFamily" => "",
+ "fontSize" => 44,
+ "weight" => false,
+ "space" => 0,
+ "lineHeight" => 0,
+ "fontColor" => "#303133"
+ ],
+ [
+ "id" => "2vmf9ovhene0",
+ "componentName" => "GoodsPrice",
+ "componentTitle" => "商品价格",
+ "type" => "text",
+ "path" => "goods-price",
+ "uses" => 1,
+ "relate" => "goods_price",
+ "value" => "",
+ "width" => 330,
+ "height" => 60,
+ "minWidth" => 120,
+ "minHeight" => 44,
+ "x" => 40,
+ "y" => 940,
+ "angle" => 0,
+ "zIndex" => 3,
+ "fontFamily" => "",
+ "fontSize" => 40,
+ "weight" => false,
+ "space" => 0,
+ "lineHeight" => 0,
+ "fontColor" => "#E4163F"
+ ],
+ [
+ "id" => "2rlojy3o60i0",
+ "componentName" => "Qrcode",
+ "componentTitle" => "二维码",
+ "type" => "qrcode",
+ "path" => "qrcode",
+ "uses" => 1,
+ "relate" => "url",
+ "value" => "",
+ "width" => 200,
+ "height" => 200,
+ "minWidth" => 60,
+ "minHeight" => 60,
+ "x" => 480,
+ "y" => 940,
+ "angle" => 0,
+ "zIndex" => 5
+ ],
+ [
+ "id" => "7a18udv7t950",
+ "componentName" => "draw",
+ "componentTitle" => "绘画",
+ "type" => "draw",
+ "path" => "draw",
+ "uses" => 1,
+ "relate" => "draw",
+ "value" => "",
+ "width" => 720,
+ "height" => 70,
+ "minWidth" => 60,
+ "minHeight" => 60,
+ "x" => 0,
+ "y" => 1206,
+ "angle" => 0,
+ "zIndex" => 6,
+ "drawType" => "Polygon",
+ "bgColor" => "#eeeeee",
+ "points" => [
+ [
+ 0,
+ 1206
+ ],
+ [
+ 720,
+ 1206
+ ],
+ [
+ 720,
+ 1280
+ ],
+ [
+ 0,
+ 1280
+ ]
+ ]
+ ],
+ [
+ "id" => "6hlj5l3as0w0",
+ "componentName" => "Text",
+ "componentTitle" => "文本",
+ "type" => "text",
+ "path" => "text",
+ "uses" => 0,
+ "relate" => "",
+ "value" => "长按识别图中的二维码查看商品详情",
+ "width" => 512,
+ "height" => 48,
+ "minWidth" => 120,
+ "minHeight" => 44,
+ "x" => 110,
+ "y" => 1230,
+ "angle" => 0,
+ "zIndex" => 7,
+ "fontFamily" => "",
+ "fontSize" => 32,
+ "weight" => false,
+ "space" => 0,
+ "lineHeight" => 0,
+ "fontColor" => "#666666"
+ ],
+ ]
+ ]
+ ]
+];
\ No newline at end of file
diff --git a/niucloud/addon/shop/app/dict/printer/type.php b/niucloud/addon/shop/app/dict/printer/type.php
new file mode 100644
index 000000000..549a114c8
--- /dev/null
+++ b/niucloud/addon/shop/app/dict/printer/type.php
@@ -0,0 +1,290 @@
+getDeliveryList();
+$print_delivery_list = [];
+foreach ($delivery_list as $k => $v) {
+ $print_delivery_list[] = [
+ 'name' => $v[ 'name' ],
+ 'value' => $v[ 'key' ]
+ ];
+}
+
+return [
+ [
+ 'key' => 'shopGoodsOrder',
+ 'title' => '商品订单', // 模板类型名称
+ 'sort' => 10000,
+ // 触发打印时机,定义何时触发调用
+ 'trigger' => [
+ 'pay_after' => '付款后',
+ 'take_delivery' => '收货后',
+ 'manual' => '手动'
+ ],
+ // 根据业务可自行扩展筛选条件
+ 'condition' => [
+ [
+ 'key' => 'print_delivery_type',
+ 'title' => '配送方式',
+ 'type' => 'checkbox',
+ 'list' => $print_delivery_list
+ ],
+ // todo 后续如果需要商品类型、订单类型,可以扩展
+ ],
+ 'path' => 'preview-goods-order', // 实时预览组件名称
+ // 模板内容
+ 'template' => [
+ [
+ 'key' => 'head_info',
+ 'title' => '票头',
+ 'list' => [
+ [
+ 'key' => 'ticket_name',
+ 'label' => '小票名称',
+ 'value' => '小票名称', // 存储的初始值,可以是字符串、数组格式
+ 'placeholder' => '', // 输入框占位符
+ 'type' => 'input', // 类型,空:无需设置,input:输入框、checkbox:复选框,select:下拉框
+ 'status' => 1, // 状态(1:显示,0:隐藏)
+ 'disabled' => false, // 是否禁止操作显示隐藏
+ 'fontSize' => 'normal', // 字号,normal:正常,small:,big:大
+ 'fontWeight' => 'normal', // 粗细,normal:正常,weight:加粗
+ 'remark' => '', // 说明
+ ],
+ [
+ 'key' => 'shop_name',
+ 'label' => '商城名称',
+ 'value' => '',
+ 'type' => '',
+ 'status' => 1,
+ 'disabled' => false,
+ 'fontSize' => 'big',
+ 'fontWeight' => 'bold',
+ 'remark' => '',
+ ],
+ ]
+ ],
+ [
+ 'key' => 'order_info',
+ 'title' => '订单信息',
+ 'list' => [
+ [
+ 'key' => 'order_item',
+ 'label' => '',
+ 'value' => [ 'order_no', 'order_from', 'pay_type', 'order_status', 'delivery_type', 'create_time', 'pay_time', 'goods_money', 'discount_money', 'delivery_money', 'order_money' ],
+ 'type' => 'checkbox',
+ 'status' => 1,
+ 'fontSize' => '',
+ 'fontWeight' => '',
+ 'disabled' => false,
+ 'remark' => '',
+ 'list' => [
+ 'order_no' => '订单编号',
+ 'order_from' => '订单来源',
+ 'order_status' => '订单状态',
+ 'pay_type' => '支付方式',
+ 'delivery_type' => '配送方式',
+ 'create_time' => '下单时间',
+ 'pay_time' => '付款时间',
+ 'goods_money' => '商品总额',
+ 'delivery_money' => '配送金额',
+ 'discount_money' => '优惠金额',
+ ]
+ ],
+ [
+ 'key' => 'order_money',
+ 'label' => '实付金额',
+ 'value' => '',
+ 'type' => '',
+ 'status' => 1,
+ 'fontSize' => 'big',
+ 'fontWeight' => 'bold',
+ 'remark' => '',
+ ],
+ [
+ 'key' => 'shop_remark',
+ 'label' => '商家备注',
+ 'value' => '',
+ 'type' => '',
+ 'status' => 1,
+ 'disabled' => false,
+ 'fontSize' => 'normal',
+ 'fontWeight' => 'bold',
+ 'remark' => '',
+ ],
+ ]
+ ],
+ [
+ 'key' => 'goods_info',
+ 'title' => '商品信息',
+ 'list' => [
+ [
+ 'key' => 'goods_name',
+ 'label' => '商品名称',
+ 'value' => '',
+ 'type' => '',
+ 'status' => 1,
+ 'disabled' => true,
+ 'fontSize' => 'normal',
+ 'fontWeight' => 'normal',
+ 'remark' => '',
+ ],
+ [
+ 'key' => 'goods_num',
+ 'label' => '商品数量',
+ 'value' => '',
+ 'type' => '',
+ 'status' => 1,
+ 'disabled' => true,
+ 'fontSize' => '',
+ 'fontWeight' => '',
+ 'remark' => '',
+ ],
+ [
+ 'key' => 'goods_price',
+ 'label' => '商品金额',
+ 'value' => '',
+ 'type' => '',
+ 'status' => 1,
+ 'disabled' => false,
+ 'fontSize' => 'normal',
+ 'fontWeight' => 'normal',
+ 'remark' => '',
+ ],
+ ]
+ ],
+ [
+ 'key' => 'buyer_info',
+ 'title' => '买家/收货信息',
+ 'list' => [
+ [
+ 'key' => 'member_basic_info',
+ 'label' => '',
+ 'value' => [ 'nickname', 'account_balance', 'account_point' ],
+ 'type' => 'checkbox',
+ 'status' => 1,
+ 'disabled' => false,
+ 'fontSize' => '',
+ 'fontWeight' => '',
+ 'remark' => '',
+ 'list' => [
+ 'nickname' => '买家昵称',
+ 'account_balance' => '账户余额',
+ 'account_point' => '账户积分',
+ ]
+ ],
+ [
+ 'key' => 'buyer_mobile',
+ 'label' => '买家手机号',
+ 'value' => 'yes',
+ 'type' => 'select',
+ 'status' => 1,
+ 'disabled' => false,
+ 'fontSize' => 'normal',
+ 'fontWeight' => 'normal',
+ 'remark' => '手机号脱敏可以有效保护用户隐私',
+ 'text' => '脱敏',
+ 'list' => [
+ 'yes' => '是',
+ 'no' => '否'
+ ]
+ ],
+ [
+ 'key' => 'taker_name',
+ 'label' => '收货人姓名',
+ 'value' => '',
+ 'type' => '',
+ 'status' => 1,
+ 'disabled' => false,
+ 'fontSize' => 'big',
+ 'fontWeight' => 'bold',
+ 'remark' => '',
+ ],
+ [
+ 'key' => 'taker_mobile',
+ 'label' => '收货人手机号',
+ 'value' => 'yes',
+ 'type' => 'select',
+ 'status' => 1,
+ 'disabled' => false,
+ 'fontSize' => 'big',
+ 'fontWeight' => 'bold',
+ 'remark' => '手机号脱敏可以有效保护用户隐私',
+ 'text' => '脱敏',
+ 'list' => [
+ 'yes' => '是',
+ 'no' => '否'
+ ]
+ ],
+ [
+ 'key' => 'taker_full_address',
+ 'label' => '收货人地址',
+ 'value' => '',
+ 'type' => '',
+ 'status' => 1,
+ 'disabled' => false,
+ 'fontSize' => 'big',
+ 'fontWeight' => 'bold',
+ 'remark' => '',
+ ],
+ [
+ 'key' => 'member_remark',
+ 'label' => '买家备注',
+ 'value' => '',
+ 'type' => '',
+ 'status' => 1,
+ 'disabled' => false,
+ 'fontSize' => 'normal',
+ 'fontWeight' => 'normal',
+ 'remark' => '',
+ ],
+ ]
+ ],
+ [
+ 'key' => 'bottom_info',
+ 'title' => '底部信息',
+ 'list' => [
+ [
+ 'key' => 'qrcode',
+ 'label' => '二维码',
+ 'placeholder' => '二维码内容',
+ 'value' => '',
+ 'type' => 'input',
+ 'status' => 1,
+ 'disabled' => false,
+ 'fontSize' => '',
+ 'fontWeight' => '',
+ 'remark' => '',
+ ],
+ [
+ 'key' => 'ticket_print_time',
+ 'label' => '小票打印时间',
+ 'value' => '',
+ 'type' => '',
+ 'status' => 1,
+ 'disabled' => false,
+ 'fontSize' => '',
+ 'fontWeight' => '',
+ 'remark' => '',
+ ],
+ [
+ 'key' => 'bottom_remark',
+ 'label' => '底部信息',
+ 'value' => '谢谢惠顾,欢迎下次光临!',
+ 'placeholder' => '',
+ 'type' => 'input',
+ 'status' => 1,
+ 'disabled' => false,
+ 'fontSize' => '',
+ 'fontWeight' => '',
+ 'remark' => '',
+ ],
+
+ ]
+ ]
+
+ ],
+ ],
+];
\ No newline at end of file
diff --git a/niucloud/addon/shop/app/dict/recharge/package_gift.php b/niucloud/addon/shop/app/dict/recharge/package_gift.php
new file mode 100644
index 000000000..1df68b790
--- /dev/null
+++ b/niucloud/addon/shop/app/dict/recharge/package_gift.php
@@ -0,0 +1,12 @@
+ [
+ 'name' => '赠送优惠券',
+ 'value' => [],
+ //用于充值编辑
+ 'edit_component'=>'/src/addon/shop/views/member/components/recharge-gift-coupon.vue',
+ //用于充值详情展示
+ 'detail_component' => '/src/addon/shop/views/member/components/recharge-detail-coupon.vue',
+ 'sort' => 3
+ ],
+];
diff --git a/niucloud/addon/shop/app/dict/schedule/schedule.php b/niucloud/addon/shop/app/dict/schedule/schedule.php
new file mode 100644
index 000000000..43fe29844
--- /dev/null
+++ b/niucloud/addon/shop/app/dict/schedule/schedule.php
@@ -0,0 +1,162 @@
+ 'shop_order_close',
+ 'name' => '未支付订单自动关闭',
+ 'desc' => '',
+ 'time' => [
+ 'type' => 'min',
+ 'min' => 1
+ ],
+ 'class' => 'addon\shop\app\job\order\OrderClose',
+ 'function' => ''
+ ],
+ [
+ 'key' => 'shop_order_close_allow_refund',
+ 'name' => '订单完成自动关闭售后',
+ 'desc' => '',
+ 'time' => [
+ 'type' => 'min',
+ 'min' => 1
+ ],
+ 'class' => 'addon\shop\app\job\order\OrderCloseAllowRefund',
+ 'function' => ''
+ ],
+ [
+ 'key' => 'shop_order_finish',
+ 'name' => '待收货订单自动完成',
+ 'desc' => '',
+ 'time' => [
+ 'type' => 'min',
+ 'min' => 1
+ ],
+ 'class' => 'addon\shop\app\job\order\OrderFinish',
+ 'function' => ''
+ ],
+ [
+ 'key' => 'shop_coupon_member_expire',
+ 'name' => '优惠券到期自动过期',
+ 'desc' => '',
+ 'time' => [
+ 'type' => 'min',
+ 'min' => 1
+ ],
+ 'class' => 'addon\shop\app\job\marketing\CouponMemberExpire',
+ 'function' => ''
+ ],
+ [
+ 'key' => 'shop_coupon_start',
+ 'name' => '优惠券限时自动开启',
+ 'desc' => '',
+ 'time' => [
+ 'type' => 'min',
+ 'min' => 1
+ ],
+ 'class' => 'addon\shop\app\job\marketing\CouponStart',
+ 'function' => ''
+ ],
+ [
+ 'key' => 'shop_coupon_end',
+ 'name' => '优惠券限时自动结束',
+ 'desc' => '',
+ 'time' => [
+ 'type' => 'min',
+ 'min' => 1
+ ],
+ 'class' => 'addon\shop\app\job\marketing\CouponEnd',
+ 'function' => ''
+ ],
+ [
+ 'key' => 'shop_coupon_send',
+ 'name' => '优惠券自动发放',
+ 'desc' => '',
+ 'time' => [
+ 'type' => 'min',
+ 'min' => 1
+ ],
+ 'class' => 'addon\shop\app\job\marketing\CouponSend',
+ 'function' => '',
+ 'params'=>['record_id'=>'']
+ ],
+ [
+ 'key' => 'shop_active_start',
+ 'name' => '营销活动自动开启',
+ 'desc' => '',
+ 'time' => [
+ 'type' => 'min',
+ 'min' => 1
+ ],
+ 'class' => 'addon\shop\app\job\marketing\ActiveStart',
+ 'function' => ''
+ ],
+ [
+ 'key' => 'shop_active_end',
+ 'name' => '营销活动自动结束',
+ 'desc' => '',
+ 'time' => [
+ 'type' => 'min',
+ 'min' => 1
+ ],
+ 'class' => 'addon\shop\app\job\marketing\ActiveEnd',
+ 'function' => ''
+ ],
+ [
+ 'key' => 'shop_manjiansong_start',
+ 'name' => '满减送自动开始',
+ 'desc' => '',
+ 'time' => [
+ 'type' => 'min',
+ 'min' => 1
+ ],
+ 'class' => 'addon\shop\app\job\marketing\ManjianStart',
+ 'function' => ''
+ ],
+ [
+ 'key' => 'shop_manjiansong_end',
+ 'name' => '满减送自动结束',
+ 'desc' => '',
+ 'time' => [
+ 'type' => 'min',
+ 'min' => 1
+ ],
+ 'class' => 'addon\shop\app\job\marketing\ManjianEnd',
+ 'function' => ''
+ ],
+ [
+ 'key' => 'shop_goods_statistical_update',
+ 'name' => '商品统计更新',
+ 'desc' => '',
+ 'time' => [
+ 'type' => 'day',
+ 'day' => 1,
+ 'min' => 1,
+ 'hour' => 0
+ ],
+ 'class' => 'addon\shop\app\job\goods\GoodsStatisticalUpdate',
+ 'function' => ''
+ ],
+ [
+ 'key' => 'shop_discount_start',
+ 'name' => '限时折扣自动开启',
+ 'desc' => '',
+ 'time' => [
+ 'type' => 'min',
+ 'min' => 1
+ ],
+ 'class' => 'addon\shop\app\job\marketing\DiscountStart',
+ 'function' => ''
+ ],
+ [
+ 'key' => 'shop_discount_end',
+ 'name' => '限时折扣自动结束',
+ 'desc' => '',
+ 'time' => [
+ 'type' => 'min',
+ 'min' => 1
+ ],
+ 'class' => 'addon\shop\app\job\marketing\DiscountEnd',
+ 'function' => ''
+ ],
+
+];
diff --git a/niucloud/addon/shop/app/dict/sow_community/package_gift.php b/niucloud/addon/shop/app/dict/sow_community/package_gift.php
new file mode 100644
index 000000000..86ca9f8d7
--- /dev/null
+++ b/niucloud/addon/shop/app/dict/sow_community/package_gift.php
@@ -0,0 +1,10 @@
+ [
+ 'name' => '赠送优惠券',
+ 'value' => [],
+ //用于编辑
+ 'edit_component'=>'/src/addon/shop/views/sow_community/components/sow-community-gift-coupon.vue',
+ 'sort' => 3
+ ],
+];
diff --git a/niucloud/addon/shop/app/event.php b/niucloud/addon/shop/app/event.php
new file mode 100644
index 000000000..1346f5aeb
--- /dev/null
+++ b/niucloud/addon/shop/app/event.php
@@ -0,0 +1,194 @@
+ [
+
+ ],
+ 'listen' => [
+ // 手机端初始化加载事件
+ 'initWap' => [
+ 'addon\shop\app\listener\config\initWapListener'
+ ],
+
+ // 添加/编辑商品之后的事件
+ 'AfterGoodsEdit' => [
+ 'addon\shop\app\listener\point_exchange\AfterGoodsEdit'
+ ],
+ // 订单创建
+ 'ShopOrderCreate' => [
+ 'addon\shop\app\listener\order\ShopOrderCreate',
+ ],
+ //订单创建时 优惠抵扣减免业务
+ 'ShopOrderDiscountCreate' => [
+ 'addon\shop\app\listener\point_exchange\ShopOrderDiscountCreate' //积分商城兑换
+ ],
+ //订单创建后
+ 'AfterShopOrderCreate' => [
+ 'addon\shop\app\listener\order\AfterShopOrderCreate',
+ 'addon\shop\app\listener\point_exchange\AfterShopOrderCreate',
+ ],
+
+ //订单支付后
+ 'AfterShopOrderPay' => [
+ 'addon\shop\app\listener\order\AfterShopOrderPay',
+ ],
+ //订单发货后
+ 'AfterShopOrderDelivery' => ['addon\shop\app\listener\order\AfterShopOrderDelivery'],
+ //订单收货后
+ 'AfterShopOrderFinish' => ['addon\shop\app\listener\order\AfterShopOrderFinish'],
+ //订单编辑价格后
+ 'AfterShopOrderEditPrice' => ['addon\shop\app\listener\order\AfterShopOrderEditPrice'],
+ //订单关闭后
+ 'AfterShopOrderClose' => [
+ 'addon\shop\app\listener\order\AfterShopOrderClose',
+ 'addon\shop\app\listener\point_exchange\AfterShopOrderClose', //积分商城业务
+ ],
+ //计算活动信息
+ 'ShopGoodsMarketCalculate' => [
+ 'addon\shop\app\listener\marketing\ShopNewcomerCalculate', //新人专享
+ ],
+ /***************************************************** 退款 start *****************************************************/
+ 'AfterShopOrderRefundApply' => ['addon\shop\app\listener\refund\AfterShopOrderRefundApply'],
+ 'AfterShopOrderRefundAuditApply' => ['addon\shop\app\listener\refund\AfterShopOrderRefundAuditApply'],
+ 'AfterShopOrderRefundAuditRefundGoods' => ['addon\shop\app\listener\refund\AfterShopOrderRefundAuditRefundGoods'],
+ 'AfterShopOrderRefundClose' => ['addon\shop\app\listener\refund\AfterShopOrderRefundClose'],
+ 'AfterShopOrderRefundDelivery' => ['addon\shop\app\listener\refund\AfterShopOrderRefundDelivery'],
+ 'AfterShopOrderRefundEdit' => ['addon\shop\app\listener\refund\AfterShopOrderRefundEdit'],
+ 'AfterShopOrderRefundEditDelivery' => ['addon\shop\app\listener\refund\AfterShopOrderRefundEditDelivery'],
+ 'AfterShopOrderRefundFinish' => [
+ 'addon\shop\app\listener\refund\AfterShopOrderRefundFinish',
+ ],
+ 'AfterShopOrderRefundActiveCreate' => ['addon\shop\app\listener\refund\AfterShopOrderRefundActiveCreate'],
+ /***************************************************** 退款 end *****************************************************/
+
+ 'ShopPromotion' => ['addon\shop\app\listener\app\ShopPromotionListener'],
+ 'WapIndex' => ['addon\shop\app\listener\WapIndexListener'],
+ 'BottomNavigation' => ['addon\shop\app\listener\BottomNavigationListener'],
+
+ //支付
+ 'PayCreate' => ['addon\shop\app\listener\pay\PayCreateListener'],
+ 'PaySuccess' => ['addon\shop\app\listener\pay\PaySuccessListener'],
+ 'PayTradeInfo' => ['addon\shop\app\listener\order\ShopOrderTradeInfoListener'], //订单交易信息
+ 'RefundSuccess' => ['addon\shop\app\listener\pay\RefundSuccessListener'],
+
+ 'NoticeData' => [
+ 'addon\shop\app\listener\notice_template\OrderPay',
+ 'addon\shop\app\listener\notice_template\OrderPayRemind',
+ 'addon\shop\app\listener\notice_template\OrderDelivery',
+ 'addon\shop\app\listener\notice_template\RefundAgree',
+ 'addon\shop\app\listener\notice_template\RefundRefuse',
+ ],
+ //优惠券
+ 'CouponReceiveType' => ['addon\shop\app\listener\coupon\CouponReceiveListener'],
+ 'CouponCheck' => ['addon\shop\app\listener\coupon\CouponCheckListener'],
+
+ //获取海报数据
+ 'GetPosterType' => ['addon\shop\app\listener\poster\ShopPosterType'],
+ 'GetPosterData' => ['addon\shop\app\listener\poster\ShopPoster'],
+
+ //导出数据类型
+ 'ExportDataType' => [
+ //订单列表导出
+ 'addon\shop\app\listener\order_export\ShopOrderExportTypeListener',
+ //订单项导出
+ 'addon\shop\app\listener\order_export\ShopOrderGoodsExportTypeListener',
+ //退款售后导出
+ 'addon\shop\app\listener\refund_export\ShopOrderRefundExportTypeListener',
+ //发票列表导出
+ 'addon\shop\app\listener\order_export\ShopInvoiceExportTypeListener',
+ ],
+ //导出数据源
+ 'ExportData' => [
+ //订单列表导出
+ 'addon\shop\app\listener\order_export\ShopOrderExportDataListener',
+ //订单项导出
+ 'addon\shop\app\listener\order_export\ShopOrderGoodsExportDataListener',
+ //退款售后导出
+ 'addon\shop\app\listener\refund_export\ShopOrderRefundExportDataListener',
+ //发票列表导出
+ 'addon\shop\app\listener\order_export\ShopInvoiceExportDataListener',
+ ],
+ //商城统计执行
+ 'StatExecute' => ['addon\shop\app\listener\stat\StatExecuteListener'],
+ //商城统计字段
+ 'StatField' => ['addon\shop\app\listener\stat\StatFieldListener'],
+ //核销
+ 'VerifyType' => ['addon\shop\app\listener\verify\VerifyTypeListener'],
+ 'VerifyCreate' => ['addon\shop\app\listener\verify\VerifyCreateListener'],
+ 'Verify' => ['addon\shop\app\listener\verify\VerifyListener'],
+ 'VerifyInfo' => ['addon\shop\app\listener\verify\VerifyInfoListener'],
+ 'VerifyCheck' => ['addon\shop\app\listener\verify\VerifyCheckListener'],
+
+ 'GetGoodsJoinInfo' => [
+ 'addon\shop\app\listener\marketing\GetGoodsJoinInfo',
+// 'addon\pintuan\app\listener\GetGoodsJoinInfo'
+ ],
+ 'ActiveSaveAfter' => [
+ 'addon\shop\app\listener\marketing\ShopActiveSaveAfter'
+ ],
+ //通过支付信息获取手机端订单详情路径
+ 'WapOrderDetailPath' => [
+ 'addon\shop\app\listener\order\WapOrderDetailPathListener',
+ ],
+
+ 'PrinterContent' => [
+ 'addon\shop\app\listener\printer\PrinterContentListener'
+ ],
+
+ //新人专享
+ 'NewcomerActiveJoin' => ['addon\shop\app\listener\marketing\NewcomerActiveJoinListener'],
+ //会员登录后事件
+ 'MemberLoginAfter' => ['addon\shop\app\listener\MemberLoginAfterListener'],
+
+ // 会员充值 赠送内容
+ 'RechargeGiftContent' => ['addon\shop\app\listener\recharge\GiftContentListener'],
+ // 会员充值成功后的事件
+ 'RechargeAfterListener' => ['addon\shop\app\listener\recharge\RechargeAfterListener'],
+
+ //获取宝贝数据
+ 'TreasureType' => ['addon\shop\app\listener\treasure\TreasureTypeListener'],
+ 'TreasureData' => ['addon\shop\app\listener\treasure\TreasureDataListener'],
+
+ //主题色
+ 'ThemeColor' => ['addon\shop\app\listener\diy\ThemeColorListener'],
+ //万能表单删除前
+ 'BeforeFormDelete' => ['addon\shop\app\listener\diy\BeforeFormDeleteListener'],
+ //查询营销列表
+ 'ShowMarketing' => [
+ 'addon\shop\app\listener\system\ShowMarketingListener'
+ ],
+ 'ShowCustomer' => [
+ 'addon\shop\app\listener\system\ShowCustomerListener'
+ ],
+ //获取商品展示价格
+ 'GoodsShowPrice' => ['addon\shop\app\listener\goods\GoodsShowPriceListener'],
+
+ // 种草奖励发放优惠券
+ 'SettleRewardListener' => ['addon\shop\app\listener\sow_community\SettleRewardListener'],
+
+ // 种草奖励优惠券
+ 'RuleContentListener' => ['addon\shop\app\listener\sow_community\RuleContentListener'],
+
+
+ //三方插件对接
+ //第三方通用插件订单备份
+ //同步订单到商城
+ 'ThirdAddonOrderBackUp' => ['addon\shop\app\listener\third_addon\order\BackUpThirdOrderListener'],
+ //获取订单后续操作路径 退款 服务
+ 'ThirdAddonOrderPath' => ['addon\shop\app\listener\third_addon\order\OrderServicePathListener'],
+ //输出当前插件/应用名称及标识
+ 'ThirdAddonOutputSource' => ['addon\shop\app\listener\third_addon\SupportAddonListener'],
+ 'ThirdAddonOutputData' => ['addon\shop\app\listener\third_addon\goods\GoodsOutPutDataListener'],
+ 'ThirdAddonOutputWhere' => ['addon\shop\app\listener\third_addon\goods\GoodsOutPutWhereInitListener'],
+ //商品详情
+ 'ThirdAddonOutputDataInfo' => ['addon\shop\app\listener\third_addon\goods\GoodsOutPutDataInfoListener' ],
+ //三方订单附加费用
+ 'ThirdAddonOrderAmount' => ['addon\shop\app\listener\third_addon\order\OrderAmountServiceListener'],
+
+
+ //获取商品配送费用
+ 'ThirdAddonOrderDelivery' => ['addon\shop\app\listener\third_addon\order\OrderDeliveryServiceListener'],
+ ],
+ 'subscribe' => [
+ ],
+];
diff --git a/niucloud/addon/shop/app/job/goods/GoodsEvaluateStat.php b/niucloud/addon/shop/app/job/goods/GoodsEvaluateStat.php
new file mode 100644
index 000000000..395fc9639
--- /dev/null
+++ b/niucloud/addon/shop/app/job/goods/GoodsEvaluateStat.php
@@ -0,0 +1,38 @@
+updateGoodsEvaluateNumBach($evaluate_ids);
+ return true;
+ } catch (\Exception $e) {
+ return false;
+ }
+ }
+
+}
diff --git a/niucloud/addon/shop/app/job/goods/GoodsStatisticalUpdate.php b/niucloud/addon/shop/app/job/goods/GoodsStatisticalUpdate.php
new file mode 100644
index 000000000..4b4023965
--- /dev/null
+++ b/niucloud/addon/shop/app/job/goods/GoodsStatisticalUpdate.php
@@ -0,0 +1,37 @@
+syncStatGoods();
+ return true;
+ } catch (\Exception $e) {
+ return false;
+ }
+ }
+
+}
diff --git a/niucloud/addon/shop/app/job/marketing/ActiveEnd.php b/niucloud/addon/shop/app/job/marketing/ActiveEnd.php
new file mode 100644
index 000000000..b9a1998b7
--- /dev/null
+++ b/niucloud/addon/shop/app/job/marketing/ActiveEnd.php
@@ -0,0 +1,48 @@
+where([
+ [ 'active_status', '=', ActiveDict::ACTIVE ],
+ ])->whereBetweenTime('end_time', 1, time())->column('active_id');//过滤end_time=0的情况,0表示活动永久有效
+
+ foreach ($ids as $k => $v) {
+ ( new CoreActiveService() )->end($v);
+ }
+
+ return true;
+ } catch (\Exception $e) {
+ Log::write('活动自动关闭error' . $e->getMessage() . $e->getFile() . $e->getLine());
+ return false;
+ }
+ }
+
+}
diff --git a/niucloud/addon/shop/app/job/marketing/ActiveEndAfter.php b/niucloud/addon/shop/app/job/marketing/ActiveEndAfter.php
new file mode 100644
index 000000000..c5ef8fa78
--- /dev/null
+++ b/niucloud/addon/shop/app/job/marketing/ActiveEndAfter.php
@@ -0,0 +1,36 @@
+where([ ['active_id', '=', $active_id] ])->findOrEmpty()->toArray();
+ event('ActiveEndAfter', $info);
+ return true;
+ } catch (\Exception $e) {
+ return false;
+ }
+ }
+
+}
diff --git a/niucloud/addon/shop/app/job/marketing/ActiveStart.php b/niucloud/addon/shop/app/job/marketing/ActiveStart.php
new file mode 100644
index 000000000..688242cc7
--- /dev/null
+++ b/niucloud/addon/shop/app/job/marketing/ActiveStart.php
@@ -0,0 +1,49 @@
+where([
+ ['active_status', '=', ActiveDict::NOT_ACTIVE],
+ ['start_time', '<=', time()]
+ ])->column('active_id');
+
+ foreach($ids as $k => $v){
+ (new CoreActiveService())->start($v);
+ }
+
+ return true;
+ } catch (\Exception $e) {
+ Log::write('活动自动开启error'.$e->getMessage().$e->getFile().$e->getLine());
+ return false;
+ }
+ }
+
+}
diff --git a/niucloud/addon/shop/app/job/marketing/ActiveStartAfter.php b/niucloud/addon/shop/app/job/marketing/ActiveStartAfter.php
new file mode 100644
index 000000000..b18eb91f6
--- /dev/null
+++ b/niucloud/addon/shop/app/job/marketing/ActiveStartAfter.php
@@ -0,0 +1,36 @@
+where([ ['active_id', '=', $active_id] ])->findOrEmpty()->toArray();
+ event('ActiveStartAfter', $info);
+ return true;
+ } catch (\Exception $e) {
+ return false;
+ }
+ }
+
+}
diff --git a/niucloud/addon/shop/app/job/marketing/CouponEnd.php b/niucloud/addon/shop/app/job/marketing/CouponEnd.php
new file mode 100644
index 000000000..3da0f2b12
--- /dev/null
+++ b/niucloud/addon/shop/app/job/marketing/CouponEnd.php
@@ -0,0 +1,48 @@
+where([
+ ['status', '=', CouponDict::NORMAL],
+ ['start_time', '>', 0],
+ ['end_time', '>', 0],
+ ['end_time', '<=', time()]
+ ])->column('id');
+ if(!empty($ids)){
+ //修改状态
+ (new CoreCouponService())->couponExpire($ids);
+ }
+ return true;
+ } catch (\Exception $e) {
+ return false;
+ }
+ }
+
+}
diff --git a/niucloud/addon/shop/app/job/marketing/CouponMemberExpire.php b/niucloud/addon/shop/app/job/marketing/CouponMemberExpire.php
new file mode 100644
index 000000000..022939ef1
--- /dev/null
+++ b/niucloud/addon/shop/app/job/marketing/CouponMemberExpire.php
@@ -0,0 +1,44 @@
+where([
+ ['status', '=', CouponMemberDict::WAIT_USE],
+ ['expire_time', '<=', time()]
+ ])->column('id');
+ if(!empty($ids)){
+ //过期
+ (new CoreCouponMemberService())->expire($ids);
+ }
+ return true;
+ } catch (\Exception $e) {
+ return false;
+ }
+ }
+
+}
diff --git a/niucloud/addon/shop/app/job/marketing/CouponSend.php b/niucloud/addon/shop/app/job/marketing/CouponSend.php
new file mode 100644
index 000000000..ee6fa8f38
--- /dev/null
+++ b/niucloud/addon/shop/app/job/marketing/CouponSend.php
@@ -0,0 +1,104 @@
+where([
+ ['id', '=', $record_id]
+ ])->update([
+ 'status' => CouponDict::SEND_STATUS_PROGRESS,
+ ]);
+ Db::startTrans();
+ try {
+ $records_info = (new CouponSendRecord())->where([
+ ['id', '=', $record_id]
+ ])->findOrEmpty()->toArray();
+ $memberIds = $this->getMemberIds($records_info['range_type'], $records_info['range_param']);
+ Log::write("CouponSend 发送优惠券id {$record_id} 会员id数组:" . json_encode($memberIds, 256));
+ $success_num = (new CoreCouponMemberService())->sendCoupon( $memberIds, $records_info['coupon_id'], $records_info['send_num']);
+ (new CouponSendRecord())->where([['id', '=', $record_id]])->update([
+ 'status' => CouponDict::SEND_STATUS_FINISH,
+ 'success_num' => $success_num,
+ 'end_time' => time(),
+ 'update_time' => time()
+ ]);
+ Db::commit();
+ return true;
+ } catch (\Exception $e) {
+ Log::error('CouponSend 发送优惠券失败' . $e->getMessage() . $e->getLine());
+ Db::rollback();
+ return false;
+ }
+ }
+
+ /**
+ * 获取发送用户数量
+ * @param $range_type
+ * @param $range_param
+ * @return array
+ * @throws \think\db\exception\DbException
+ */
+ public function getMemberIds($range_type, $range_param)
+ {
+ switch ($range_type) {
+ case CouponDict::SEND_RANGE_ALL:
+ $member_ids = (new Member())->where([
+ ['member_id', '>', 0]
+ ])->column('member_id');
+ break;
+ case CouponDict::SEND_RANGE_MEMBER:
+ $member_ids = $range_param['member_ids'];
+ break;
+ case CouponDict::SEND_RANGE_MEMBER_LEVEL:
+ $member_level = $range_param['member_level'];
+ $member_ids = (new Member())->where([
+ ['member_level', 'in', implode(',', $member_level)]
+ ])->column('member_id');
+ break;
+ case CouponDict::SEND_RANGE_MEMBER_LABEL:
+ $member_label = $range_param['member_label'];
+ $member_ids = (new Member())->where([
+ ['member_id', '>', 0]
+ ])->withSearch(['member_label'], ['member_label' => $member_label])->column('member_id');
+ break;
+ default:
+ $member_ids = 0;
+ break;
+ }
+ return array_values($member_ids ?? []) ?? [];
+ }
+}
diff --git a/niucloud/addon/shop/app/job/marketing/CouponStart.php b/niucloud/addon/shop/app/job/marketing/CouponStart.php
new file mode 100644
index 000000000..5c2b3ffe7
--- /dev/null
+++ b/niucloud/addon/shop/app/job/marketing/CouponStart.php
@@ -0,0 +1,48 @@
+where([
+ ['status', '=', CouponDict::WAIT_START],
+ ['start_time', '>', 0],
+ ['start_time', '<=', time()],
+ ['end_time', '>', time()]
+ ])->column('id');
+ if(!empty($ids)){
+ //修改状态
+ (new CoreCouponService())->couponNormal($ids);
+ }
+ return true;
+ } catch (\Exception $e) {
+ return false;
+ }
+ }
+
+}
diff --git a/niucloud/addon/shop/app/job/marketing/DiscountEnd.php b/niucloud/addon/shop/app/job/marketing/DiscountEnd.php
new file mode 100644
index 000000000..427c34449
--- /dev/null
+++ b/niucloud/addon/shop/app/job/marketing/DiscountEnd.php
@@ -0,0 +1,51 @@
+where([
+ ['status', '=', DiscountDict::ACTIVE],
+ ])->whereBetweenTime('end_time', 1, time())->column('discount_id');//过滤end_time=0的情况,0表示活动永久有效
+
+ (new Discount())->where([['discount_id', 'in', $ids], ['status', '=', DiscountDict::ACTIVE], ['end_time', '<=', time()]])->update(['status' => DiscountDict::END]);
+ (new DiscountGoods())->where([['discount_id', 'in', $ids]])->update(['status' => DiscountDict::END]);
+ (new DiscountService())->discountEndAfter($ids);
+ return true;
+ } catch (\Exception $e) {
+ Log::error('DiscountEnd 限时折扣自动关闭error' . $e->getMessage() . $e->getFile() . $e->getLine());
+ return false;
+ }
+ }
+
+}
diff --git a/niucloud/addon/shop/app/job/marketing/DiscountStart.php b/niucloud/addon/shop/app/job/marketing/DiscountStart.php
new file mode 100644
index 000000000..bd98a482a
--- /dev/null
+++ b/niucloud/addon/shop/app/job/marketing/DiscountStart.php
@@ -0,0 +1,48 @@
+where([
+ ['status', '=', DiscountDict::NOT_ACTIVE],
+ ['start_time', '<=', time()]
+ ])->column('discount_id');
+ (new Discount())->where([ ['discount_id', 'in', $ids], ['status', '=', DiscountDict::NOT_ACTIVE], ['start_time', '<=', time()] ])->update([ 'status' => DiscountDict::ACTIVE ]);
+ (new DiscountGoods())->where([ ['discount_id', 'in', $ids]])->update([ 'status' => DiscountDict::ACTIVE ]);
+ ( new DiscountService() )->discountStartAfter($ids);
+ return true;
+ } catch (\Exception $e) {
+ Log::write('限时折扣自动开启error'.$e->getMessage().$e->getFile().$e->getLine());
+ return false;
+ }
+ }
+
+}
diff --git a/niucloud/addon/shop/app/job/marketing/ManjianEnd.php b/niucloud/addon/shop/app/job/marketing/ManjianEnd.php
new file mode 100644
index 000000000..87b18a265
--- /dev/null
+++ b/niucloud/addon/shop/app/job/marketing/ManjianEnd.php
@@ -0,0 +1,45 @@
+where([
+ ['status', '=', ManjianDict::ACTIVE],
+ ])->whereBetweenTime('end_time', 1, time())->column('manjian_id');//过滤end_time=0的情况,0表示活动永久有效
+ (new Manjian())->where([['manjian_id', 'in', $ids], ['status', '=', ManjianDict::ACTIVE], ['end_time', '<=', time()]])->update(['status' => ManjianDict::END]);
+ (new ManjianGoods())->where([['manjian_id', 'in', $ids]])->update(['status' => ManjianDict::END]);
+ return true;
+ } catch (\Exception $e) {
+ Log::write('满减送自动关闭error' . $e->getMessage() . $e->getFile() . $e->getLine());
+ return false;
+ }
+ }
+
+}
diff --git a/niucloud/addon/shop/app/job/marketing/ManjianStart.php b/niucloud/addon/shop/app/job/marketing/ManjianStart.php
new file mode 100644
index 000000000..61493ef8e
--- /dev/null
+++ b/niucloud/addon/shop/app/job/marketing/ManjianStart.php
@@ -0,0 +1,46 @@
+where([
+ ['status', '=', ManjianDict::NOT_ACTIVE],
+ ['start_time', '<=', time()]
+ ])->column('manjian_id');
+ (new Manjian())->where([['manjian_id', 'in', $ids], ['status', '=', ManjianDict::NOT_ACTIVE], ['start_time', '<=', time()]])->update(['status' => ManjianDict::ACTIVE]);
+ (new ManjianGoods())->where([['manjian_id', 'in', $ids]])->update(['status' => ManjianDict::ACTIVE]);
+ return true;
+ } catch (\Exception $e) {
+ Log::write('满减送自动开启error' . $e->getMessage() . $e->getFile() . $e->getLine());
+ return false;
+ }
+ }
+
+}
diff --git a/niucloud/addon/shop/app/job/marketing/NewcomerSaveAfter.php b/niucloud/addon/shop/app/job/marketing/NewcomerSaveAfter.php
new file mode 100644
index 000000000..242a42470
--- /dev/null
+++ b/niucloud/addon/shop/app/job/marketing/NewcomerSaveAfter.php
@@ -0,0 +1,38 @@
+afterSave();
+ return true;
+ } catch (\Exception $e) {
+ return false;
+ }
+ }
+
+}
diff --git a/niucloud/addon/shop/app/job/order/OrderClose.php b/niucloud/addon/shop/app/job/order/OrderClose.php
new file mode 100644
index 000000000..f8ffd0e5c
--- /dev/null
+++ b/niucloud/addon/shop/app/job/order/OrderClose.php
@@ -0,0 +1,53 @@
+where([
+ ['status', '=', OrderDict::WAIT_PAY],
+ ['timeout', '<=', time()],
+ ['timeout', '>', 0]
+ ])->select();
+ if(!$list->isEmpty()){
+ foreach($list as $v){
+ $data['order_id'] = $v['order_id'];
+ try {
+ (new CoreOrderCloseService())->close($data);
+ } catch (\Throwable $e) {
+ Log::write(date('Y-m-d H:i:s'). ',订单自动关闭失败:'. $e->getMessage(). '_'. $e->getFile(). '_'. $e->getLine());
+ }
+ }
+ }
+ return true;
+ }
+
+}
diff --git a/niucloud/addon/shop/app/job/order/OrderCloseAllowRefund.php b/niucloud/addon/shop/app/job/order/OrderCloseAllowRefund.php
new file mode 100644
index 000000000..a0540e96a
--- /dev/null
+++ b/niucloud/addon/shop/app/job/order/OrderCloseAllowRefund.php
@@ -0,0 +1,70 @@
+where([
+ [ 'status', '=', OrderDict::FINISH ],
+ [ 'timeout', '<=', time() ],
+ [ 'is_enable_refund', '=', 1 ]
+ ])->select();
+ if (!$list->isEmpty()) {
+ //订单设置
+ $list->update([ 'is_enable_refund' => 0, 'timeout' => 0 ]);
+ $order_ids = array_column($list->toArray(), 'order_id');
+ //订单项设置
+ ( new OrderGoods() )->where([
+ [ 'order_id', 'in', $order_ids ]
+ ])->update([ 'is_enable_refund' => 0 ]);
+ //写日志
+ $log_data = [];
+ $lot_template = [
+ 'status' => OrderDict::FINISH,
+ 'main_type' => $main_type,//todo 可以是传入的
+ 'main_id' => $main_id,
+ 'type' => OrderDict::ORDER_CLOSE_ALLOW_REFUND_ACTION,
+ 'content' => '',
+ 'create_time' => time()
+ ];
+ foreach ($list as $v) {
+ $lot_template[ 'order_id' ] = $v[ 'order_id' ];
+ $log_data[] = $lot_template;
+ }
+ ( new CoreOrderLogService() )->addAll($log_data);
+ }
+
+ return true;
+ } catch (\Exception $e) {
+ return false;
+ }
+ }
+
+}
diff --git a/niucloud/addon/shop/app/job/order/OrderFinish.php b/niucloud/addon/shop/app/job/order/OrderFinish.php
new file mode 100644
index 000000000..bdf97225a
--- /dev/null
+++ b/niucloud/addon/shop/app/job/order/OrderFinish.php
@@ -0,0 +1,52 @@
+where([
+ ['status', '=', OrderDict::WAIT_TAKE],
+ ['timeout', '<=', time()],
+ ['timeout', '>', 0]
+ ])->select();
+ if(!$list->isEmpty()){
+ foreach($list as $v){
+ $data['order_id'] = $v['order_id'];
+ try {
+ (new CoreOrderFinishService())->finish($data);
+ } catch (\Throwable $e) {
+ Log::write(date('Y-m-d H:i:s'). ',订单自动收货完成失败:'. $e->getMessage(). '_'. $e->getFile(). '_'. $e->getLine());
+ }
+ }
+ }
+ return true;
+ }
+
+}
diff --git a/niucloud/addon/shop/app/job/order/OrderPayRemind.php b/niucloud/addon/shop/app/job/order/OrderPayRemind.php
new file mode 100644
index 000000000..849cef916
--- /dev/null
+++ b/niucloud/addon/shop/app/job/order/OrderPayRemind.php
@@ -0,0 +1,36 @@
+send('shop_order_pay_remind', ['order_id' => $order_id ]);
+ return true;
+ } catch (\Exception $e) {
+ return false;
+ }
+ }
+
+}
diff --git a/niucloud/addon/shop/app/job/order_event/OrderBatchDeliveryJob.php b/niucloud/addon/shop/app/job/order_event/OrderBatchDeliveryJob.php
new file mode 100644
index 000000000..f933084d3
--- /dev/null
+++ b/niucloud/addon/shop/app/job/order_event/OrderBatchDeliveryJob.php
@@ -0,0 +1,35 @@
+execute($id);
+ return true;
+ } catch (\Exception $e) {
+ return false;
+ }
+ }
+
+}
diff --git a/niucloud/addon/shop/app/job/order_event/OrderCloseAfter.php b/niucloud/addon/shop/app/job/order_event/OrderCloseAfter.php
new file mode 100644
index 000000000..65b03bd13
--- /dev/null
+++ b/niucloud/addon/shop/app/job/order_event/OrderCloseAfter.php
@@ -0,0 +1,31 @@
+$key($addon);
+ return true;
+ }
+
+ /**
+ * 订单统计
+ * @param $addon
+ * @return void
+ */
+ public function shopOrder($addon)
+ {
+// ['addon' =>, 'date' => ['year' => , 'month'=> , 'day' => , 'hour' => ], 'data' => ['shop_order_money' => 12, 'member' => 12]]
+ $orderModel = new Order();
+ $order_money = $orderModel->where([ [ 'status', '>', 0 ] ])->sum('order_money');
+ $param = [
+ 'addon' => $addon,
+ 'date' => [
+ 'year' => date('Y'),
+ 'month' => date('m'),
+ 'day' => date('d'),
+ 'hour' => date('H'),
+ ],
+ 'data' => [
+ 'order_money' => $order_money
+ ]
+ ];
+ ( new CoreStatService() )->add($param);
+
+ }
+
+ /**
+ * @param $addon
+ * @return void
+ */
+ public function shopRechargeOrder($addon)
+ {
+
+ }
+
+}
diff --git a/niucloud/addon/shop/app/lang/en/api.php b/niucloud/addon/shop/app/lang/en/api.php
new file mode 100644
index 000000000..6dd355233
--- /dev/null
+++ b/niucloud/addon/shop/app/lang/en/api.php
@@ -0,0 +1,4 @@
+ '订单不存在',
+ 'SHOP_ORDER_IS_INVALID' => '订单已失效',
+ 'SHOP_ONLY_WAIT_TAKE_CAN_BE_TAKE' => '只有待收货的订单才可以收货',
+ 'SHOP_ONLY_WAIT_DELIVERY_CAN_BE_DELIVERY' => '只有待发货的订单才可以发货',
+ 'SHOP_ONLY_WAIT_PAY_CAN_BE_PAY' => '只有待支付的订单可以支付',
+ 'SHOP_GOODS_CATEGORY_NOT_EXIST' => '分类不存在',
+ 'SHOP_GOODS_CATEGORY_EXIST_CHILD' => '当前分类存在下级,不可修改为该上级',
+ 'SHOP_GOODS_CATEGORY_EXIST_GOODS' => '当前分类下存在商品,不可删除',
+ 'SHOP_GOODS_NOT_EXIST' => '商品不存在',
+ 'SHOP_GOODS_LABEL_NAME_REPEAT'=>'标签名称重复',
+ 'SHOP_GOODS_LABEL_IN_USE'=>'该标签正在使用中',
+ 'NOT_SUPPORT_DELIVERY_TYPE' => '不支持选择的配送方式',
+ 'NOT_SUPPORT_DELIVERY_ADDRESS' => '所选的收货地址不支持配送',
+ 'NOT_SELECT_ADDRESS' => '需要先选择收货地址',
+ 'NOT_SELECT_STORE' => '请选择自提点',
+ 'NOT_NEED_DELIVERY_START_PRICE' => '未达到起送费用',
+ 'EXIST_ORDER_NOT_DELETE_GOODS' => '存在未完成的订单,无法删除商品',
+ 'EXIST_ORDER_NOT_EDIT_GOODS' => '存在未完成的订单,无法编辑商品',
+ 'COUPON_STOCK_INSUFFICIENT' => '优惠券已领完',
+ 'COUPON_NOT_EXIST' => '优惠券不存在',
+ 'COUPON_INVALID' => '优惠券已失效',
+ 'COUPON_CAN_NOT_MANUAL_RECEIVE' => '该优惠券不可手动领取',
+ 'COUPON_RECEIVE_NOT_TIME' => '优惠券不在领取时间范围内',
+ 'COUPON_RECEIVE_EXCESS' => '已领取数量超过限制领取数量,不可领取',
+ 'COUPON_RECEIVE_TYPE_NOT_EXIST' => '优惠券领取方式有误',
+ 'COUPON_RECEIVE_SUCCESS' => '领取成功',
+ 'MEMBER_ALREADY_COLLECT' => '已收藏,不可重复收藏',
+ 'CANCEL_COLLECT_SUCCESS' => '取消收藏成功',
+
+ 'SHOP_COUPON_IS_USED_OR_EXIST' => '优惠券不存在或已使用',
+ 'SHOP_COUPON_VALID_END_TIME_NOT_ALLOW_LT_START_TIME' => '优惠券的有效期结束时间不能小于当前时间',
+ 'SHOP_COUPON_IN_USE_NOT_ALLOW_EDIT' => '优惠券正在参与营销活动,禁止修改',
+ 'SHOP_COUPON_IN_USE_NOT_ALLOW_DEL' => '优惠券已有用户领取,禁止删除',
+ 'SHOP_GOODS_NOT_HAS_DEFAULT_SPEC' => '商品缺少默认规格',
+ 'SHOP_GOODS_DELISTED' => '此商品已下架',
+ 'SHOP_GOODS_EVALUATE_SUCCESS' => '评价成功',
+ 'SHOP_GOODS_PARTICIPATE_IN_ACTIVE_DISABLED_EDIT' => '商品正在参与营销活动,禁止修改',
+ 'SELECT_AUDIT_EVALUATE' => '请选择待审核评价',
+
+
+ 'SHOP_THE_LINE_ITEM_SUBTOTAL_CAN_T_BE_LESS_THAN_0' => '订单项小计总额不能小于0',
+ 'SHOP_THE_SHIPPING_FEE_CANNOT_BE_LESS_THAN_0' => '运费不能小于0',
+ 'SHOP_ONLY_PENDING_ORDERS_CAN_BE_REPRICED' => '只有待支付的订单可以改价',
+ 'SHOP_THE_AVAILABLE_SHIPPING_RATES_AREN_T_CONFIGURED' => '未配置可用的运费模板',
+
+ 'SHOP_ONLY_PENDING_ORDERS_EDIT_TAKER' => '只有待支付或待发货的订单可以修改配送地址',
+ 'SHOP_VIRTUAL_ORDERS_EDIT_TAKER' => '虚拟商品订单不可以修改配送地址',
+ 'EXPRESS_FIELD_EMPTY' => '地址信息有误',
+ 'GOODS_NOT_DELIVERY_TYPE' => '当前商品不支持该配送方式',
+ 'DELIVERY_TYPE_NOT_OPEN' => '商家未开启该配送方式',
+
+ 'SHOP_THE_ITEM_IS_BEING_REFUNDED_OR_HAS_BEEN_REFUNDED' => '当前商品项存在退款',
+
+ 'NOT_GET_SET_TYPE' => '未获取到设置类型',
+ 'NOT_GET_SHOP_INFO' => '未获取到商品信息',
+
+ /********************************************* 订单相关 start ****************************************************/
+ 'SHOP_ORDER_HAS_REFUNDING_NOT_ALLOW_FINISH' => '订单中存在退款,无法收货',
+ 'SHOP_ORDER_IS_PAY_FINISH' => '订单已支付',
+ 'SHOP_ORDER_IS_CLOSED' => '订单已关闭',
+ 'SHOP_ORDER_STATUS_NOT_SUPPORT_ACTION' => '当前的操作与订单状态不符',
+ 'SHOP_ORDER_COUPON_EXPIRE_OR_NOT_FOUND' => '优惠券已使用或已过期',
+ 'SHOP_ORDER_COUPON_EXPIRE' => '当前优惠券已过期',
+ 'SHOP_ORDER_COUPON_NOT_SUPPORT_GOODS' => '当前优惠券在本单不可用',
+ 'SHOP_ORDER_COUPON_NOT_SUPPORT_MIN_MONEY' => '未达到当前优惠券的最低使用条件',
+ 'SHOP_ORDER_PLEASE_SELECT_DELIVERY_TYPE' => '请选择正确的配送方式',
+ 'SHOP_ORDER_PLEASE_SELECT_DELIVERY_EMPTY_LNG_LAT' => '所选同城配送没有设置地图定位',
+ 'SHOP_ORDER_CARTS_EXPIRE' => '购物车数据已过期',
+ 'SHOP_ORDER_BUYER_NOT_FOUND' => '找不到买家',
+ 'SHOP_ORDER_BUYER_LOCKED' => '该会员已被锁定,请联系商家',
+ 'SHOP_ORDER_DELIVERY_NOT_ALLOW_REFUND_OR_DELIVERY_FINISH' => '存在退款或已发货的商品不能发货',
+ 'SHOP_ORDER_DELIVERY_ALLOW_ONE_GOODS_TYPE' => '一次发货只能存在一种商品类型的订单项',
+ 'SHOP_ORDER_DELIVERY_VIRTUAL_ALLOW_VIRTUAL_DELIVERY' => '虚拟商品只支持虚拟发货',
+ 'SHOP_ORDER_DELIVERY_TYPE_NOT_ORDER_DELIVERY_TYPE' => '发货方式需要与订单的配送方式相匹配',
+ 'SHOP_ORDER_COUPON_SUPPORT_GOODS' => '没有适用的商品',
+ 'SHOP_ORDER_COUPON_NOT_CONDITION' => '未达到最低可使用金额',
+ 'SHOP_ORDER_DELIVERY_SUCCESS' => '发货成功',
+ 'SHOP_ORDER_DELIVERY_EXPRESS_NUMBER_EXITS' => '物流单号不能重复',
+ 'NOT_CONFIGURED_LOCAL_DELIVERY' => '商家未配置同城配送',
+ 'NOT_CONFIGURED_DELIVERY_TYPE' => '商家尚未配置配送方式',
+ 'NOT_CONFIGURED_DELIVERY_KD100' => '快递100配送接口参数未配置',
+
+ 'SHOP_ELECTRONIC_SHEET_API_EMPTY' => '未配置电子面单接口',
+ 'SHOP_ELECTRONIC_SHEET_TEMPLATE_FOUND' => '电子面单模板不存在',
+
+ 'SHOP_ADDRESS_DEFAULT_EMPTY' => '商家未设置默认地址',
+
+ 'SHOP_ORDER_GOODS_INSUFFICIENT' => '商品库存不足',
+ 'SHIPPING_TEMPLATE_IN_USE' => '运费模板有商品正在使用中不能删除',
+
+ //虚拟订单
+ 'SHOP_ORDER_ITEM_HAS_BEEN_WRITTEN_OFF_OR_EXPIRED' => '商品已核销或已过期',
+ 'SHOP_ORDER_HAS_BEEN_CLOSED_OR_COMPLETED' => '订单已关闭或已完成!',
+ 'SHOP_GOODS_CURRENT_PRODUCT_DOES_NOT_SUPPORT_WRITE_OFF' => '当前商品不支持核销',
+ 'SHOP_ORDER_MAXIMUM_NUMBER_OF_WRITE_OFFS_HAS_BEEN_REACHED' => '已达到最大核销次数',
+ 'SHOP_ORDER_ITEM_HAS_EXPIRED' => '商品已过期',
+ /********************************************* 订单相关 end ****************************************************/
+ /********************************************* 订单退款 start ****************************************************/
+ 'SHOP_ORDER_REFUND_IS_INVALID' => '退款已失效',
+ 'SHOP_ORDER_REFUND_IS_INVALID_OR_FINISH' => '退款已完成或已关闭',
+ 'SHOP_ORDER_REFUND_WAIT_PAY_OR_CLOSE' => '退款未支付或已关闭',
+ 'SHOP_ORDER_REFUND_IS_REFUND_FINISH' => '订单已退款或存在未完成的退款',
+ 'SHOP_ORDER_REFUND_MONEY_GT_ORDER_MONEY' => '退款金额不能大于可退款总额',
+ 'SHOP_ORDER_REFUND_MONEY_LESS_THAN_ZERO' => '退款金额不能小于0',
+ 'SHOP_ORDER_REFUND_STATUS_NOT_SUPPORT_ACTION' => '当前的操作与退款状态不符',
+ 'SHOP_ORDER_IS_NOT_ENABLE_REFUND' => '订单不允许退款',
+ 'SHOP_ORDER_REFUND_SELECT_ADDRESS' => '请选择退货地址',
+ 'SHOP_ORDER_REFUND_IS_ONLY_WAIT_REFUND_GOODS' => '只有待确认退货请求才可以审核',
+ 'SHOP_ORDER_REFUND_IS_ONLY_WAIT_REFUND' => '只有待确认退款请求才可以审核',
+ 'SHOP_ORDER_BUYER_APPLY_REFUND' => '买家申请退款',
+ 'SHOP_ORDER_STORE_ACTIVE_REFUND' => '卖家主动退款',
+ 'SHOP_ORDER_REFUND_DELIVERY_NOT_ALLOW_REFUND_GOODS' => '待发货的商品项不允许退货退款',
+ 'SHOP_ORDER_DELETE_STATUS_ERROR' => '删除订单中有未关闭订单:%s',
+ /********************************************* 订单退款 end ****************************************************/
+
+
+ 'INVOICE_NOT_EXIST' => '发票不存在',
+ 'INVOICE_IS_EXIST' => '发票已存在',
+ 'INVOICED' => '已开票',
+ 'INVOICE_CANCEL_ERROR' => '取消申请失败',
+ 'INVOICE_HAS_ORDER_APPLY' => '当前选择订单中已有订单开具发票',
+
+
+ /********************************************* 活动start ****************************************************/
+ 'END_TIME_NOT_LESS_CURRENT_TIME' => '活动结束时间不能小于当前时间',
+ 'ACTIVE_GOODS_NOT_EMPTY' => '请选择参与活动商品',
+ 'ACTIVE_GOODS_SKU_NOT_EMPTY' => '商品规格不能为空',
+ 'ACTIVE_NOT_FOUND' => '活动未找到',
+ 'ACTIVE_NOT_EDIT' => '活动不可编辑',
+ 'ACTIVE_GOODS_NOT_REPEAR' => '同一商品在一个时间段内只能参加一个限时折扣活动',
+ 'ACTIVE_NOT_DELETE' => '进行中活动不能直接删除',
+ 'ACTIVE_GOODS_DISCOUNT_TYPE_NOT_EMPTY' => '折扣类型不能为空',
+ 'ACTIVE_GOODS_DISCOUNT_TYPE_ERROR' => '折扣类型错误',
+ 'ACTIVE_GOODS_DISCOUNT_PRICE_NOT_EMPTY' => '折扣价格discount_price不能为空',
+ 'ACTIVE_GOODS_SPECIFY_PRICE_NOT_EMPTY' => '促销价不能为空',
+ 'ACTIVE_GOODS_DISCOUNT_RATE_NOT_EMPTY' => '打折折扣不能为空',
+ 'ACTIVE_GOODS_REDUCE_MONEY_NOT_EMPTY' => '减钱金额不能为空',
+ 'ACTIVE_IS_ENABLED_NOT_EMPTY' => 'is_enabled必传',
+ /********************************************* 活动end ****************************************************/
+
+ /********************************************* 积分商城start ****************************************************/
+ 'EXCHANGE_GOODS_CONFIRM_TYPE' => '请确认兑换的类型',
+ 'EXCHANGE_GOODS_POINT_GREATER_THAN_ZERO' => '商品兑换积分要大于零',
+ 'EXCHANGE_GOODS_STOCK_GREATER_THAN_ZERO' => '商品兑换库存要大于零',
+ 'EXCHANGE_GOODS_NOT_EMPTY' => '请选择参与活动商品',
+ 'EXCHANGE_COUPON_NOT_EMPTY' => '请选择要参与的优惠券',
+ 'EXCHANGE_COUPON_NOT_EXIST' => '优惠券不存在',
+ 'EXCHANGE_BALANCE_GREATER_THAN_ZERO' => '商品兑换余额要大于零',
+ 'EXCHANGE_DATA_NOT_FOUND' => '积分信息活动未找到',
+ 'EXCHANGE_ACTIVITY_REMOVE' => '此积分商品已经下架',
+ 'EXCHANGE_GOODS_ACTIVITY_EXISTING' => '此商品已经参与积分兑换活动了',
+ 'EXIST_NOT_DOWN_ACTIVE' => '存在未下架活动',
+ /********************************************* 积分商城end ****************************************************/
+
+ /********************************************* 订单业务 *****************************************************/
+ 'SHOP_ORDER_EXCHANGE_EXCEEDING_LIMIT' => '此积分商品超出单次限购数量',
+ 'SHOP_ORDER_EXCHANGE_INSUFFICIENT_EXCHANGE_QUANTITY' => '此积分商品可兑换数量不足',
+ 'SHOP_ORDER_EXCHANGE_POINT_INSUFFICIENT' => '账户积分不足',
+
+ /********************************************* 新人专享start ****************************************************/
+ 'ACTIVE_GOODS_NEWCOMER_PRICE_NOT_EMPTY' => '新人价不能为空',
+ /********************************************* 新人专享end ****************************************************/
+
+ /********************************************* 商品排行榜start ****************************************************/
+ 'SHOP_RANK_NOT_EXIST' => '商品榜单不存在',
+ /********************************************* 商品排行榜end ****************************************************/
+
+ /********************************************* 满减送start ****************************************************/
+ 'MANJIANSONG_GOODS_NOT_REPEAR' => '同一商品在一个时间段内只能参加一个满减送活动',
+ 'MANJIANSONG_ALL_GOODS_EXIT' => '当前时间段已存在类型为全部商品参与的满减送活动,不可再添加其它满减送活动',
+ 'MANJIANSONG_CLOSED' => '满减送活动已关闭',
+ 'MANJIANSONG_NOT_FOUND' => '满减送活动未找到',
+ 'MANJIAN_TIME_HINT' => '已有互斥类型活动存在(仅针对指定商品参与的类型活动,同一时间段内可以同时有多个开展。)',
+ /********************************************* 满减送end ****************************************************/
+
+ /********************************************* 限时折扣start ****************************************************/
+ 'DISCOUNT_END_TIME_NOT_LESS_CURRENT_TIME' => '活动结束时间不能小于当前时间',
+ 'DISCOUNT_GOODS_NOT_EMPTY' => '请选择参与活动商品',
+ 'DISCOUNT_GOODS_SKU_NOT_EMPTY' => '商品规格不能为空',
+ 'DISCOUNT_NOT_FOUND' => '活动未找到',
+ 'DISCOUNT_NOT_EDIT' => '活动不可编辑',
+ 'DISCOUNT_GOODS_NOT_REPEAR' => '同一商品在一个时间段内只能参加一个限时折扣活动',
+ 'DISCOUNT_NOT_DELETE' => '进行中活动不能直接删除',
+ 'DISCOUNT_GOODS_DISCOUNT_TYPE_NOT_EMPTY' => '折扣类型不能为空',
+ 'DISCOUNT_GOODS_DISCOUNT_TYPE_ERROR' => '折扣类型错误',
+ 'DISCOUNT_GOODS_DISCOUNT_PRICE_NOT_EMPTY' => '折扣价格discount_price不能为空',
+ 'DISCOUNT_GOODS_SPECIFY_PRICE_NOT_EMPTY' => '促销价不能为空',
+ 'DISCOUNT_GOODS_DISCOUNT_RATE_NOT_EMPTY' => '打折折扣不能为空',
+ 'DISCOUNT_GOODS_REDUCE_MONEY_NOT_EMPTY' => '减钱金额不能为空',
+ 'DISCOUNT_IS_ENABLED_NOT_EMPTY' => 'is_enabled必传',
+ /********************************************* 限时折扣end ****************************************************/
+
+];
\ No newline at end of file
diff --git a/niucloud/addon/shop/app/lang/zh-cn/dict.php b/niucloud/addon/shop/app/lang/zh-cn/dict.php
new file mode 100644
index 000000000..aea28362c
--- /dev/null
+++ b/niucloud/addon/shop/app/lang/zh-cn/dict.php
@@ -0,0 +1,359 @@
+ [
+ 'num' => '按件',
+ 'weight' => '按重量',
+ 'volume' => '按体积'
+ ],
+ 'dict_shop_goods' => [
+ 'real' => '实物商品',
+ 'real_desc' => '物流发货',
+ 'virtual' => '虚拟商品',
+ 'virtual_desc' => '无需物流'
+ ],
+ 'dict_shop_app_manage' => [
+ 'coupon' => '优惠券',
+ 'marketing' => '营销活动',
+ ],
+ 'dict_shop_order' => [
+ 'status_wait_pay' => '待支付',
+ 'status_wait_shipping' => '待发货',
+ 'status_wait_pickup' => '待提货',
+ 'status_wait_take' => '待收货',
+ 'status_finish' => '已完成',
+ 'status_close' => '已关闭'
+ ],
+ 'dict_shop_delivery_type' => [
+ 'express' => '物流配送',
+ 'local_delivery' => '同城配送',
+ 'store' => '门店自提',
+ 'virtual' => '虚拟发货',
+ 'none_express' => '无需物流'
+ ],
+ 'dict_shop_delivery_store_time_interval' => [
+ '30' => '30分钟',
+ '60' => '1小时',
+ '90' => '90分钟',
+ '120' => '2小时',
+ ],
+
+ 'dict_shop_coupon' => [
+ 'user' => '手动领取',
+ 'grant' => '后台或活动发放',
+ 'all' => '通用券',
+ 'category' => '品类券',
+ 'goods' => '商品券',
+ 'wait_start' => '未开始',
+ 'normal' => '进行中',
+ 'expire' => '已过期',
+ 'invalid' => '已失效',
+ ],
+ 'dict_shop_member_coupon' => [
+ 'wait_use' => '待使用',
+ 'used' => '已使用',
+ 'expire' => '已过期',
+ 'invalid' => '已失效',
+ 'send' => '后台发放',
+ 'receive' => '用户手动领取'
+ ],
+ 'dict_shop_send_coupon_range' => [//后台发送优惠券范围类型
+ 'all' => '全部会员',
+ 'member' => '选择会员',
+ 'member_level' => '按会员等级',
+ 'member_label' => '按会员标签',
+ ],
+ 'dict_shop_send_coupon_range_type_desc' => [//后台发送优惠券范围类型描述
+ 'all' => '全部会员',
+ 'member' => '指定会员',
+ 'member_level' => '指定会员等级',
+ 'member_label' => '指定会员标签',
+ ],
+ 'dict_shop_send_coupon_status' => [//后台发送优惠券状态
+ 'wait' => '待发放',
+ 'progress' => '发放中',
+ 'finish' => '发放完成',
+ ],
+ 'dict_wap_index' => [
+ 'shop' => '商城',
+ 'shop_desc' => '商品购买,配送'
+ ],
+ 'dict_shop_order_log' => [
+ 'store' => '商家',
+ 'member' => '会员',
+ 'system' => '系统'
+ ],
+ 'dict_shop_goods_evaluate' => [
+ 'audit_no' => '无需审核',
+ 'audit' => '待审核',
+ 'audit_adopt' => '审核通过',
+ 'audit_refuse' => '审核拒绝'
+ ],
+ 'dict_shop_order_action' => [
+ 'order_create_action' => '订单创建',
+ 'order_pay_action' => '订单支付',
+ 'order_close_action' => '订单关闭',
+ 'order_delivery_action' => '订单发货',
+ 'order_finish_action' => '订单完成',
+ 'order_remark_action' => '订单商家备注',
+ 'order_close_allow_refund' => '订单自动关闭售后',
+ 'order_edit_price_action' => '订单改价',
+ ],
+ 'dict_shop_invoice' => [
+ 'header_type_company' => '企业',
+ 'header_type_person' => '个人',
+ 'common' => '普票',
+ 'sprcial' => '专票',
+ 'wait_open' => '未生效',
+ 'wait_audit' => '待审核',
+ 'open' => '已生效',
+ 'wait_invoice' => '待开票',
+ 'invoiced' => '已开票',
+ ],
+ 'dict_shop_order_refund_status' => [
+ 'buyer_apply_wait_store' => '买家申请售后',
+ 'store_agree_refund_goods_apply_wait_buyer' => '商家同意售后',
+ 'store_refuse_refund_goods_apply_wait_buyer' => '商家拒绝售后',
+ 'buyer_refund_goods_wait_store' => '买家已退货',
+ 'store_refuse_take_refund_goods_wait_buyer' => '商家拒绝收货',
+ 'store_agree_refund_wait_transfer' => '同意售后申请',
+ 'store_refund_transfering' => '转账中',
+ 'finish' => '退款成功',
+ 'close' => '退款关闭',
+ 'shop_active_close_refund' => '商家关闭售后'
+ ],
+ 'dict_shop_order_close_type' => [
+ 'shop_close' => '后台关闭',
+ 'buyer_close' => '用户关闭',
+ 'auto_close' => '未支付自动关闭',
+ 'refund_close' => '退款完成关闭',
+ ],
+ 'dict_diy' => [
+ 'shop_component_type_basic' => '商城组件',
+ 'shop_goods_detail_component_type_basic' => '商品详情组件',
+ 'page_shop_index' => '商城首页',
+ 'page_shop_member_index' => '商城个人中心',
+ 'page_shop_point_index' => '积分商城',
+ 'page_shop_detail' => '商品详情',
+
+ 'shop_title' => '商城',
+ 'shop_link' => '商城系统',
+ 'shop_link_basic' => '商城链接',
+ 'shop_link_index' => '商城首页',
+ 'shop_link_goods_category' => '商品分类',
+ 'shop_link_goods_list' => '商品列表',
+ 'shop_link_goods_rank' => '商品排行榜',
+ 'shop_link_goods_search' => '商品搜索',
+ 'shop_link_goods_cart' => '购物车',
+ 'page_link_member_index' => '商城个人中心',
+ 'shop_link_coupon_list' => '优惠券列表',
+ 'shop_link_my_coupon' => '我的优惠券',
+ 'shop_link_my_goods_collect' => '商品收藏',
+ 'shop_link_my_goods_browse' => '我的足迹',
+ 'shop_link_order_list' => '订单列表',
+ 'shop_link_order_refund_list' => '退款列表',
+ 'shop_link_point_index' => '积分商城',
+ 'shop_link_point_list' => '积分商品列表',
+ 'shop_link_point_order_list' => '积分兑换记录',
+ 'shop_link_discount_list' => '限时折扣列表',
+ 'shop_link_newcomer_list' => '新人专享',
+ 'shop_link_goods_select' => '选择商品',
+ 'shop_link_goods_category_select' => '商品分类',
+ 'shop_link_coupon_select' => '优惠券',
+ 'shop_link_point_exchange_select' => '积分商品',
+ 'shop_link_goods_rank_select' => '商品榜单',
+ 'shop_link_invoice_list' => '发票列表'
+ ],
+ 'dict_diy_poster' => [
+ 'shop_goods_component_type_basic' => '商品组件',
+ ],
+ 'dict_diy_form' => [
+ 'shop_component_type_basic' => '商城表单组件',
+ 'type_goods_detail' => '商品表单',
+ 'type_order_payment' => '待付款表单',
+ ],
+ 'dict_shop_delivery_status' => [
+ 'wait_delivery' => '待发货',
+ 'delivery' => '配送中',
+ 'delivery_finish' => '已发货',
+ 'taked' => '已收货'
+ ],
+ 'dict_shop_order_refund_action' => [
+ 'apply' => '买家申请退款',
+ 'edit_apply' => '买家修改退款',
+ 'delivery' => '买家退货',
+ 'edit_delivery' => '买家修改退货',
+ 'agree_audit_apply' => '卖家同意退款',
+ 'refuse_audit_apply_action' => '卖家拒绝退款申请',
+ 'agree_audit_refund_goods' => '卖家同意退货',
+ 'refuse_audit_refund_goods' => '卖家拒绝退货',
+ 'active_refund' => '卖家主动退款',
+ 'shop_active_refund' => '商家主动退款',
+ 'finish' => '退款完成',
+ 'close' => '关闭退款'
+ ],
+
+ 'dict_shop_order_refund_reason' => [
+ 'delivery_timeout' => '未按约定时间发货',
+ 'buy_more_or_dislike' => '拍错/多拍/不喜欢',
+ 'negotiation_completed' => '协商一致退款',
+ 'other' => '其他',
+ ],
+
+
+ 'dict_shop_order_refund_type' => [
+ 'only_refund' => '仅退款',
+ 'return_and_refund_goods' => '退款退货'
+ ],
+ 'dict_shop_order_refund' => [
+ 'normal' => '正常',
+ 'refunding' => '退款中',
+ 'refund_finish' => '退款完成'
+ ],
+
+ 'dict_shop_active_status' => [
+ 'not_active' => '未开始',
+ 'active' => '进行中',
+ 'end' => '已结束',
+ 'close' => '已关闭'
+ ],
+ 'dict_shop_active_class' => [
+ 'discount' => '限时折扣',
+ 'exchange' => '积分商城',
+ 'manjiansong' => '满减送',
+ 'newcomer_discount' => '新人专享',
+ 'giftcard' => '礼品卡',
+ 'pintuan' => '拼团'
+ ],
+ 'dict_shop_active_type' => [
+ 'shop' => '店铺活动',
+ 'goods' => '商品活动',
+ 'member' => '会员活动',
+ ],
+ 'dict_shop_active_goods_type' => [
+ 'single' => '单品',
+ 'independent' => '独立商品',
+ 'shop' => '店铺整体商品',
+ ],
+
+ 'dict_shop_point_exchange_type' => [
+ 'goods' => '商品',
+ 'coupon' => '优惠券',
+ 'balance' => '余额',
+ ],
+
+ 'dict_shop_manjian_condition_type' => [
+ 'over_n_yuan' => '满N元',
+ 'over_n_piece' => '满N件'
+ ],
+
+ 'dict_shop_manjian_goods_type' => [
+ 'all_goods' => '全部商品参与',
+ 'selected_goods' => '指定商品参与',
+ 'selected_goods_not' => '指定商品不参与'
+ ],
+
+ 'dict_shop_manjian_join_member_type' => [
+ 'all_member' => '所有会员参与',
+ 'selected_member_level' => '指定会员等级',
+ 'selected_member_label' => '指定会员标签'
+ ],
+
+ 'dict_shop_manjian_rule_type' => [
+ 'ladder' => '阶梯优惠',
+ 'cycle' => '循环优惠',
+ ],
+
+ 'dict_shop_manjian_status' => [
+ 'not_active' => '未开始',
+ 'active' => '进行中',
+ 'end' => '已结束',
+ 'close' => '已关闭',
+ ],
+
+ 'dict_member' => [
+ 'account_point_exchange_close' => '兑换订单关闭',
+ 'account_point_exchange_order' => '兑换订单消费',
+ 'account_point_exchange_refund' => '兑换订单售后',
+ 'account_point_consume_reward' => '下单奖励',
+ 'account_point_manjian_gift_give' => '满减送活动赠品发放',
+ 'account_point_manjian_gift_back' => '满减送活动赠品退还',
+ 'account_balance_manjian_gift_give' => '满减送活动赠品发放',
+ 'account_balance_manjian_gift_back' => '满减送活动赠品退还',
+ 'recharge_point_give' => '会员充值积分发放',
+ 'account_point_sow_community_settle_reward' => '种草奖励发放',
+ 'account_balance_sow_community_settle_reward' => '种草奖励发放',
+ ],
+
+ 'dict_shop_delivery_electronic_sheet' => [
+ 'cash_payment' => '现付',
+ 'freight_collect' => '到付',
+ 'monthly_statement' => '月结'
+ ],
+
+ 'dict_shop_batch_delivery_status' => [
+ 'processing' => '处理中',
+ 'finish' => '已完成',
+ 'fail' => '任务失败'
+ ],
+ 'dict_shop_batch_delivery_type' => [
+ 'delivery' => '批量导入发货',
+ ],
+
+ // 商品排行榜单
+ 'dict_shop_goods_rank_rank_type' => [
+ 'day' => '天',
+ 'week' => '周',
+ 'month' => '月',
+ 'quarter' => '季度'
+ ],
+ 'dict_shop_goods_rank_goods_source' => [
+ 'goods' => '指定商品',
+ 'category' => '指定分类',
+ 'brand' => '指定品牌',
+ 'label' => '指定标签',
+ 'all' => '全部',
+ ],
+
+ 'dict_shop_goods_rank_rule_type' => [
+ 'sale' => '按销量',
+ 'collect' => '按收藏数',
+ 'evaluate' => '按评价数',
+ 'access' => '按浏览量'
+ ],
+
+ //商品统计
+ 'dict_shop_goods_statistics_type' => [
+ 'access_num' => '访问次数',
+ 'cart_num' => '加入购物车数量',
+ 'sale_num' => '商品销量',
+ 'pay_num' => '支付件数',
+ 'collect_num' => '收藏数量',
+ 'pay_money' => '支付总金额',
+ 'goods_visit_member_count' => '访客数',
+ ],
+
+ //批量设置
+ 'dict_shop_goods_batch_set' => [
+ 'label' => '商品标签',
+ 'service' => '商品服务',
+ 'virtual_sale_num' => '虚拟销量',
+ 'category' => '商品分类',
+ 'brand' => '商品品牌',
+ 'poster' => '商品海报',
+ 'gift' => '是否赠品',
+ 'delivery' => '配送设置',
+ 'stock' => '商品库存',
+ 'member_discount' => '会员折扣',
+ 'diy_detail' => '商品模版',
+ 'diy_form' => '万能表单',
+ ],
+ 'dict_shop_goods_sort_config' => [
+ 'asc' => '正序排序',
+ 'desc' => '倒序排序',
+ 'price' => '价格',
+ 'sort' => '排序号',
+ 'sale_num' => '销量',
+ 'create_time' => '创建时间',
+ ],
+];
diff --git a/niucloud/addon/shop/app/lang/zh-cn/validate.php b/niucloud/addon/shop/app/lang/zh-cn/validate.php
new file mode 100644
index 000000000..7e1d52067
--- /dev/null
+++ b/niucloud/addon/shop/app/lang/zh-cn/validate.php
@@ -0,0 +1,7 @@
+ [
+ 'mobile' => '手机号格式有误',
+ ],
+];
diff --git a/niucloud/addon/shop/app/listener/BottomNavigationListener.php b/niucloud/addon/shop/app/listener/BottomNavigationListener.php
new file mode 100644
index 000000000..4e9be6d35
--- /dev/null
+++ b/niucloud/addon/shop/app/listener/BottomNavigationListener.php
@@ -0,0 +1,91 @@
+getAddonConfig($key);
+
+ return [
+ 'key' => $key,
+ 'info' => $addon_info,
+ 'value' => [
+ 'backgroundColor' => '#ffffff',
+ 'textColor' => '#333333',
+ 'textHoverColor' => '#FF4500',
+ 'type' => '1',
+ 'list' => [
+ [
+ "text" => "首页",
+ "link" => [
+ "parent" => "SHOP_LINK",
+ "name" => "SHOP_INDEX",
+ "title" => get_lang('dict_diy.shop_link_index'),
+ "url" => "/addon/shop/pages/index"
+ ],
+ "iconPath" => "addon/shop/diy/tabbar/system-home.png",
+ "iconSelectPath" => "addon/shop/diy/tabbar/system-home-selected.png"
+ ],
+ [
+ "text" => "商品分类",
+ "link" => [
+ "parent" => "SHOP_LINK",
+ "name" => "SHOP_GOODS_CATEGORY",
+ "title" => "商品分类",
+ "url" => "/addon/shop/pages/goods/category"
+ ],
+ "iconPath" => "addon/shop/diy/tabbar/system-category.png",
+ "iconSelectPath" => "addon/shop/diy/tabbar/system-category-selected.png"
+ ],
+ [
+ "text" => "购物车",
+ "link" => [
+ "parent" => "SHOP_LINK",
+ "name" => "SHOP_GOODS_CART",
+ "title" => "购物车",
+ "url" => "/addon/shop/pages/goods/cart"
+ ],
+ "iconPath" => "addon/shop/diy/tabbar/system-cart.png",
+ "iconSelectPath" => "addon/shop/diy/tabbar/system-cart-selected.png"
+ ],
+ [
+ "text" => "我的",
+ "link" => [
+ "parent" => "SHOP_LINK",
+ "name" => "SHOP_MEMBER_INDEX",
+ "title" => get_lang('dict_diy.member_index'),
+ "url" => "/addon/shop/pages/member/index"
+ ],
+ "iconPath" => "addon/shop/diy/tabbar/system-my.png",
+ "iconSelectPath" => "addon/shop/diy/tabbar/system-my-selected.png"
+ ]
+ ]
+ ]
+ ];
+ }
+}
diff --git a/niucloud/addon/shop/app/listener/MemberLoginAfterListener.php b/niucloud/addon/shop/app/listener/MemberLoginAfterListener.php
new file mode 100644
index 000000000..bd47a28c5
--- /dev/null
+++ b/niucloud/addon/shop/app/listener/MemberLoginAfterListener.php
@@ -0,0 +1,32 @@
+checkIfNewcomer($params[ 'member_id' ]);
+ return true;
+ }
+}
diff --git a/niucloud/addon/shop/app/listener/WapIndexListener.php b/niucloud/addon/shop/app/listener/WapIndexListener.php
new file mode 100644
index 000000000..eee1c7b27
--- /dev/null
+++ b/niucloud/addon/shop/app/listener/WapIndexListener.php
@@ -0,0 +1,31 @@
+ 'shop',
+ "title" => get_lang("dict_wap_index.shop"),
+ 'desc' => get_lang("dict_wap_index.shop_desc"),
+ "url" => "/addon/shop/pages/index",
+ 'icon' => 'addon/shop/icon.png'
+ ],
+ ];
+ }
+}
diff --git a/niucloud/addon/shop/app/listener/app/ShopPromotionListener.php b/niucloud/addon/shop/app/listener/app/ShopPromotionListener.php
new file mode 100644
index 000000000..5b9f0e8fe
--- /dev/null
+++ b/niucloud/addon/shop/app/listener/app/ShopPromotionListener.php
@@ -0,0 +1,46 @@
+ [
+ [
+ "key" => "marketing",
+ "name" => get_lang('dict_app_manage.marketing'),
+ "sort" => 10
+ ],
+ ],
+ [
+ "addon" => "shop",
+ "title" => get_lang('dict_shop_app_manage.coupon'),
+ "category" => "marketing",
+ "desc" => get_lang('dict_shop_app_manage.message_manage'),
+ "icon" => "addon/shop/coupon.png",
+ "cover" => "addon/shop/coupon.png",
+ "url" => "/shop/marketing/coupon/list"
+ ],
+ ];
+ }
+ return [];
+ }
+}
diff --git a/niucloud/addon/shop/app/listener/config/initWapListener.php b/niucloud/addon/shop/app/listener/config/initWapListener.php
new file mode 100644
index 000000000..ea0be4624
--- /dev/null
+++ b/niucloud/addon/shop/app/listener/config/initWapListener.php
@@ -0,0 +1,26 @@
+addStat([ 'access_sum' => 1 ]);
+ }
+}
diff --git a/niucloud/addon/shop/app/listener/coupon/CouponCheckListener.php b/niucloud/addon/shop/app/listener/coupon/CouponCheckListener.php
new file mode 100644
index 000000000..133a7bf57
--- /dev/null
+++ b/niucloud/addon/shop/app/listener/coupon/CouponCheckListener.php
@@ -0,0 +1,45 @@
+field('id,status,remain_count')
+ ->where([ [ 'id', 'in', $data['coupon_id'] ] ])
+ ->select()->toArray();
+ foreach ($coupon_data as $coupon) {
+ //检测优惠券状态和剩余数量
+ if ($coupon['status'] == CouponDict::NORMAL && ($coupon[ 'remain_count' ] == '-1' || $coupon[ 'remain_count' ] >= $old_coupon_list[ 'id_' . $coupon['id']])) {
+ $coupon_id[] = $coupon['id'];
+ $coupon_list[] = 'id_' . $coupon['id'];
+ }
+ }
+ return [
+ 'coupon_id' => $coupon_id,
+ 'coupon_list' => $coupon_list,
+ ];
+ }
+}
diff --git a/niucloud/addon/shop/app/listener/coupon/CouponReceiveListener.php b/niucloud/addon/shop/app/listener/coupon/CouponReceiveListener.php
new file mode 100644
index 000000000..969d7707a
--- /dev/null
+++ b/niucloud/addon/shop/app/listener/coupon/CouponReceiveListener.php
@@ -0,0 +1,34 @@
+ "send",
+ "title" => get_lang('dict_shop_member_coupon.send'),
+ ],
+ [
+ "name" => "receive",
+ "title" => get_lang('dict_shop_member_coupon.receive'),
+ ],
+ ];
+ }
+}
diff --git a/niucloud/addon/shop/app/listener/diy/BeforeFormDeleteListener.php b/niucloud/addon/shop/app/listener/diy/BeforeFormDeleteListener.php
new file mode 100644
index 000000000..96a845ad2
--- /dev/null
+++ b/niucloud/addon/shop/app/listener/diy/BeforeFormDeleteListener.php
@@ -0,0 +1,42 @@
+getConfig();
+ if (!empty($config) && $config[ 'form_id' ] == $form_id) {
+ $allow_operate = false;
+ }
+ $goods = ( new Goods() )->where([['form_id', '=', $form_id]])->findOrEmpty()->toArray();
+ if (!empty($goods)) {
+ $allow_operate = false;
+ }
+ return [
+ 'allow_operate' => $allow_operate
+ ];
+ }
+}
diff --git a/niucloud/addon/shop/app/listener/diy/ThemeColorListener.php b/niucloud/addon/shop/app/listener/diy/ThemeColorListener.php
new file mode 100644
index 000000000..e60bc27e2
--- /dev/null
+++ b/niucloud/addon/shop/app/listener/diy/ThemeColorListener.php
@@ -0,0 +1,125 @@
+ [
+ [
+ 'title' => '热情红',
+ 'name' => 'red',
+ 'theme' => [
+ '--page-bg-color' => "#F6F6F6",//页面背景色
+ '--price-text-color' => "#FF4142",//价格颜色
+ '--primary-color' => "#FF4142",//主色调
+ '--primary-color-light' => "#FFEAEA",//主色调浅色(淡)
+ '--primary-color-light2' => "#FFF7F7",//主色调深色(深)
+ '--primary-help-color1' => "#FFB000",//辅色调1
+ '--primary-help-color2' => "#FB7939",//辅色调2
+ '--primary-help-color3' => "#F26F3E",//辅色调3
+ '--primary-help-color4' => "#FFB397",//辅色调4
+ '--primary-help-color5' => "#FFA029",//辅色调5
+ '--primary-color-dark' => "#999999",//灰色调
+ '--primary-color-disabled' => "#CCCCCC",//禁用色
+ ],
+ ],
+ ],
+ // 主题颜色字段,前端展示用,字段中的value值颜色为添加自定义颜色的默认值,默认黑色风格
+ 'theme_field' => [
+ [
+ 'title' => '页面背景色',
+ 'label' => "--page-bg-color",
+ 'value' => "#F6F6F6",
+ 'tip' => "页面背景色在uniapp中使用:var(--page-bg-color)",
+ ],
+ [
+ 'title' => '价格颜色',
+ 'label' => "--price-text-color",
+ 'value' => "#FF4142",
+ 'tip' => "价格颜色在uniapp中使用:var(--price-text-color)",
+ ],
+ [
+ 'title' => '主色调',
+ 'label' => "--primary-color",
+ 'value' => "rgba(51, 51, 51, 1)",
+ 'tip' => "主色调在uniapp中使用:var(--primary-color)",
+ ],
+ [
+ 'title' => '主色调浅色(淡)',
+ 'label' => "--primary-color-light",
+ 'value' => "rgba(51, 51, 51, 0.1)",
+ 'tip' => "主色调浅色(淡)在uniapp中使用:var(--primary-color-light)",
+ ],
+ [
+ 'title' => '主色调深色(深)',
+ 'label' => "--primary-color-light2",
+ 'value' => "rgba(51, 51, 51, 0.8)",
+ 'tip' => "主色调深色(深)在uniapp中使用:var(--primary-color-light2)",
+ ],
+ [
+ 'title' => '辅色调1',
+ 'label' => "--primary-help-color1",
+ 'value' => "rgba(51, 51, 51, 1)",
+ 'tip' => "辅色调1在uniapp中使用:var(--primary-help-color1)",
+ ],
+ [
+ 'title' => '辅色调2',
+ 'label' => "--primary-help-color2",
+ 'value' => "rgba(51, 51, 51, 1)",
+ 'tip' => "辅色调2在uniapp中使用:var(--primary-help-color2)",
+ ],
+ [
+ 'title' => '辅色调3',
+ 'label' => "--primary-help-color3",
+ 'value' => "rgba(51, 51, 51, 1)",
+ 'tip' => "辅色调3在uniapp中使用:var(--primary-help-color3)",
+ ],
+ [
+ 'title' => '辅色调4',
+ 'label' => "--primary-help-color4",
+ 'value' => "rgba(51, 51, 51, 1)",
+ 'tip' => "辅色调4在uniapp中使用:var(--primary-help-color4)",
+ ],
+ [
+ 'title' => '辅色调5',
+ 'label' => "--primary-help-color5",
+ 'value' => "rgba(51, 51, 51, 1)",
+ 'tip' => "辅色调5在uniapp中使用:var(--primary-help-color5)",
+ ],
+ [
+ 'title' => '灰色调',
+ 'label' => "--primary-color-dark",
+ 'value' => "#999999",
+ 'tip' => "灰色调在uniapp中使用:var(--primary-color-dark)",
+ ],
+ [
+ 'title' => '禁用色',
+ 'label' => "--primary-color-disabled",
+ 'value' => "#CCCCCC",
+ 'tip' => "禁用色在uniapp中使用:var(--primary-color-disabled)",
+ ],
+ ]
+ ];
+ }
+ }
+}
diff --git a/niucloud/addon/shop/app/listener/goods/GoodsShowPriceListener.php b/niucloud/addon/shop/app/listener/goods/GoodsShowPriceListener.php
new file mode 100644
index 000000000..6723d899d
--- /dev/null
+++ b/niucloud/addon/shop/app/listener/goods/GoodsShowPriceListener.php
@@ -0,0 +1,30 @@
+getShowPrice($sku_info,$member_id);
+ }
+}
diff --git a/niucloud/addon/shop/app/listener/marketing/GetGoodsJoinInfo.php b/niucloud/addon/shop/app/listener/marketing/GetGoodsJoinInfo.php
new file mode 100644
index 000000000..ff788783a
--- /dev/null
+++ b/niucloud/addon/shop/app/listener/marketing/GetGoodsJoinInfo.php
@@ -0,0 +1,106 @@
+getBatchAllQuery($params['where'], $goods_ids);
+ $example_goods_ids = $query->column('goods.goods_id');
+ $condition[] = ['goods_id', 'in', $example_goods_ids];
+ } else {
+ $condition[] = ['goods_id', 'in', $goods_ids];
+ }
+ $return = [];
+
+ $query = (new ActiveGoods())->where([
+ ['active_goods_status', '=', 'active'],
+ ['active_goods_type', 'in', [ActiveDict::GOODS_SINGLE, ActiveDict::GOODS_INDEPENDENT]],
+ ['active_class', '<>', ActiveDict::DISCOUNT]
+ ])->where($condition)->with([
+ 'active' => function ($query) {
+ $query->withField('active_id,active_name, active_desc, start_time, end_time');
+ }
+ ]);
+ $discount_query = (new DiscountGoods())->where([
+ ['status', '=', 'active']
+ ])->where($condition)->with([
+ 'discount' => function ($query) {
+ $query->withField('discount_id,name');
+ }
+ ]);
+ $manjian_query = (new ManjianGoods())->where([
+ ['status', '=', ManjianDict::ACTIVE]
+ ])->where($condition)->with([
+ 'manjian' => function ($query) {
+ $query->withField('manjian_id,manjian_name');
+ }
+ ]);
+
+
+ if ($is_get_count == 1) {
+ return $query->count() + $discount_query->count() + $manjian_query->count();
+ }
+ $common_active_dict_arr = CommonActiveDict::getActiveShort();
+
+ $active_goods_list = $query->group('goods_id,active_id')->select()->toArray();
+ foreach ($active_goods_list as $item) {
+ $return[$item['goods_id']]['active_' . $item['active_id']] = [
+ 'join_id' => $item['active_id'],
+ 'join_type' => 'active_' . $item['active_class'],
+ 'short' => $common_active_dict_arr[$item['active_class']],
+ 'name' => $item['active']['active_name'] ?? $common_active_dict_arr[$item['active_class']]['active_name'],
+ ];
+ }
+ // 折扣商品条件
+ $discount_goods_list = $discount_query->group('goods_id,discount_id')->select()->toArray();
+ $short_info = $common_active_dict_arr['discount'];
+ foreach ($discount_goods_list as $item) {
+ $return[$item['goods_id']]['discount_' . $item['discount_id']] = [
+ 'join_id' => $item['discount_id'],
+ 'join_type' => 'discount',
+ 'short' => $short_info,
+ 'name' => $item['discount']['name'] ?? $short_info['active_name'],
+ ];
+ }
+ // 满减送商品条件
+ $manjian_goods_list = $manjian_query->group('goods_id,manjian_id')->select()->toArray();
+ $manjian_short_info = $common_active_dict_arr['manjiansong'];
+ foreach ($manjian_goods_list as $item) {
+ $return[$item['goods_id']]['manjian_' . $item['manjian_id']] = [
+ 'join_id' => $item['manjian_id'],
+ 'join_type' => 'manjian',
+ 'short' => $manjian_short_info,
+ 'name' => $item['manjian']['name'] ?? $manjian_short_info['active_name'],
+ ];
+ }
+ return $return;
+ }
+}
diff --git a/niucloud/addon/shop/app/listener/marketing/NewcomerActiveJoinListener.php b/niucloud/addon/shop/app/listener/marketing/NewcomerActiveJoinListener.php
new file mode 100644
index 000000000..bc1d12ff7
--- /dev/null
+++ b/niucloud/addon/shop/app/listener/marketing/NewcomerActiveJoinListener.php
@@ -0,0 +1,58 @@
+getConfig();
+ if (isset($params[ 'is_join' ]) && $config[ 'active_status' ] == ActiveDict::ACTIVE) {
+ if ($params[ 'is_join' ] == 1) {
+ $newcomer_records_model->where([
+ [ 'member_id', '=', $params[ 'member_id' ] ]
+ ])->update([
+ 'is_join' => $params[ 'is_join' ],
+ 'order_id' => $params[ 'order_id' ],
+ 'goods_ids' => $params[ 'goods_ids' ],
+ 'sku_ids' => $params[ 'sku_ids' ],
+ 'update_time' => time()
+ ]);
+ } else {
+ $newcomer_records_model->where([
+ [ 'member_id', '=', $params[ 'member_id' ] ],
+ [ 'order_id', '=', $params[ 'order_id' ] ]
+ ])->update([
+ 'is_join' => $params[ 'is_join' ],
+ 'order_id' => 0,
+ 'goods_ids' => '',
+ 'sku_ids' => '',
+ 'update_time' => time()
+ ]);
+ }
+ }
+ return true;
+ }
+}
diff --git a/niucloud/addon/shop/app/listener/marketing/ShopActiveSaveAfter.php b/niucloud/addon/shop/app/listener/marketing/ShopActiveSaveAfter.php
new file mode 100644
index 000000000..91cca7e9b
--- /dev/null
+++ b/niucloud/addon/shop/app/listener/marketing/ShopActiveSaveAfter.php
@@ -0,0 +1,34 @@
+extend_data) && $sku_info && $sku_info[ 'goods' ][ 'is_discount' ] && $order_obj->extend_data[ 'activity_type' ] == ActiveDict::DISCOUNT) {
+
+ $discount_goods_info = ( new DiscountGoods() )->where([ [ 'discount_goods.goods_id', '=', $sku_info[ 'goods_id' ] ], [ 'discount_goods.sku_id', '=', $sku_info[ 'sku_id' ] ] ])
+ ->withJoin([ 'discount' => function($query) {
+ $query->where([
+ [ 'discount.status', '=', DiscountDict::ACTIVE ],
+ ]);
+ } ])->findOrEmpty()->toArray();
+ if ($discount_goods_info && $discount_goods_info[ 'discount' ][ 'status' ] == DiscountDict::ACTIVE) {
+
+ if ($discount_goods_info[ 'is_enabled' ]){
+ $order_obj->discount[ ActiveDict::DISCOUNT ] = $order_obj->discountFormat(
+ [ $sku_info[ 'sku_id' ] ],
+ OrderDiscountDict::DISCOUNT,
+ $sku_info[ 'num' ],
+ number_format($sku_info[ 'price' ] - $sku_info[ 'sale_price' ], '2', '.'),
+ ActiveDict::DISCOUNT,
+ $discount_goods_info[ 'discount_id' ],
+ '限时折扣',
+ $discount_goods_info[ 'discount' ][ 'remark' ] ?? ''
+ );
+ $sku_info[ 'price' ] = $sku_info[ 'sale_price' ];
+ $sku_info[ 'goods_money' ] = $sku_info[ 'price' ] * $sku_info[ 'num' ];//小计
+ return [
+ 'sku_info' => $sku_info,
+ 'relate_id' => $discount_goods_info[ 'discount_id' ],
+ 'activity_type' => ActiveDict::DISCOUNT
+ ];
+ }
+
+ }
+
+ }
+ }
+}
diff --git a/niucloud/addon/shop/app/listener/marketing/ShopNewcomerCalculate.php b/niucloud/addon/shop/app/listener/marketing/ShopNewcomerCalculate.php
new file mode 100644
index 000000000..d144a2c10
--- /dev/null
+++ b/niucloud/addon/shop/app/listener/marketing/ShopNewcomerCalculate.php
@@ -0,0 +1,80 @@
+checkIfNewcomer($order_obj->member_id);
+
+ if (!empty($order_obj->extend_data) && $sku_info && $order_obj->extend_data[ 'activity_type' ] == ActiveDict::NEWCOMER_DISCOUNT && $is_newcomer) {
+
+ //查询新人专享活动
+ $newcomer_goods_info = ( new ActiveGoods() )->field('active_id,active_goods_value')->where([
+ [ 'goods_id', '=', $sku_info[ 'goods_id' ] ],
+ [ 'sku_id', '=', $sku_info[ 'sku_id' ] ],
+ [ 'active_class', '=', ActiveDict::NEWCOMER_DISCOUNT ]
+ ])->with([
+ 'active' => function($query) {
+ $query->field('active_id,active_desc,active_status,active_value');
+ }
+ ])->findOrEmpty()->toArray();
+
+ if (!empty($newcomer_goods_info) && $newcomer_goods_info[ 'active' ][ 'active_status' ] == ActiveDict::ACTIVE) {
+ $newcomer_price = json_decode($newcomer_goods_info[ 'active_goods_value' ], true)[ 'newcomer_price' ];
+ $sku_info[ 'newcomer_price' ] = $newcomer_price;
+ $sku_info[ 'is_newcomer' ] = 1;
+ $sku_info[ 'extend' ] = [ 'is_newcomer' => 1, 'newcomer_price' => $newcomer_price ];
+ $order_obj->discount[ ActiveDict::NEWCOMER_DISCOUNT ] = $order_obj->discountFormat(
+ [ $sku_info[ 'sku_id' ] ],
+ OrderDiscountDict::DISCOUNT,
+ 1,
+ number_format($sku_info[ 'price' ] - $newcomer_price, '2', '.'),
+ ActiveDict::NEWCOMER_DISCOUNT,
+ $newcomer_goods_info[ 'active_id' ],
+ '新人专享',
+ $newcomer_goods_info[ 'active' ][ 'active_desc' ] ?? ''
+ );
+ if ($sku_info[ 'num' ] == 1) {
+ $sku_info[ 'price' ] = $newcomer_price;
+ $sku_info[ 'goods_money' ] = $sku_info[ 'price' ] * $sku_info[ 'num' ];//只有一个商品时使用新人价计算
+ } else {
+ // 超出数量按照正常价格计算(原价/会员价)
+ $sku_info[ 'goods_money' ] = $newcomer_price * 1 + $sku_info[ 'member_price' ] * ( intval($sku_info[ 'num' ]) - 1 );
+ }
+
+ return [
+ 'sku_info' => $sku_info,
+ 'relate_id' => $newcomer_goods_info[ 'active_id' ],
+ 'activity_type' => ActiveDict::NEWCOMER_DISCOUNT
+ ];
+ }
+
+ }
+ }
+}
diff --git a/niucloud/addon/shop/app/listener/notice_template/OrderDelivery.php b/niucloud/addon/shop/app/listener/notice_template/OrderDelivery.php
new file mode 100644
index 000000000..9824b8856
--- /dev/null
+++ b/niucloud/addon/shop/app/listener/notice_template/OrderDelivery.php
@@ -0,0 +1,39 @@
+key == $params['key']) {
+ $order = (new CoreOrderService())->getInfo($params['data']['order_id']);
+ if (!empty($order)) {
+ $wap_domain = get_wap_domain();
+ return $this->toReturn(
+ [
+ '__wechat_page' => $wap_domain . '/addon/shop/pages/order/detail?order_id=' . $order['order_id'],//模板消息链接
+ '__weapp_page' => 'addon/shop/pages/order/detail?order_id=' . $order['order_id'],//小程序链接
+ 'body' => str_sub($order['body']),
+ 'order_no' => $order['order_no'],
+ 'delivery_time' => $order['delivery_time'],
+ 'order_money' => $order['order_money'],
+ 'url' => $wap_domain . '/addon/shop/pages/order/detail?order_id=' . $order['order_id']
+ ],
+ [
+ 'member_id' => $order['member_id']
+ ]
+ );
+ }
+ }
+ }
+}
diff --git a/niucloud/addon/shop/app/listener/notice_template/OrderPay.php b/niucloud/addon/shop/app/listener/notice_template/OrderPay.php
new file mode 100644
index 000000000..18a375ed3
--- /dev/null
+++ b/niucloud/addon/shop/app/listener/notice_template/OrderPay.php
@@ -0,0 +1,40 @@
+key == $params['key']) {
+ $order = (new CoreOrderService())->getInfo($params['data']['order_id']);
+ if (!empty($order)) {
+ $wap_domain = get_wap_domain();
+ return $this->toReturn(
+ [
+ '__wechat_page' => $wap_domain . '/addon/shop/pages/order/detail?order_id=' . $order['order_id'],//模板消息链接
+ '__weapp_page' => 'addon/shop/pages/order/detail?order_id=' . $order['order_id'],//小程序链接
+ 'body' => str_sub($order['body']),
+ 'order_no' => $order['order_no'],
+ 'order_money' => $order['order_money'], //交易流水号
+ 'create_time' => $order['create_time'],
+ 'pay_time' => $order['pay_time'],
+ 'url' => $wap_domain . '/addon/shop/pages/order/detail?order_id=' . $order['order_id']
+ ],
+ [
+ 'member_id' => $order['member_id']
+ ]
+ );
+ }
+ }
+ }
+}
diff --git a/niucloud/addon/shop/app/listener/notice_template/OrderPayRemind.php b/niucloud/addon/shop/app/listener/notice_template/OrderPayRemind.php
new file mode 100644
index 000000000..24a45aa86
--- /dev/null
+++ b/niucloud/addon/shop/app/listener/notice_template/OrderPayRemind.php
@@ -0,0 +1,40 @@
+key == $params['key']) {
+ $order = (new CoreOrderService())->getInfo($params['data']['order_id']);
+ if (!empty($order) && $order['status'] == OrderDict::WAIT_PAY) {
+ $wap_domain = get_wap_domain();
+ return $this->toReturn(
+ [
+ '__wechat_page' => $wap_domain . '/addon/shop/pages/order/detail?order_id=' . $order['order_id'],//模板消息链接
+ '__weapp_page' => 'addon/shop/pages/order/detail?order_id=' . $order['order_id'],//小程序链接
+ 'body' => $order['body'],
+ 'order_no' => $order['order_no'],
+ 'order_money' => $order['order_money'], //交易流水号
+ 'timeout' => $order['timeout'],
+ 'url' => $wap_domain . '/addon/shop/pages/order/detail?order_id=' . $order['order_id']
+ ],
+ [
+ 'member_id' => $order['member_id']
+ ]
+ );
+ }
+ }
+ }
+}
diff --git a/niucloud/addon/shop/app/listener/notice_template/RefundAgree.php b/niucloud/addon/shop/app/listener/notice_template/RefundAgree.php
new file mode 100644
index 000000000..33c7a90f2
--- /dev/null
+++ b/niucloud/addon/shop/app/listener/notice_template/RefundAgree.php
@@ -0,0 +1,35 @@
+key == $params['key']) {
+ $refund = (new CoreRefundService())->getInfo($params['data']['order_refund_no']);
+ if (!empty($refund)) {
+ return $this->toReturn(
+ [
+ 'order_refund_no' => $refund['order_refund_no'],
+ 'order_no' => $refund['order_main']['order_no'],
+ 'refund_money' => $refund['apply_money'],
+ 'result' => '已通过申请'
+ ],
+ [
+ 'member_id' => $refund['member_id']
+ ]
+ );
+ }
+ }
+ }
+}
diff --git a/niucloud/addon/shop/app/listener/notice_template/RefundRefuse.php b/niucloud/addon/shop/app/listener/notice_template/RefundRefuse.php
new file mode 100644
index 000000000..539928dd7
--- /dev/null
+++ b/niucloud/addon/shop/app/listener/notice_template/RefundRefuse.php
@@ -0,0 +1,35 @@
+key == $params['key']) {
+ $refund = (new CoreRefundService())->getInfo($params['data']['order_refund_no']);
+ if (!empty($refund)) {
+ return $this->toReturn(
+ [
+ 'order_refund_no' => $refund['order_refund_no'],
+ 'order_no' => $refund['order_main']['order_no'],
+ 'refund_money' => $refund['apply_money'],
+ 'result' => '未通过申请'
+ ],
+ [
+ 'member_id' => $refund['member_id']
+ ]
+ );
+ }
+ }
+ }
+}
diff --git a/niucloud/addon/shop/app/listener/order/AfterShopOrderClose.php b/niucloud/addon/shop/app/listener/order/AfterShopOrderClose.php
new file mode 100644
index 000000000..05f209dd9
--- /dev/null
+++ b/niucloud/addon/shop/app/listener/order/AfterShopOrderClose.php
@@ -0,0 +1,117 @@
+where($order_discount_where)->select();
+ if (!$order_discount->isEmpty()) {
+ $recover_list = [];
+ foreach ($order_discount as $v) {
+ $item_discount_type = $v['discount_type'];
+ $recover_list[$item_discount_type][] = $v['discount_type_id'];
+ }
+ foreach ($recover_list as $item_discount_type => $discount_type_ids) {
+ switch ($item_discount_type) {
+ case 'coupon'://优惠券
+ (new CoreCouponMemberService())->recover($discount_type_ids);
+ break;
+ }
+ }
+ }
+ $order_goods_where = array(
+ ['order_id', '=', $order_data['order_id']],
+ ['is_gift', '=', 0],
+ );
+ $order_goods_data = (new OrderGoods())->where($order_goods_where)->select()->toArray();
+ //返还商品库存
+ $core_goods_stock_service = new CoreGoodsStockService();
+ $inc_data = [];
+ foreach ($order_goods_data as $v) {
+ $stock = $v['num'];
+ $inc_data['goods'][] = [
+ 'stock' => Db::raw("stock+" . $stock),
+ 'goods_id' => $v['goods_id']
+ ];
+ $inc_data['sku'][] = [
+ 'stock' => Db::raw(" stock+" . $stock),
+ 'sku_id' => $v['sku_id']
+ ];
+ }
+ $core_goods_stock_service->batchUpdateStock($inc_data);
+ //商品累计销量
+ //累减销量
+ $dec_data = [];
+ $core_goods_sale_num_service = new CoreGoodsSaleNumService();
+ foreach ($order_goods_data as $v) {
+ // 商品销量累减 - 下单数(不剔除退款订单)
+ if (empty($order_data['pay_time'])) {
+ //商品累计销量
+ $stock = $v['num'];
+ $dec_data['goods'][] = [
+ 'sale_num' => Db::raw("sale_num-" . $stock),
+ 'goods_id' => $v['goods_id']
+ ];
+ $dec_data['sku'][] = [
+ 'sale_num' => Db::raw(" sale_num-" . $stock),
+ 'sku_id' => $v['sku_id']
+ ];
+ //TODO::可以优化 后置
+ CoreGoodsStatService::decStat(['goods_id' => $v['goods_id'], 'time' => $order_data['create_time'], 'sale_num' => $v['num']]);
+ }
+ }
+ $core_goods_sale_num_service->batchUpdateSaleNum($dec_data);
+
+
+ //发票改变状态........
+ (new CoreInvoiceService())->close($order_data['invoice_id']);
+ //发布日志
+ $main_type = $data['main_type'];
+ $main_id = $data['main_id'] ?? 0;
+ (new CoreOrderLogService())->add([
+ 'order_id' => $order_data['order_id'],
+ 'status' => OrderDict::CLOSE,
+ 'main_type' => $main_type,//todo 可以是传入的
+ 'main_id' => $main_id,
+ 'type' => OrderDict::ORDER_CLOSE_ACTION,
+ 'content' => ''
+ ]);
+ //todo 消息发送
+
+ //新人专享活动退还参与资格
+ if ($order_data['activity_type'] == ActiveDict::NEWCOMER_DISCOUNT) {
+ event("NewcomerActiveJoin", ['member_id' => $order_data['member_id'], 'is_join' => 0, 'order_id' => $order_data['order_id']]);
+ }
+ } catch (\Exception $e) {
+ Log::write('订单AfterShopOrderClose失败' . $e->getMessage() . $e->getFile() . $e->getLine());
+ }
+ }
+}
diff --git a/niucloud/addon/shop/app/listener/order/AfterShopOrderCreate.php b/niucloud/addon/shop/app/listener/order/AfterShopOrderCreate.php
new file mode 100644
index 000000000..7f5e021be
--- /dev/null
+++ b/niucloud/addon/shop/app/listener/order/AfterShopOrderCreate.php
@@ -0,0 +1,155 @@
+ Db::raw('stock-' . $v[ 'num' ]),
+ 'goods_id' => $v[ 'goods_id' ],
+ ];
+ $dec_data['sku'][] =[
+ 'stock' => Db::raw('stock-' . $v[ 'num' ]),
+ 'sku_id' => $v[ 'sku_id' ],
+ ];
+ }
+ $core_goods_stock_service->batchUpdateStock($dec_data);
+// Db::commit();
+// } catch (\Exception $e) {
+// Db::rollback();
+// throw new CommonException($e->getMessage());
+// }
+
+ //购物车删除
+ $cart_ids = $data[ 'cart_ids' ] ?? [];
+ if ($cart_ids) {
+ ( new CoreCartService() )->deleteByCartIds($cart_ids);
+ }
+
+ //累增销量
+ $core_goods_sale_num_service = new CoreGoodsSaleNumService();
+ $inc_data = [];
+ foreach ($order_goods_data as $v) {
+ //商品累计销量
+ $inc_data['goods'][] =[
+ 'sale_num' => Db::raw('sale_num+' . $v[ 'num' ]),
+ 'goods_id' => $v[ 'goods_id' ],
+ ];
+ $inc_data['sku'][] =[
+ 'sale_num' => Db::raw('sale_num+' . $v[ 'num' ]),
+ 'sku_id' => $v[ 'sku_id' ],
+ ];
+ // todo 可以优化 逻辑较多 后置
+ // 商品销量统计 - 下单数
+ CoreGoodsStatService::addStat([ 'goods_id' => $v[ 'goods_id' ], 'sale_num' => $v[ 'num' ] ]);
+ }
+ $core_goods_sale_num_service->batchUpdateSaleNum($inc_data);
+ //写入发票
+ $invoice = $basic[ 'invoice' ] ?? [];
+ if (!empty($invoice)) {
+ $invoice_id = ( new CoreInvoiceService() )->add([
+ 'type' => $invoice[ 'type' ] ?? '',
+ 'name' => $invoice[ 'name' ],
+ 'header_type' => $invoice[ 'header_type' ],
+ 'header_name' => $invoice[ 'header_name' ],
+ 'tax_number' => $invoice[ 'tax_number' ],
+ 'mobile' => $invoice[ 'mobile' ],
+ 'email' => $invoice[ 'email' ],
+ 'telephone' => $invoice[ 'telephone' ],
+ 'address' => $invoice[ 'address' ],
+ 'bank_name' => $invoice[ 'bank_name' ],
+ 'bank_card_number' => $invoice[ 'bank_card_number' ],
+ 'money' => $order_data[ 'order_money' ],
+ 'status' => InvoiceDict::WAIT_OPEN,
+ 'member_id' => $order_data[ 'member_id' ],
+ 'trade_type' => $order_data[ 'order_type' ],
+ 'trade_id' => $order_data[ 'order_id' ],
+ ]);
+ //修改订单发票id
+ ( new Order() )->where([
+ [ 'order_id', '=', $order_data[ 'order_id' ] ]
+ ])->update([ 'invoice_id' => $invoice_id ]);
+ }
+
+ //发布日志
+ $main_type = $data[ 'main_type' ] ?? OrderLogDict::MEMBER;
+ $main_id = $data[ 'main_id' ] ?? $order_data[ 'member_id' ];
+ ( new CoreOrderLogService() )->add([
+ 'order_id' => $order_data[ 'order_id' ],
+ 'status' => OrderDict::WAIT_PAY,
+ 'main_type' => $main_type,//todo 可以是传入的
+ 'main_id' => $main_id,
+ 'type' => OrderDict::ORDER_CREATE_ACTION,
+ 'content' => ''
+ ]);
+
+ //消息发送
+
+ //创建定时关闭任务
+ $core_order_config_service = new CoreOrderConfigService();
+ $order_config = $core_order_config_service->orderClose();
+ if ($order_config[ 'is_close' ] == 1) {
+ if ($order_config[ 'close_length' ] > 0) {
+ ( new Order() )->where([ [ 'order_id', '=', $order_data[ 'order_id' ] ] ])->update([
+ 'timeout' => $data[ 'time' ] + $order_config[ 'close_length' ] * 60
+ ]);
+// OrderClose::dispatch(['order_id' => $order_data['order_id'] ], secs: $order_config['close_length'] * 60);
+ }
+ }
+ //增加统计数据
+ CoreStatService::addStat([ 'order_num' => 1 ]);
+
+ //新人专享活动扣除参与资格
+ $goods_ids = [];//参与商品id集合
+ $sku_ids = [];//参与商品规格id集合
+ foreach ($order_goods_data as $v) {
+ //判断商品是否享受新人专享活动
+ if (isset($v[ 'extend' ]) && !empty($v[ 'extend' ]) && isset($v[ 'extend' ][ 'is_newcomer' ]) && $v[ 'extend' ][ 'is_newcomer' ]) {
+ $goods_ids[] = $v[ 'goods_id' ];
+ $sku_ids[] = $v[ 'sku_id' ];
+ }
+ }
+ if ($order_data[ 'activity_type' ] == ActiveDict::NEWCOMER_DISCOUNT) {
+ event("NewcomerActiveJoin", [ 'member_id' => $order_data[ 'member_id' ], 'is_join' => 1, 'order_id' => $order_data[ 'order_id' ], 'goods_ids' => $goods_ids, 'sku_ids' => $sku_ids ]);
+ }
+ } catch (\Exception $e) {
+ Log::write('订单AfterShopOrderCreate失败' . $e->getMessage() . $e->getFile() . $e->getLine());
+ }
+ // 订单催付通知
+ OrderPayRemind::dispatch([ 'order_id' => $order_data[ 'order_id' ] ], secs: 1800);
+ }
+}
diff --git a/niucloud/addon/shop/app/listener/order/AfterShopOrderDelivery.php b/niucloud/addon/shop/app/listener/order/AfterShopOrderDelivery.php
new file mode 100644
index 000000000..7e92aa1ed
--- /dev/null
+++ b/niucloud/addon/shop/app/listener/order/AfterShopOrderDelivery.php
@@ -0,0 +1,80 @@
+add([
+ 'order_id' => $order_data[ 'order_id' ],
+ 'status' => OrderDict::WAIT_TAKE,
+ 'main_type' => $main_type,
+ 'main_id' => $main_id,
+ 'type' => OrderDict::ORDER_DELIVERY_ACTION,
+ 'content' => ''
+ ]);
+
+ //消息发送
+ if ($order_data[ 'status' ] == OrderDict::WAIT_TAKE) {
+ ( new NoticeService() )->send('shop_order_delivery', [ 'order_id' => $order_data[ 'order_id' ] ]);
+ }
+
+ //写入定时收货任务
+ $order_goods_list = ( new OrderGoods() )->where([ [ 'order_id', '=', $order_data[ 'order_id' ] ] ])->select()->toArray();
+ //判断是否是核销商品
+ if (count($order_goods_list) == 1 && $order_goods_list[ 0 ][ 'is_verify' ] == 1) {
+ if (!empty($order_goods_list[ 0 ][ 'verify_expire_time' ])) {
+ $timeout = strtotime($order_goods_list[ 0 ][ 'verify_expire_time' ]);
+ }
+ } else {
+ $core_order_config_service = new CoreOrderConfigService();
+ $order_config = $core_order_config_service->orderConfirm();
+ if ($order_config[ 'is_finish' ] == 1) {
+ if ($order_config[ 'finish_length' ] > 0) {
+ $timeout = strtotime($order_data[ 'delivery_time' ]) + $order_config[ 'finish_length' ] * 86400;
+ }
+ }
+ }
+ if (!empty($timeout)) {
+ ( new Order() )->where([ [ 'order_id', '=', $order_data[ 'order_id' ] ] ])->update([
+ 'timeout' => $timeout
+ ]);
+ }
+
+ // 微信小程序 发货信息录入接口
+ ( new CoreOrderDeliveryService() )->orderShippingUploadShippingInfo([ 'order_id' => $order_data[ 'order_id' ] ]);
+// $core_order_config_service = new CoreOrderConfigService();
+// $order_config = $core_order_config_service->orderConfirm();
+// if ($order_config['is_finish'] == 1) {
+// if ($order_config['finish_length'] > 0) {
+// (new Order())->where([['order_id', '=', $order_data['order_id']]])->update([
+// 'timeout' => strtotime($order_data['delivery_time']) + $order_config['finish_length'] * 86400
+// ]);
+//// OrderFinish::dispatch(['order_id' => $order_data['order_id'] ], secs: $order_config['finish_length'] * 86400);
+// }
+// }
+ } catch (\Exception $e) {
+ Log::write('订单AfterShopOrderDelivery失败' . $e->getMessage() . $e->getFile() . $e->getLine());
+ }
+ }
+}
diff --git a/niucloud/addon/shop/app/listener/order/AfterShopOrderEditPrice.php b/niucloud/addon/shop/app/listener/order/AfterShopOrderEditPrice.php
new file mode 100644
index 000000000..4ee4a7df4
--- /dev/null
+++ b/niucloud/addon/shop/app/listener/order/AfterShopOrderEditPrice.php
@@ -0,0 +1,41 @@
+add([
+ 'order_id' => $order_data['order_id'],
+ 'status' => OrderDict::WAIT_PAY,
+ 'main_type' => $main_type,
+ 'main_id' => $main_id,
+ 'type' => OrderDict::ORDER_EDIT_PRICE_ACTION,
+ 'content' => $content
+ ]);
+
+ //todo 发送消息提醒.....
+ } catch ( \Exception $e ) {
+ Log::write('订单AfterShopOrderEditPrice失败' . $e->getMessage() . $e->getFile() . $e->getLine());
+ }
+ }
+}
diff --git a/niucloud/addon/shop/app/listener/order/AfterShopOrderFinish.php b/niucloud/addon/shop/app/listener/order/AfterShopOrderFinish.php
new file mode 100644
index 000000000..7e051fdf6
--- /dev/null
+++ b/niucloud/addon/shop/app/listener/order/AfterShopOrderFinish.php
@@ -0,0 +1,75 @@
+add([
+ 'order_id' => $order_data[ 'order_id' ],
+ 'status' => OrderDict::FINISH,
+ 'main_type' => $main_type,
+ 'main_id' => $main_id,
+ 'type' => OrderDict::ORDER_FINISH_ACTION,
+ 'content' => ''
+ ]);
+ //消息发送
+
+ //定时关闭订单允许退款开关
+ $core_order_config_service = new CoreOrderConfigService();
+ $order_config = $core_order_config_service->orderRefund(); //确认收货后售后,1.开启,2.关闭
+ if ($order_config[ 'no_allow_refund' ] == 2) {//等于2,不支持确认收货后售后,此时要关闭退款,否则不关闭
+ ( new OrderGoods() )->where([ [ 'order_id', '=', $order_data[ 'order_id' ] ] ])->update([
+ 'is_enable_refund' => 0
+ ]);
+ } else {
+ if ($order_config[ 'refund_length' ] > 0) {
+ ( new Order() )->where([ [ 'order_id', '=', $order_data[ 'order_id' ] ] ])->update([
+ 'is_enable_refund' => 1,
+ 'timeout' => $order_data[ 'finish_time' ] + $order_config[ 'refund_length' ] * 86400 //确认收货后售后,单位为天
+ ]);
+// OrderCloseAllowRefund::dispatch(['order_id' => $order_data['order_id'] ], secs: $order_config['refund_length'] * 86400);
+ }
+ }
+
+ // 订单完成发放积分成长值
+ CoreMemberService::sendGrowth($order_data[ 'member_id' ], 'shop_buy_goods', $order_data);
+ CoreMemberService::sendGrowth($order_data[ 'member_id' ], 'shop_buy_order');
+ CoreMemberService::sendPoint($order_data[ 'member_id' ], 'shop_buy_goods', array_merge($order_data, [ 'from_type' => 'consume_reward', 'related_id' => $order_data[ 'order_id' ] ]));
+
+ // 微信小程序 发送 确认收货提醒消息
+ ( new CoreOrderFinishService() )->orderShippingNotifyConfirmReceive($order_data);
+
+ // 小票打印,订单收货之后
+ return ( new CorePrinterService() )->printTicket([
+ "type" => "shopGoodsOrder",
+ "trigger" => "take_delivery",
+ 'business' => [
+ 'order_id' => $order_data[ 'order_id' ]
+ ]
+ ]);
+ } catch (\Exception $e) {
+ Log::write('订单AfterShopOrderFinish失败' . $e->getMessage() . $e->getFile() . $e->getLine());
+ }
+ }
+}
diff --git a/niucloud/addon/shop/app/listener/order/AfterShopOrderPay.php b/niucloud/addon/shop/app/listener/order/AfterShopOrderPay.php
new file mode 100644
index 000000000..9247e60da
--- /dev/null
+++ b/niucloud/addon/shop/app/listener/order/AfterShopOrderPay.php
@@ -0,0 +1,103 @@
+open($order_data['invoice_id']);
+ //商城专用统计
+ CoreStatService::addStat([ 'sale_money' => $order_data['order_money']]);
+ //日志
+ $main_type = $data['main_type'] ?? OrderLogDict::MEMBER;
+ $main_id = $data['main_id'] ?? $order_data['member_id'];
+ (new CoreOrderLogService())->add([
+ 'order_id' => $order_data['order_id'],
+ 'status' => OrderDict::WAIT_DELIVERY,
+ 'main_type' => $main_type,
+ 'main_id' => $main_id,
+ 'type' => OrderDict::ORDER_PAY_ACTION,
+ 'content' => ''
+ ]);
+ //虚拟商品自动发货
+ $order_goods_list = (new OrderGoods())->where(['order_id' => $data['order_id']])->select();
+ if (!empty($order_goods_list)) {
+ $goods_column = (new Goods())->where([['goods_id', 'in', array_column($order_goods_list->toArray(), 'goods_id')]])->column('*', 'goods_id');
+ $virtual_order_goods_ids = [];
+ foreach ($order_goods_list as $v) {
+ //根据商品配置判断下一步配送操作
+ $temp_goods_type = $v['goods_type'];
+ //读取虚拟商品配置
+ if ($temp_goods_type == GoodsDict::VIRTUAL) {
+ $temp_goods = $goods_column[$v['goods_id']] ?? [];
+ if (empty($temp_goods)) continue;
+ //是否自动发货
+ if ($temp_goods['virtual_auto_delivery'] == 1) {
+ //调用订单项发货
+ $virtual_order_goods_ids[] = $v['order_goods_id'];
+ }
+ }
+ }
+ if ($virtual_order_goods_ids) {
+ $delivery_data = [];
+ $delivery_data['main_type'] = OrderLogDict::SYSTEM;
+ $delivery_data['main_id'] = 0;
+ $delivery_data['order_id'] = $order_data['order_id'];
+ $delivery_data['delivery_type'] = OrderDeliveryDict::VIRTUAL;
+ $delivery_data['order_goods_ids'] = $virtual_order_goods_ids;
+ (new CoreOrderDeliveryService())->delivery($delivery_data);
+ }
+
+ }
+
+ //消息发送
+ if ($send_notice == 1) {
+ (new NoticeService())->send('shop_order_pay', ['order_id' => $order_data['order_id']]);
+ }
+
+ (new DiscountService())->orderPayAfter($order_data);
+
+ (new CoreGoodsStatService())->saveGoodsPayNumAndMoneyByOrderId($order_data); // 商品支付数量 金额统计数据
+
+ //满减送订单支付后赠品发放
+ (new CoreManjianService())->giftGrant($order_data);
+
+ // 小票打印,订单付款之后
+ return (new CorePrinterService())->printTicket([
+ "type" => "shopGoodsOrder",
+ "trigger" => "pay_after",
+ 'business' => [
+ 'order_id' => $order_data['order_id']
+ ]
+ ]);
+
+ } catch (\Exception $e) {
+ Log::write('订单AfterShopOrderPay失败' . $e->getMessage() . $e->getFile() . $e->getLine());
+ }
+ }
+}
diff --git a/niucloud/addon/shop/app/listener/order/ShopOrderCreate.php b/niucloud/addon/shop/app/listener/order/ShopOrderCreate.php
new file mode 100644
index 000000000..0a3ca0f6a
--- /dev/null
+++ b/niucloud/addon/shop/app/listener/order/ShopOrderCreate.php
@@ -0,0 +1,36 @@
+orderClose();
+ if ($order_config[ 'is_close' ] == 1) {
+ if ($order_config[ 'close_length' ] > 0) {
+ ( new Order() )->where([ [ 'order_id', '=', $order_data[ 'order_id' ] ] ])->update([
+ 'timeout' => $data[ 'time' ] + $order_config[ 'close_length' ] * 60
+ ]);
+// OrderClose::dispatch(['order_id' => $order_data['order_id'] ], secs: $order_config['close_length'] * 60);
+ }
+ }
+
+ //满减赠送记录
+ ( new CoreManjianService() )->addGiveRecords($data);
+ }
+}
diff --git a/niucloud/addon/shop/app/listener/order/ShopOrderTradeInfoListener.php b/niucloud/addon/shop/app/listener/order/ShopOrderTradeInfoListener.php
new file mode 100644
index 000000000..17fc94720
--- /dev/null
+++ b/niucloud/addon/shop/app/listener/order/ShopOrderTradeInfoListener.php
@@ -0,0 +1,54 @@
+where([ [ 'order_id', '=', $params[ 'trade_id' ] ] ])->field('order_id')
+ ->with([
+ 'order_goods' => function($query) {
+ $query->field('order_id,goods_name,sku_name,sku_image,price,num')->append([ 'sku_image_thumb_mid' ]);
+ }
+ ])->findOrEmpty()->toArray();
+ $info = [];
+ $item = [];
+ if (!empty($order_info)) {
+ if ($order_info[ 'order_goods' ]) {
+ foreach ($order_info[ 'order_goods' ] as $k => $v) {
+ $item[ $k ][ 'item_image' ] = empty($v[ 'sku_image_thumb_mid' ]) ? $v[ 'sku_image' ] : $v[ 'sku_image_thumb_mid' ];//订单项图片
+ $item[ $k ][ 'item_name' ] = $v[ 'goods_name' ];//订单项名称
+ $item[ $k ][ 'item_sub_name' ] = $v[ 'sku_name' ];//订单项副标题
+ $item[ $k ][ 'item_price' ] = $v[ 'price' ];//订单项金额
+ $item[ $k ][ 'item_num' ] = $v[ 'num' ];//订单项数量
+ }
+ $info[ 'item_list' ] = $item;//订单项列表
+ $info[ 'item_total' ] = '共' . count($order_info[ 'order_goods' ]) . '种商品';//订单项总计
+ $info[ 'detail_url' ] = '/addon/shop/pages/order/detail?order_id=' . $params[ 'trade_id' ];//订单详情跳转路径
+ }
+ }
+ return $info;
+ }
+ }
+}
diff --git a/niucloud/addon/shop/app/listener/order/WapOrderDetailPathListener.php b/niucloud/addon/shop/app/listener/order/WapOrderDetailPathListener.php
new file mode 100644
index 000000000..72cf008c5
--- /dev/null
+++ b/niucloud/addon/shop/app/listener/order/WapOrderDetailPathListener.php
@@ -0,0 +1,34 @@
+getInfo($params[ 'trade_id' ]);
+ if (empty($order_info)) return 'addon/shop/pages/order/list';
+ return 'addon/shop/pages/order/detail?order_id=' . $order_info[ 'order_id' ];
+ }
+ }
+}
diff --git a/niucloud/addon/shop/app/listener/order_export/ShopInvoiceExportDataListener.php b/niucloud/addon/shop/app/listener/order_export/ShopInvoiceExportDataListener.php
new file mode 100644
index 000000000..8aa8fa59f
--- /dev/null
+++ b/niucloud/addon/shop/app/listener/order_export/ShopInvoiceExportDataListener.php
@@ -0,0 +1,61 @@
+withSearch(["header_name", "create_time", "invoice_time"], $param['where'])
+ ->with([
+ 'member' => function ($query) {
+ $query->field('member_id, nickname');
+ },
+ 'shop_order' => function ($query) {
+ $query->field('order_id, order_no, order_money');
+ }
+ ])
+ ->where([['status', '=', InvoiceDict::OPEN]])->append(['header_type_name', 'type_name', 'is_invoice_name'])->field('*')->order($order);
+ if ($param['page']['page'] > 0 && $param['page']['limit'] > 0) {
+ $data = $search_model->page($param['page']['page'], $param['page']['limit'])->select()->toArray();
+ } else {
+ $data = $search_model->select()->toArray();
+ }
+ foreach ($data as $key => $val) {
+ $data[$key]['order_no'] = !empty($val['shop_order']) ? $val['shop_order']['order_no']."\t" : '';
+ $data[$key]['order_money'] = !empty($val['shop_order']) ? $val['shop_order']['order_money'] : '';
+ $data[$key]['nickname'] = !empty($val['member']) ? $val['member']['nickname'] : '';
+ $data[$key]['header_name'] = $val['header_name']."\t";
+ $data[$key]['tax_number'] = $val['tax_number']."\t";
+ $data[$key]['bank_card_number'] = $val['bank_card_number']."\t";
+ $data[$key]['invoice_number'] = $val['invoice_number']."\t";
+ $data[$key]['create_time'] = !empty($val['create_time']) ? $val['create_time'] : '';
+ $data[$key]['invoice_time'] = !empty($val['invoice_time']) ? $val['invoice_time'] : '';
+ }
+ }
+ return $data;
+ }
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/app/listener/order_export/ShopInvoiceExportTypeListener.php b/niucloud/addon/shop/app/listener/order_export/ShopInvoiceExportTypeListener.php
new file mode 100644
index 000000000..9ec9ebbe4
--- /dev/null
+++ b/niucloud/addon/shop/app/listener/order_export/ShopInvoiceExportTypeListener.php
@@ -0,0 +1,49 @@
+ [
+ 'name' => '发票列表',
+ 'column' => [
+ 'order_no' => [ 'name' => '订单号'],
+ 'nickname' => [ 'name' => '会员昵称'],
+ 'order_money' => [ 'name' => '订单金额'],
+ 'header_name' => [ 'name' => '发票抬头'],
+ 'header_type_name' => [ 'name' => '抬头类型'],
+ 'type_name' => [ 'name' => '发票类型'],
+ 'tax_number' => [ 'name' => '纳税人识别号'],
+ 'bank_name' => [ 'name' => '开户银行'],
+ 'bank_card_number' => [ 'name' => '银行账号'],
+ 'address' => [ 'name' => '注册地址'],
+ 'name' => [ 'name' => '发票内容'],
+ 'money' => [ 'name' => '开票金额'],
+ 'invoice_number' => [ 'name' => '发票代码'],
+ 'remark' => [ 'name' => '备注'],
+ 'create_time' => [ 'name' => '申请时间'],
+ 'invoice_time' => [ 'name' => '开票时间'],
+ 'is_invoice_name' => [ 'name' => '开票状态'],
+ ],
+ ]
+ ];
+ }
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/app/listener/order_export/ShopOrderExportDataListener.php b/niucloud/addon/shop/app/listener/order_export/ShopOrderExportDataListener.php
new file mode 100644
index 000000000..89b472075
--- /dev/null
+++ b/niucloud/addon/shop/app/listener/order_export/ShopOrderExportDataListener.php
@@ -0,0 +1,131 @@
+where([ [ 'order.order_id', '>', 0 ] ])->withSearch([ 'search_type', 'order_from', 'join_status', 'create_time', 'join_pay_time' ], $param[ 'where' ])
+ ->withJoin([
+ 'pay' => function(Query $query) use ($pay_where) {
+ $query->where($pay_where);
+ } ], 'left')
+ ->field('order_id')->order('order.create_time desc')->column('order_id');
+
+ $order_goods_field = 'extend,order_goods_id,order_id,member_id,goods_id,sku_id,delivery_id,goods_name,sku_name,goods_image,sku_image,price,num,goods_money,is_enable_refund,goods_type,delivery_status,status';
+ $search_model = $orderGoodsModel->where([ [ 'order_id', 'in', $order_ids ] ])
+ ->with([
+ 'order_delivery' => function($query) {
+ $query->field('id, express_company_id, express_number')->with('company');
+ }
+ ])
+ ->field($order_goods_field)->append([ 'status_name', 'delivery_status_name', 'goods_type_name' ]);
+ if ($param[ 'page' ][ 'page' ] > 0 && $param[ 'page' ][ 'limit' ] > 0) {
+ $data = $search_model->page($param[ 'page' ][ 'page' ], $param[ 'page' ][ 'limit' ])->select()->toArray();
+ } else {
+ $data = $search_model->select()->toArray();
+ }
+
+ $is_first = true;
+ $encountered = array();
+ foreach ($data as $key => $val) {
+
+ if (isset($encountered[ $val[ 'order_id' ] ])) {
+ $is_first = false;
+ } else {
+ $encountered[ $val[ 'order_id' ] ] = true;
+ $is_first = true;
+ }
+ $order_field = 'order_id,invoice_id,order_no,order_type,order_from,out_trade_no,status,member_id,ip,goods_money,delivery_money,order_money,point,discount_money,create_time,pay_time,delivery_type,delivery_time,take_time,finish_time,close_time,taker_name,taker_mobile,taker_full_address,take_store_id,is_enable_refund,member_remark,shop_remark,close_remark';
+ $order_data = $model
+ ->where([ [ 'order_id', '=', $val[ 'order_id' ] ] ])->field($order_field)
+ ->withJoin([ 'pay' ], 'left')
+ ->with([
+ 'member' => function($query) {
+ $query->field('member_id, nickname, mobile, member_no');
+ },
+ 'store' => function($query) {
+ $query->field('store_id, store_name, store_mobile');
+ },
+ 'invoice' => function($query) {
+ $query->where([ [ 'status', '=', InvoiceDict::OPEN ] ])->field('id,header_name,tax_number,type')->append([ 'type_name' ]);
+ }
+ ])->order('order.create_time desc')->append([ 'order_from_name', 'order_type_name', 'status_name', 'delivery_type_name' ])->findOrEmpty();
+
+ $pay = $order_data[ 'pay' ];
+ if (!empty($pay)) {
+ $pay->append([ 'type_name' ]);
+ }
+ $order_data = $order_data->toArray();
+
+ $data[ $key ][ 'order_no' ] = $is_first ? $order_data[ 'order_no' ] . "\t" : '';
+ $data[ $key ][ 'order_from_name' ] = $is_first ? $order_data[ 'order_from_name' ] : '';
+ $data[ $key ][ 'goods_total_money' ] = $is_first ? $order_data[ 'goods_money' ] : '';
+ $data[ $key ][ 'delivery_money' ] = $is_first ? $order_data[ 'delivery_money' ] : '';
+ $data[ $key ][ 'discount_money' ] = $is_first ? $order_data[ 'discount_money' ] : '';
+ $data[ $key ][ 'order_money' ] = $is_first ? $order_data[ 'order_money' ] : '';
+ $data[ $key ][ 'point' ] = $is_first ? $order_data[ 'point' ] : '';
+ $data[ $key ][ 'taker_name' ] = $is_first ? $order_data[ 'taker_name' ] : '';
+ $data[ $key ][ 'taker_mobile' ] = $is_first ? $order_data[ 'taker_mobile' ] . "\t" : '';
+ $data[ $key ][ 'taker_full_address' ] = $is_first ? $order_data[ 'taker_full_address' ] : '';
+ $data[ $key ][ 'delivery_type_name' ] = $is_first ? $order_data[ 'delivery_type_name' ] : '';
+ $data[ $key ][ 'create_time' ] = $is_first ? $order_data[ 'create_time' ] : '';
+ $data[ $key ][ 'pay_time' ] = $is_first ? $order_data[ 'pay_time' ] : '';
+ $data[ $key ][ 'delivery_time' ] = $is_first ? $order_data[ 'delivery_time' ] : '';
+ $data[ $key ][ 'finish_time' ] = $is_first ? $order_data[ 'finish_time' ] : '';
+ $data[ $key ][ 'member_remark' ] = $is_first ? $order_data[ 'member_remark' ] : '';
+ $data[ $key ][ 'shop_remark' ] = $is_first ? $order_data[ 'shop_remark' ] : '';
+ $data[ $key ][ 'close_remark' ] = $is_first ? $order_data[ 'close_remark' ] : '';
+ $data[ $key ][ 'out_trade_no' ] = $is_first ? $order_data[ 'out_trade_no' ] . "\t" : '';
+
+ $data[ $key ][ 'status_name' ] = $is_first ? $order_data[ 'status_name' ][ 'name' ] : '';
+ $data[ $key ][ 'nickname' ] = $is_first ? ( !empty($order_data[ 'member' ]) ? $order_data[ 'member' ][ 'nickname' ] : '' ) : '';
+ $data[ $key ][ 'mobile' ] = $is_first ? ( !empty($order_data[ 'member' ]) ? $order_data[ 'member' ][ 'mobile' ] . "\t" : '' ) : '';
+ $data[ $key ][ 'member_no' ] = $is_first ? ( !empty($order_data[ 'member' ]) ? $order_data[ 'member' ][ 'member_no' ] . "\t" : '' ) : '';
+ $data[ $key ][ 'pay_type' ] = $is_first ? ( !empty($order_data[ 'pay' ]) ? $order_data[ 'pay' ][ 'type_name' ] : '' ) : '';
+ $data[ $key ][ 'invoice_type' ] = $is_first ? ( !empty($order_data[ 'invoice' ]) ? $order_data[ 'invoice' ][ 'type_name' ] : '' ) : '';
+ $data[ $key ][ 'header_name' ] = $is_first ? ( !empty($order_data[ 'invoice' ]) ? $order_data[ 'invoice' ][ 'header_name' ] . "\t" : '' ) : '';
+ $data[ $key ][ 'tax_number' ] = $is_first ? ( !empty($order_data[ 'invoice' ]) ? $order_data[ 'invoice' ][ 'tax_number' ] . "\t" : '' ) : '';
+ $data[ $key ][ 'store_name' ] = $is_first ? ( !empty($order_data[ 'store' ]) ? $order_data[ 'store' ][ 'store_name' ] : '' ) : '';
+ $data[ $key ][ 'pay_time' ] = $is_first ? ( !empty($order_data[ 'pay_time' ]) ? $order_data[ 'pay_time' ] : '' ) : '';
+ $data[ $key ][ 'delivery_time' ] = $is_first ? ( !empty($order_data[ 'delivery_time' ]) ? $order_data[ 'delivery_time' ] : '' ) : '';
+ $data[ $key ][ 'finish_time' ] = $is_first ? ( !empty($order_data[ 'finish_time' ]) ? $order_data[ 'finish_time' ] : '' ) : '';
+
+ $data[ $key ][ 'express_number' ] = !empty($val[ 'order_delivery' ]) ? $val[ 'order_delivery' ][ 'express_number' ] . "\t" : '';
+ $data[ $key ][ 'company_name' ] = !empty($val[ 'order_delivery' ]) ? ( !empty($val[ 'order_delivery' ][ 'company' ]) ? $val[ 'order_delivery' ][ 'company' ][ 'company_name' ] : '' ) : '';
+
+ }
+ }
+ return $data;
+ }
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/app/listener/order_export/ShopOrderExportTypeListener.php b/niucloud/addon/shop/app/listener/order_export/ShopOrderExportTypeListener.php
new file mode 100644
index 000000000..2c51e6b52
--- /dev/null
+++ b/niucloud/addon/shop/app/listener/order_export/ShopOrderExportTypeListener.php
@@ -0,0 +1,67 @@
+ [
+ 'name' => '订单列表',
+ 'column' => [
+ 'order_no' => ['name' => '订单编号'],
+ 'member_no' => ['name' => '会员编号'],
+ 'nickname' => ['name' => '买家昵称'],
+ 'mobile' => ['name' => '买家手机号'],
+ 'goods_name' => ['name' => '商品名称'],
+ 'sku_name' => ['name' => '商品规格'],
+ 'num' => ['name' => '商品数量'],
+ 'price' => ['name' => '商品售价'],
+ 'goods_money' => ['name' => '商品小计'],
+ 'order_from_name' => ['name' => '订单来源'],
+ 'goods_total_money' => ['name' => '商品总价'],
+ 'delivery_money' => ['name' => '配送金额'],
+ 'discount_money' => ['name' => '优惠金额'],
+ 'order_money' => ['name' => '订单金额'],
+ 'point' => [ 'name' => '积分'],
+ 'taker_name' => ['name' => '收货人姓名'],
+ 'taker_mobile' => ['name' => '收货人手机号'],
+ 'taker_full_address' => ['name' => '收货地址'],
+ 'delivery_type_name' => ['name' => '配送方式'],
+ 'status_name' => ['name' => '订单状态'],
+ 'create_time' => ['name' => '订单创建时间'],
+ 'pay_time' => ['name' => '订单支付时间'],
+ 'delivery_time' => ['name' => '订单发货时间'],
+ 'finish_time' => ['name' => '订单完成时间'],
+ 'member_remark' => ['name' => '买家留言'],
+ 'shop_remark' => ['name' => '商家备注'],
+ 'close_remark' => ['name' => '关闭原因'],
+ 'out_trade_no' => ['name' => '支付流水号'],
+ 'pay_type' => ['name' => '支付方式'],
+ 'store_name' => ['name' => '自提门店'],
+ 'express_number' => ['name' => '物流单号'],
+ 'company_name' => ['name' => '物流公司'],
+ 'invoice_type' => ['name' => '发票类型'],
+ 'header_name' => ['name' => '发票抬头'],
+ 'tax_number' => ['name' => '发票税号'],
+ ]
+ ]
+ ];
+ }
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/app/listener/order_export/ShopOrderGoodsExportDataListener.php b/niucloud/addon/shop/app/listener/order_export/ShopOrderGoodsExportDataListener.php
new file mode 100644
index 000000000..52b42371d
--- /dev/null
+++ b/niucloud/addon/shop/app/listener/order_export/ShopOrderGoodsExportDataListener.php
@@ -0,0 +1,100 @@
+where([[ 'order.order_id', '>', 0 ]])->withSearch([ 'search_type', 'order_from', 'join_status', 'create_time', 'join_pay_time' ], $param['where'])
+ ->withJoin([
+ 'pay' => function(Query $query) use($pay_where){
+ $query->where($pay_where);
+ }], 'left')
+ ->field('order_id')->order($order)->column('order_id');
+
+ $order_goods_field = 'order_goods_id,order_id,member_id,delivery_id,goods_name,sku_name,price,num,goods_money,discount_money,order_refund_no,order_goods_money,goods_type,delivery_status,status';
+ $order_field = 'order_id,order_no,order_from,taker_name,taker_mobile,taker_full_address,create_time,pay_time,delivery_money,delivery_type,delivery_time,finish_time,member_remark,shop_remark,out_trade_no,status';
+ $search_model = $orderGoodsModel->where([['order_id', 'in', $order_ids]])
+ ->with([
+ 'order_delivery' => function($query) {
+ $query->field('id, express_company_id, express_number')->with('company');
+ },
+ 'orderMain' =>function ($query) use($order_field) {
+ $query->field($order_field)->with(['pay'])->append([ 'order_from_name', 'status_name', 'delivery_type_name' ]);
+ },
+ 'member' => function($query) {
+ $query->field('member_id, nickname, mobile, member_no');
+ },
+ ])
+ ->field($order_goods_field)->append(['status_name', 'delivery_status_name', 'goods_type_name']);
+
+ $page = intval($param['page']['page']);
+ $limit = intval($param['page']['limit']);
+ if ($page > 0 && $limit > 0) {
+ $data = $search_model->page($page, $limit)->select();
+ } else {
+ $data = $search_model->select();
+ }
+ foreach ($data as $key => $val){
+ $pay = $val['orderMain']['pay'];
+ if(!empty($pay)){
+ $pay->append(['type_name']);
+ }
+ $data[$key]['order_no'] = $val['orderMain']['order_no']."\t";
+ $data[$key]['nickname'] = !empty($val['member']) ? $val['member']['nickname'] : '';
+ $data[$key]['mobile'] = !empty($val['member']) ? $val['member']['mobile'] . "\t" : '';
+ $data[$key]['member_no'] = !empty($val['member']) ? $val['member']['member_no'] . "\t" : '';
+ $data[$key]['order_from_name'] = $val['orderMain']['order_from_name'];
+ $data[$key]['taker_name'] = $val['orderMain']['taker_name'];
+ $data[$key]['taker_mobile'] = $val['orderMain']['taker_mobile'];
+ $data[$key]['taker_full_address'] = $val['orderMain']['taker_full_address'];
+ $data[$key]['delivery_type_name'] = $val['orderMain']['delivery_type_name'];
+ $data[$key]['delivery_money'] = $val['orderMain']['delivery_money'];
+ $data[$key]['order_status_name'] = $val['orderMain']['status_name']['name'];
+ $data[$key]['create_time'] = $val['orderMain']['create_time'];
+ $data[$key]['pay_time'] = !empty($val['orderMain']['pay_time']) ? $val['orderMain']['pay_time'] : '';
+ $data[$key]['delivery_time'] = !empty($val['orderMain']['delivery_time']) ? $val['orderMain']['delivery_time'] : '';
+ $data[$key]['finish_time'] = !empty($val['orderMain']['finish_time']) ? $val['orderMain']['finish_time'] : '';
+ $data[$key]['member_remark'] = $val['orderMain']['member_remark'];
+ $data[$key]['shop_remark'] = $val['orderMain']['shop_remark'];
+ $data[$key]['out_trade_no'] = $val['orderMain']['out_trade_no']."\t";
+ $data[$key]['pay_type'] = !empty($val['orderMain']['pay']) ? $val['orderMain']['pay']['type_name'] : '';
+ $data[$key]['order_refund_no'] = $val['order_refund_no']."\t";
+ $data[$key]['express_number'] = !empty($val['order_delivery']) ? $val['order_delivery']['express_number']."\t" : '';
+ $data[$key]['company_name'] = !empty($val['order_delivery']) ? (!empty($val['order_delivery']['company']) ? $val['order_delivery']['company']['company_name'] : '') : '';
+ }
+ $data = $data->toArray();
+ }
+ return $data;
+ }
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/app/listener/order_export/ShopOrderGoodsExportTypeListener.php b/niucloud/addon/shop/app/listener/order_export/ShopOrderGoodsExportTypeListener.php
new file mode 100644
index 000000000..43365bf95
--- /dev/null
+++ b/niucloud/addon/shop/app/listener/order_export/ShopOrderGoodsExportTypeListener.php
@@ -0,0 +1,67 @@
+ [
+ 'name' => '订单项列表',
+ 'column' => [
+ 'order_no' => ['name' => '订单编号'],
+ 'order_goods_id' => ['name' => '子订单编号'],
+ 'goods_name' => [ 'name' => '商品名称'],
+ 'sku_name' => [ 'name' => '商品规格名称'],
+ 'member_no' => ['name' => '会员编号'],
+ 'nickname' => ['name' => '买家昵称'],
+ 'mobile' => ['name' => '买家手机号'],
+ 'price' => [ 'name' => '商品单价'],
+ 'num' => [ 'name' => '购买数量'],
+ 'goods_money' => [ 'name' => '商品总价'],
+ 'discount_money' => [ 'name' => '优惠金额'],
+ 'order_goods_money' => [ 'name' => '订单项实付金额'],
+ 'order_from_name' => ['name' => '订单来源'],
+ 'goods_type_name' => [ 'name' => '商品类型'],
+ 'taker_name' => ['name' => '收货人姓名'],
+ 'taker_mobile' => ['name' => '收货人手机号'],
+ 'taker_full_address' => ['name' => '收货地址'],
+ 'delivery_type_name' => ['name' => '配送方式'],
+ 'delivery_status_name' => [ 'name' => '配送状态'],
+ 'delivery_money' => ['name' => '配送金额'],
+ 'express_number' => [ 'name' => '物流单号'],
+ 'company_name' => [ 'name' => '物流公司'],
+
+ 'order_status_name' => ['name' => '订单状态'],
+ 'create_time' => ['name' => '订单创建时间'],
+ 'pay_time' => ['name' => '订单支付时间'],
+ 'delivery_time' => ['name' => '订单发货时间'],
+ 'finish_time' => ['name' => '订单完成时间'],
+ 'member_remark' => ['name' => '买家留言'],
+ 'shop_remark' => ['name' => '商家备注'],
+ 'out_trade_no' => ['name' => '支付流水号'],
+ 'pay_type' => ['name' => '支付方式'],
+
+ 'order_refund_no' => [ 'name' => '退款单号'],
+ 'status_name' => [ 'name' => '退款状态']
+ ],
+ ]
+ ];
+ }
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/app/listener/pay/PayCreateListener.php b/niucloud/addon/shop/app/listener/pay/PayCreateListener.php
new file mode 100644
index 000000000..293eebbfa
--- /dev/null
+++ b/niucloud/addon/shop/app/listener/pay/PayCreateListener.php
@@ -0,0 +1,42 @@
+getInfo($params['trade_id']);
+ if ($order_info['status'] != OrderDict::WAIT_PAY) throw new CommonException('SHOP_ONLY_WAIT_PAY_CAN_BE_PAY');
+ //添加订单支付表
+ return [
+ 'main_type' => PayDict::MEMBER,
+ 'main_id' => $order_info['member_id'],//买家id
+ 'money' => $order_info['order_money'],//订单金额
+ 'trade_type' => $trade_type,//业务类型
+ 'trade_id' => $params['trade_id'],
+ 'body' => $order_info['body'],
+ ];
+ }
+ }
+}
diff --git a/niucloud/addon/shop/app/listener/pay/PaySuccessListener.php b/niucloud/addon/shop/app/listener/pay/PaySuccessListener.php
new file mode 100644
index 000000000..ec69fc5e9
--- /dev/null
+++ b/niucloud/addon/shop/app/listener/pay/PaySuccessListener.php
@@ -0,0 +1,28 @@
+pay($pay_info);
+ }
+ }
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/app/listener/pay/RefundSuccessListener.php b/niucloud/addon/shop/app/listener/pay/RefundSuccessListener.php
new file mode 100644
index 000000000..9c9f63779
--- /dev/null
+++ b/niucloud/addon/shop/app/listener/pay/RefundSuccessListener.php
@@ -0,0 +1,34 @@
+transferSuccess([
+ 'refund_no' => $params[ 'refund_no' ],
+ 'order_refund_no' => $params[ 'trade_id' ],
+ ]);
+ return true;
+ }
+ }
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/app/listener/point_exchange/AfterGoodsEdit.php b/niucloud/addon/shop/app/listener/point_exchange/AfterGoodsEdit.php
new file mode 100644
index 000000000..34971e22b
--- /dev/null
+++ b/niucloud/addon/shop/app/listener/point_exchange/AfterGoodsEdit.php
@@ -0,0 +1,32 @@
+getInfo($where);
+ if (!empty($exchange_goods_info)) {
+ $sku_list = (new GoodsSku())->where([['goods_id', '=', $where['goods_id']]])->field('sku_id,stock')->select()->toArray();
+ $sku_list = array_column($sku_list, null, 'sku_id');
+ (new ExchangeService)->afterGoodsEdit($exchange_goods_info, $data['goods_data']['status'], $sku_list);
+ }
+ } catch (\Exception $e) {
+ Log::write('订单AfterShopOrderClose失败' . $e->getMessage() . $e->getFile() . $e->getLine());
+ }
+ }
+}
diff --git a/niucloud/addon/shop/app/listener/point_exchange/AfterShopOrderClose.php b/niucloud/addon/shop/app/listener/point_exchange/AfterShopOrderClose.php
new file mode 100644
index 000000000..925cc0548
--- /dev/null
+++ b/niucloud/addon/shop/app/listener/point_exchange/AfterShopOrderClose.php
@@ -0,0 +1,97 @@
+where($order_goods_where)->select()->toArray();
+ //减去商品主体库存
+ $core_goods_stock_service = new CoreGoodsStockService();
+ foreach ($order_goods_data as $v) {
+ // todo 可以优化 暂不处理
+ $core_goods_stock_service->inc([
+ 'num' => $v['num'],
+ 'goods_id' => $v['goods_id'],
+ 'sku_id' => $v['sku_id'],
+ ]);
+ }
+ //销量 + 兑换数量 +累积分消费 返还
+ $core_goods_sale_num_service = new CoreGoodsSaleNumService();
+ $dec_data = [];
+ foreach ($order_goods_data as $v) {
+ //商品累计销量
+// $core_goods_sale_num_service->dec([
+// 'num' => $v['num'],
+// 'goods_id' => $v['goods_id'],
+// 'sku_id' => $v['sku_id'],
+// 'id' => $order_data['relate_id'],
+// 'point' => $order_data['point'],
+// 'goods_money' => $v['goods_money'],
+// ]);
+
+ $dec_data[] = [
+ 'total_exchange_num' => Db::raw('total_exchange_num-' . $v['num']),
+ 'total_member_num' => Db::raw('total_member_num-1'),
+ 'total_point_num' => Db::raw('total_point_num-' . $order_data['point']),
+ 'total_price_num' => Db::raw('total_price_num-' . $v['goods_money']),
+ 'total_order_num' => Db::raw('total_order_num-1'),
+ 'goods_id' => $v['goods_id'],
+ 'sku_id' => $v['sku_id'],
+ 'id' => $order_data['relate_id'],
+ ];
+
+
+ }
+ $core_goods_sale_num_service->batchUpdate($dec_data);
+ $point = 0;
+ foreach ($order_goods_data as $v) {
+ if (empty($v['order_refund_no'])) {
+ $point = ($v['extend']['point'] ?? 0) * $v['num'];
+ $from_type = 'account_point_exchange_close';
+ $memo = '积分商城订单关闭积分返还';
+ } else {
+ $order_refund_info = (new OrderRefund)->where([
+ ['order_refund_no', '=', $v['order_refund_no']]
+ ])->findOrEmpty();
+ if ($order_refund_info->isEmpty()) throw new CommonException('SHOP_ORDER_REFUND_IS_INVALID');//退款已失效
+// if ($order_refund_info['money'] == $v['order_goods_money']) {
+ $point = ($v['extend']['point'] ?? 0) * $v['num'];
+ $from_type = 'account_point_exchange_refund';
+ $memo = '积分商城订单售后成功积分返还';
+// }
+ }
+ if ($point > 0) {
+ (new CoreMemberAccountService())->addLog($order_data['member_id'], 'point', $order_data['point'], $from_type, $memo ?? '');
+ }
+ }
+ }
+ } catch ( Exception $e ) {
+ Log::write('订单AfterShopOrderClose失败' . $e->getMessage() . $e->getFile() . $e->getLine());
+ }
+ }
+}
diff --git a/niucloud/addon/shop/app/listener/point_exchange/AfterShopOrderCreate.php b/niucloud/addon/shop/app/listener/point_exchange/AfterShopOrderCreate.php
new file mode 100644
index 000000000..1803f7ce4
--- /dev/null
+++ b/niucloud/addon/shop/app/listener/point_exchange/AfterShopOrderCreate.php
@@ -0,0 +1,72 @@
+dec([
+ 'num' => $v['num'],
+ 'goods_id' => $v['goods_id'],
+ 'sku_id' => $v['sku_id']
+ ]);
+ }
+
+ //累增销量 + 兑换数量 +累积分消费..
+ $core_goods_sale_num_service = new CoreGoodsSaleNumService();
+ $inc_data = [];
+ foreach ($order_goods_data as $v) {
+ //商品累计销量
+// $core_goods_sale_num_service->inc([
+// 'num' => $v[ 'num' ],
+// 'goods_id' => $v[ 'goods_id' ],
+// 'sku_id' => $v[ 'sku_id' ],
+// 'id' => $order_data[ 'relate_id' ],
+// 'point' => $order_data[ 'point' ],
+// 'goods_money' => $v[ 'goods_money' ],
+// ]);
+ $inc_data[] = [
+ 'total_exchange_num' => Db::raw('total_exchange_num+' . $v['num']),
+ 'total_member_num' => Db::raw('total_member_num+1'),
+ 'total_point_num' => Db::raw('total_point_num+' . $order_data['point']),
+ 'total_price_num' => Db::raw('total_price_num+' . $v['goods_money']),
+ 'total_order_num' => Db::raw('total_order_num+1'),
+ 'goods_id' => $v['goods_id'],
+ 'sku_id' => $v['sku_id'],
+ 'id' => $order_data['relate_id'],
+ ];
+ }
+ $core_goods_sale_num_service->batchUpdate($inc_data);
+ }
+ } catch (\Exception $e) {
+ Log::write('订单AfterShopOrderCreate失败' . $e->getMessage() . $e->getFile() . $e->getLine());
+ }
+ }
+}
diff --git a/niucloud/addon/shop/app/listener/point_exchange/ShopOrderDiscountCreate.php b/niucloud/addon/shop/app/listener/point_exchange/ShopOrderDiscountCreate.php
new file mode 100644
index 000000000..b0cbc868c
--- /dev/null
+++ b/niucloud/addon/shop/app/listener/point_exchange/ShopOrderDiscountCreate.php
@@ -0,0 +1,26 @@
+addLog($data['order_object']->member_id, 'point', -$data['order_object']->basic['point_sum'], 'account_point_exchange_order', '积分商城消费扣款积分');
+ }
+ } catch (\Exception $e) {
+ throw new CommonException($e->getMessage());
+ }
+ }
+}
diff --git a/niucloud/addon/shop/app/listener/poster/ShopPoster.php b/niucloud/addon/shop/app/listener/poster/ShopPoster.php
new file mode 100644
index 000000000..6c8f238ae
--- /dev/null
+++ b/niucloud/addon/shop/app/listener/poster/ShopPoster.php
@@ -0,0 +1,270 @@
+ 'sku_id', 'value' => $sku_id ]
+ ];
+ $return_data = [
+ 'nickname' => '会员昵称',
+ 'headimg' => 'static/resource/images/default_headimg.png',
+ 'goods_name' => '商品名称',
+ 'goods_price' => '¥369.00',
+ 'goods_market_price' => '¥3690.00',
+ 'goods_img' => 'addon/shop/goods_template.png',
+ 'url' => [
+ 'url' => ( new CoreSysConfigService() )->getSceneDomain()[ 'wap_url' ],
+ 'page' => 'addon/shop/pages/goods/detail',
+ 'data' => $url_data,
+ ],
+ ];
+ return $return_data;
+ }
+
+ // 查询sku信息
+ $sku = ( new GoodsSku() )->where([ [ 'sku_id', '=', $sku_id ] ])->findOrEmpty();
+
+ if ($sku->isEmpty()) return [];
+
+ $goods_id = $sku[ 'goods_id' ];
+ $goods = ( new Goods() )->where([ [ 'goods_id', '=', $goods_id ] ])->findOrEmpty();
+ if ($goods->isEmpty()) return [];
+
+ $goods_name = $goods[ 'goods_name' ] . $sku[ 'sku_name' ];
+// if (mb_strlen($goods_name, 'UTF-8') > 14) {
+// $goods_name = mb_substr($goods_name, 0, 14, 'UTF-8') . '...';
+// }
+
+// $service_ids = $goods['service_ids'];
+// if(!empty($service_ids)){
+// // 商品服务
+// $goods_service_model = new Service();
+// $services = $goods_service_model->where([
+// [ 'service_id', 'in', $service_ids ]
+// ])->column('service_name');
+// $services = implode('·', $services);
+// }
+
+ $sku_img = $sku[ 'sku_image' ];
+ if (empty($sku_img)) {
+ $sku_img = $goods[ 'goods_cover' ];
+ }
+ if (empty($sku_img)) {
+ $sku_img = 'addon/shop/goods_template.png';
+ }
+ $market_price_text = $sku[ 'market_price' ] > 0 ? '¥' . $sku[ 'market_price' ] : '';
+ $url_data = [
+ [ 'key' => 'sku_id', 'value' => $sku_id ]
+ ];
+
+ $member_info = [];
+ $show_price_data[] = $sku[ 'sale_price' ];
+
+ switch ($active){
+ case ActiveDict::NEWCOMER_DISCOUNT:
+ if ($member_id > 0){
+ //查询新人专享活动
+ $newcomer_goods_info = ( new ActiveGoods() )->field('active_id,active_goods_value')->where([
+ [ 'goods_id', '=', $goods_id ],
+ [ 'sku_id', '=', $sku_id ],
+ [ 'active_class', '=', ActiveDict::NEWCOMER_DISCOUNT ]
+ ])->with([
+ 'active' => function($query) {
+ $query->field('active_id,active_desc,active_status,active_value');
+ }
+ ])->findOrEmpty()->toArray();
+
+ if (!empty($newcomer_goods_info) && $newcomer_goods_info[ 'active' ][ 'active_status' ] == ActiveDict::ACTIVE) {
+ $url_data[] = [ 'key' => 'type', 'value' => 'newcomer_discount' ];
+ $newcomer_price = json_decode($newcomer_goods_info[ 'active_goods_value' ], true)[ 'newcomer_price' ];
+ if ($newcomer_price > 0) $show_price_data[] = $newcomer_price;
+ }
+ }
+ break;
+ case ActiveDict::DISCOUNT:
+ //查看商品是否参加限时折扣活动
+ $discount = (new DiscountGoods())->where([
+ [ 'goods_id', '=', $goods_id ],
+ [ 'sku_id', '=', $sku_id ],
+ [ 'status', '=', DiscountDict::ACTIVE ],
+ [ 'is_enabled', '=', DiscountDict::YES ],
+ ])->findOrEmpty();
+ if (!$discount->isEmpty()){
+ $discount_price = $sku[ 'sale_price' ] ?? 0;
+ if ($discount_price >= 0) $show_price_data[] = $discount_price;
+ }
+ break;
+ default:
+ if ($member_id > 0) {
+ $url_data[] = [ 'key' => 'mid', 'value' => $member_id ];
+
+ //查询会员信息
+ $member_info = ( new Member() )->where([ [ 'member_id', '=', $member_id ] ])->findOrEmpty();
+
+ if (!empty($member_info)) {
+ if (empty($member_info[ 'headimg' ])) {
+ $member_info[ 'headimg' ] = 'static/resource/images/default_headimg.png';
+ }
+ }
+
+ // 查询会员价
+ $goods_service = new GoodsService();
+
+ $member_price = $goods_service->getMemberPrice($goods_service->getMemberInfo(), $goods[ 'member_discount' ], $sku[ 'member_price' ], $sku[ 'price' ]);
+ if ($member_price > 0) $show_price_data[] = $member_price;
+ }
+
+ //查看商品是否参加限时折扣活动
+ $discount = (new DiscountGoods())->where([
+ [ 'goods_id', '=', $goods_id ],
+ [ 'sku_id', '=', $sku_id ],
+ [ 'status', '=', DiscountDict::ACTIVE ],
+ [ 'is_enabled', '=', DiscountDict::YES ],
+ ])->findOrEmpty();
+ if (!$discount->isEmpty()){
+ $discount_price = $sku[ 'sale_price' ] ?? 0;
+ if ($discount_price >= 0) $show_price_data[] = $discount_price;
+ }
+
+ }
+ $show_price = min($show_price_data);
+ $max_length = 35;
+ if (mb_strlen($goods_name, 'UTF-8') > $max_length) {
+ $goods_name = mb_substr($goods_name, 0, $max_length, 'UTF-8') . '...';
+ }
+ $return_data = [
+ 'goods_name' => $goods_name,
+// 'services' => $services,
+ 'goods_price' => '¥' . $show_price,
+ 'goods_market_price' => $market_price_text,
+ 'goods_img' => $sku_img,
+ 'url' => [
+ 'url' => ( new CoreSysConfigService() )->getSceneDomain()[ 'wap_url' ],
+ 'page' => 'addon/shop/pages/goods/detail',
+ 'data' => $url_data,
+ ],
+ ];
+ if (!empty($member_info)) {
+ $return_data[ 'nickname' ] = mb_strlen($member_info[ 'nickname' ]) > 10 ? mb_substr($member_info[ 'nickname' ], 0, 7, 'utf-8') . '...' : $member_info[ 'nickname' ];
+ $return_data[ 'headimg' ] = $member_info[ 'headimg' ];
+ }
+ Log::write('海报数据'.json_encode($return_data,256));
+ return $return_data;
+ } elseif ($type == 'shop_point_goods') {
+
+ // 积分商品 海报模板数据
+
+ $param = $data[ 'param' ];
+ $id = $param[ 'id' ] ?? 0;
+ $member_id = $param[ 'member_id' ] ?? 0;
+ $mode = $param[ 'mode' ] ?? '';
+
+ if ($mode == 'preview') {
+ // 预览模式
+ $url_data = [
+ [ 'key' => 'id', 'value' => $id ]
+ ];
+ $return_data = [
+ 'nickname' => '会员昵称',
+ 'headimg' => 'static/resource/images/default_headimg.png',
+ 'goods_name' => '商品名称',
+ 'goods_price' => '积分100+¥369.00',
+ 'goods_img' => 'addon/shop/goods_template.png',
+ 'url' => [
+ 'url' => ( new CoreSysConfigService() )->getSceneDomain()[ 'wap_url' ],
+ 'page' => 'addon/shop/pages/point/detail',
+ 'data' => $url_data,
+ ],
+ ];
+ return $return_data;
+ }
+
+ // 查询sku信息
+ $exchange_info = ( new Exchange() )->withSearch([ 'ids' ], [ 'ids' => $id ])->findOrEmpty();
+ if ($exchange_info->isEmpty()) return [];
+ $goods_name = $exchange_info[ 'names' ];
+// if (mb_strlen($goods_name, 'UTF-8') > 14) {
+// $goods_name = mb_substr($goods_name, 0, 14, 'UTF-8') . '...';
+// }
+ $sku_img = explode(',', $exchange_info[ 'image' ])[ 0 ];
+ if (empty($sku_img)) {
+ $sku_img = 'addon/shop/goods_template.png';
+ }
+ $url_data = [
+ [ 'key' => 'id', 'value' => $id ]
+ ];
+
+ $member_info = [];
+
+ if ($member_id > 0) {
+ $url_data[] = [ 'key' => 'mid', 'value' => $member_id ];
+
+ //查询会员信息
+ $member_info = ( new Member() )->where([ [ 'member_id', '=', $member_id ] ])->findOrEmpty();
+
+ if (!empty($member_info)) {
+ if (empty($member_info[ 'headimg' ])) {
+ $member_info[ 'headimg' ] = 'static/resource/images/default_headimg.png';
+ }
+ }
+ }
+ $price = $exchange_info[ 'price' ] <= 0 ? '' : '+¥' . $exchange_info[ 'price' ];
+ $return_data = [
+ 'goods_name' => $goods_name,
+ 'goods_price' => "积分:" . $exchange_info[ 'point' ] . $price,
+ 'goods_img' => $sku_img,
+ 'url' => [
+ 'url' => ( new CoreSysConfigService() )->getSceneDomain()[ 'wap_url' ],
+ 'page' => 'addon/shop/pages/point/detail',
+ 'data' => $url_data,
+ ],
+ ];
+
+ if (!empty($member_info)) {
+ $return_data[ 'nickname' ] = mb_strlen($member_info[ 'nickname' ]) > 10 ? mb_substr($member_info[ 'nickname' ], 0, 7, 'utf-8') . '...' : $member_info[ 'nickname' ];
+ $return_data[ 'headimg' ] = $member_info[ 'headimg' ];
+ }
+ return $return_data;
+
+ }
+ }
+}
diff --git a/niucloud/addon/shop/app/listener/poster/ShopPosterType.php b/niucloud/addon/shop/app/listener/poster/ShopPosterType.php
new file mode 100644
index 000000000..e128b938d
--- /dev/null
+++ b/niucloud/addon/shop/app/listener/poster/ShopPosterType.php
@@ -0,0 +1,37 @@
+ 'shop_goods',
+ 'addon' => 'shop',
+ 'name' => '商品海报',
+ 'desc' => '推广商品,分享后进入商品详情页',
+ 'icon' => 'addon/shop/poster/type_shop_goods.png'
+ ],
+ [
+ 'type' => 'shop_point_goods',
+ 'addon' => 'shop',
+ 'name' => '积分商品海报',
+ 'desc' => '推广积分商品,分享后进入积分商品详情页',
+ 'icon' => 'addon/shop/poster/type_shop_goods.png'
+ ],
+ ];
+
+ }
+}
diff --git a/niucloud/addon/shop/app/listener/printer/PrinterContentListener.php b/niucloud/addon/shop/app/listener/printer/PrinterContentListener.php
new file mode 100644
index 000000000..1b9e785f6
--- /dev/null
+++ b/niucloud/addon/shop/app/listener/printer/PrinterContentListener.php
@@ -0,0 +1,648 @@
+getList([
+ [ 'status', '=', 1 ],
+ [ 'template_type', 'like', [ '%shopGoodsOrder%' ], 'or' ],
+ [ 'trigger', 'like', [ '%shopGoodsOrder_trigger_pay_after%', '%shopGoodsOrder_trigger_take_delivery%', '%shopGoodsOrder_trigger_manual%' ], 'or' ],
+ ], 'printer_id,brand,printer_name,printer_code,printer_key,open_id,apikey,value');
+
+ if (empty($printer_list)) {
+ return [
+ 'code' => -1,
+ 'message' => '未找到小票打印机'
+ ];
+ }
+
+ // 查询订单信息
+ $order_model = new Order();
+ $field = 'order_id, order_no, order_from, out_trade_no, status, member_id,taker_name, taker_mobile, goods_money, delivery_money, discount_money, order_money, create_time, pay_time, finish_time, delivery_type, take_store_id, taker_name, taker_mobile, taker_full_address, member_remark, shop_remark';
+ $order_info = $order_model->where([ [ 'order_id', '=', $params[ 'business' ][ 'order_id' ] ] ])->field($field)
+ ->with(
+ [
+ 'order_goods' => function($query) {
+ $query->field('order_goods_id, order_id, goods_id, sku_id, goods_name, sku_name, price, num, goods_money, discount_money, status, order_goods_money, original_price')->append([ 'status_name' ]);
+ },
+ 'member' => function($query) {
+ $query->field('member_id,nickname,mobile,balance,point');
+ }
+ ])->append([ 'order_from_name', 'status_name', 'delivery_type_name' ])->findOrEmpty()->toArray();
+
+ if (empty($order_info)) {
+ return [
+ 'code' => -1,
+ 'message' => '未找到订单信息'
+ ];
+ }
+
+ if ($order_info[ 'out_trade_no' ]) {
+ $order_info[ 'pay' ] = ( new Pay() )->where([ [ 'out_trade_no', '=', $order_info[ 'out_trade_no' ] ] ])
+ ->field('out_trade_no, type, pay_time')->append([ 'type_name' ])->findOrEmpty()->toArray();
+ }
+
+ $res_data = [];
+
+ $printer_template_model = new SysPrinterTemplate();
+
+ // 拼装打印内容
+ foreach ($printer_list as $k => $v) {
+
+ if (!empty($v[ 'value' ] [ $params[ 'type' ] ]) && !empty($v[ 'value' ] [ $params[ 'type' ] ] [ 'trigger_' . $params[ 'trigger' ] ])) {
+ $info = $v[ 'value' ] [ $params[ 'type' ] ] [ 'trigger_' . $params[ 'trigger' ] ];
+
+ // 过滤不符合条件的模板
+ if (in_array($order_info[ 'delivery_type' ], $info[ 'print_delivery_type' ]) == false) {
+ continue;
+ }
+
+ // 查询小票模板内容
+ $template_info = $printer_template_model->field('value')->where([
+ [ 'template_id', "=", $info[ 'template_id' ] ],
+ [ 'template_type', '=', $params[ 'type' ] ]
+ ])->findOrEmpty()->toArray();
+
+ if (empty($template_info) && empty($template_info[ 'value' ])) {
+ continue;
+ }
+
+ $template_info_value = $template_info[ 'value' ];
+
+ $content = "" . $info[ 'print_num' ] . "";
+
+ // 获取 票头信息内容
+ $content .= $this->getTicketHeadContent($template_info_value[ 'head_info' ]);
+
+ // 获取 订单信息内容
+ $content .= $this->getOrderInfoContent($template_info_value[ 'order_info' ], $order_info);
+
+ // 获取 商品信息内容
+ $content .= $this->getGoodsInfoContent($template_info_value[ 'goods_info' ], $order_info);
+
+ // 获取 买家/收货信息内容
+ $content .= $this->getMemberInfoContent($template_info_value[ 'buyer_info' ], $order_info);
+
+ // 获取 底部信息内容
+ $content .= $this->getBottomInfoContent($template_info_value[ 'bottom_info' ]);
+
+ $item = [
+ 'printer_info' => $v,
+ 'origin_id' => $order_info[ 'order_no' ], // 内部订单号(32位以内)
+ 'content' => $content
+ ];
+
+ $res_data[] = $item;
+
+ }
+
+ }
+
+ return [
+ 'code' => 0,
+ 'message' => '',
+ 'data' => $res_data
+ ];
+ }
+
+ /**
+ * 获取票头信息内容
+ * @param $data
+ * @return string
+ */
+ private function getTicketHeadContent($data)
+ {
+
+ $content = '';
+
+ // 小票名称
+ if ($data[ 'ticket_name' ][ 'status' ] == 1 && !empty($data[ 'ticket_name' ][ 'value' ])) {
+
+ // 文字大小
+ if ($data[ 'ticket_name' ][ 'fontSize' ] == 'big') {
+ $content .= "";
+ }
+
+ // 文字加粗
+ if ($data[ 'ticket_name' ][ 'fontWeight' ] == 'bold') {
+ $content .= "";
+ }
+
+ $content .= "";
+ $content .= $data[ 'ticket_name' ][ 'value' ];
+ $content .= "";
+
+ if ($data[ 'ticket_name' ][ 'fontWeight' ] == 'bold') {
+ $content .= "";
+ }
+
+ // 文字大小
+ if ($data[ 'ticket_name' ][ 'fontSize' ] == 'big') {
+ $content .= "";
+ }
+
+ $content .= str_repeat('.', 32);
+ }
+
+ $site_info = ( new ConfigService() )->getWebSite();
+
+ // 商城名称
+ if ($data[ 'shop_name' ][ 'status' ] == 1 && !empty($site_info[ 'site_name' ])) {
+
+ // 文字大小
+ if ($data[ 'shop_name' ][ 'fontSize' ] == 'big') {
+ $content .= "";
+ }
+
+ // 文字加粗
+ if ($data[ 'shop_name' ][ 'fontWeight' ] == 'bold') {
+ $content .= "";
+ }
+
+ $content .= "";
+ $content .= $site_info[ 'site_name' ];
+ $content .= "";
+
+ if ($data[ 'shop_name' ][ 'fontWeight' ] == 'bold') {
+ $content .= "";
+ }
+
+ // 文字大小
+ if ($data[ 'shop_name' ][ 'fontSize' ] == 'big') {
+ $content .= "";
+ }
+
+ $content .= str_repeat('.', 32);
+ }
+
+ return $content;
+ }
+
+ /**
+ * 获取订单信息内容
+ * @param $data
+ * @param $order_info
+ * @return string
+ */
+ private function getOrderInfoContent($data, $order_info)
+ {
+ $content = '';
+
+ // 订单基础信息
+ if ($data[ 'order_item' ][ 'status' ] == 1 && !empty($data[ 'order_item' ][ 'value' ])) {
+
+ // 订单编号
+ if (in_array('order_no', $data[ 'order_item' ][ 'value' ])) {
+ $content .= '订单编号:' . $order_info[ 'order_no' ] . "\n";
+ }
+
+ // 订单来源
+ if (in_array('order_from', $data[ 'order_item' ][ 'value' ])) {
+ $content .= '订单来源:' . $order_info[ 'order_from_name' ] . "\n";
+ }
+
+ // 订单状态
+ if (in_array('order_status', $data[ 'order_item' ][ 'value' ])) {
+ $content .= '订单状态:' . $order_info[ 'status_name' ][ 'name' ] . "\n";
+ }
+
+ // 支付方式
+ if (in_array('pay_type', $data[ 'order_item' ][ 'value' ])) {
+ $content .= '支付方式:' . $order_info[ 'pay' ][ 'type_name' ] . "\n";
+ }
+
+ // 配送方式
+ if (in_array('delivery_type', $data[ 'order_item' ][ 'value' ])) {
+ $content .= '配送方式:' . $order_info[ 'delivery_type_name' ] . "\n";
+ }
+
+ // 下单时间
+ if (in_array('create_time', $data[ 'order_item' ][ 'value' ])) {
+ $content .= '下单时间:' . $order_info[ 'create_time' ] . "\n";
+ }
+
+ // 付款时间
+ if (in_array('pay_time', $data[ 'order_item' ][ 'value' ])) {
+ $content .= '付款时间:' . $order_info[ 'pay_time' ] . "\n";
+ }
+
+ // 商品总额
+ if (in_array('goods_money', $data[ 'order_item' ][ 'value' ]) && $order_info[ 'goods_money' ] > 0) {
+ $content .= '商品总额:¥' . $order_info[ 'goods_money' ] . "\n";
+ }
+
+ // 优惠金额
+ if (in_array('discount_money', $data[ 'order_item' ][ 'value' ]) && $order_info[ 'discount_money' ] > 0) {
+ $content .= '优惠金额:¥' . $order_info[ 'discount_money' ] . "\n";
+ }
+
+ // 配送金额
+ if (in_array('delivery_money', $data[ 'order_item' ][ 'value' ]) && $order_info[ 'delivery_money' ] > 0) {
+ $content .= '配送金额:¥' . $order_info[ 'delivery_money' ] . "\n";
+ }
+
+ }
+
+ // 实付金额
+ if ($data[ 'order_money' ][ 'status' ] == 1) {
+
+ // 文字大小
+ if ($data[ 'order_money' ][ 'fontSize' ] == 'big') {
+ $content .= "";
+ }
+
+ // 文字加粗
+ if ($data[ 'order_money' ][ 'fontWeight' ] == 'bold') {
+ $content .= "";
+ }
+
+ $content .= '实付金额:¥' . $order_info[ 'order_money' ];
+
+ if ($data[ 'order_money' ][ 'fontWeight' ] == 'bold') {
+ $content .= "";
+ }
+
+ // 文字大小
+ if ($data[ 'order_money' ][ 'fontSize' ] == 'big') {
+ $content .= "";
+ }
+
+ $content .= "\n";
+ }
+
+ // 商家备注
+ if ($data[ 'shop_remark' ][ 'status' ] == 1 && !empty($order_info[ 'shop_remark' ])) {
+
+ // 文字大小
+ if ($data[ 'shop_remark' ][ 'fontSize' ] == 'big') {
+ $content .= "";
+ }
+
+ // 文字加粗
+ if ($data[ 'shop_remark' ][ 'fontWeight' ] == 'bold') {
+ $content .= "";
+ }
+
+ $content .= '商家备注:' . $order_info[ 'shop_remark' ] . "\n";
+
+ if ($data[ 'shop_remark' ][ 'fontWeight' ] == 'bold') {
+ $content .= "";
+ }
+
+ // 文字大小
+ if ($data[ 'shop_remark' ][ 'fontSize' ] == 'big') {
+ $content .= "";
+ }
+ }
+
+ if ($data[ 'order_item' ][ 'status' ] == 1 || $data[ 'order_money' ][ 'status' ] == 1 || $data[ 'shop_remark' ][ 'status' ] == 1) {
+ $content .= str_repeat('.', 32);
+ }
+
+ return $content;
+ }
+
+ /**
+ * 获取 商品信息内容
+ * @param $data
+ * @param $order_info
+ * @return string
+ */
+ private function getGoodsInfoContent($data, $order_info)
+ {
+ $content = '';
+
+ $content .= "";
+ $content .= "";
+
+ $content .= "| 商品名称 | ";
+ $content .= " | ";
+ $content .= "数量 | ";
+
+ if ($data[ 'goods_price' ][ 'status' ] == 1) {
+ $content .= "金额 | ";
+ }
+
+ $content .= "
";
+ $content .= "
\n";
+
+ $content .= "";
+ foreach ($order_info[ 'order_goods' ] as $goods_k => $goods_v) {
+
+ $content .= "";
+
+ $content .= "| ";
+
+ // 文字大小
+ if ($data[ 'goods_name' ][ 'fontSize' ] == 'big') {
+ $content .= "";
+ }
+
+ // 文字加粗
+ if ($data[ 'goods_name' ][ 'fontWeight' ] == 'bold') {
+ $content .= "";
+ }
+
+ $content .= $goods_v[ 'goods_name' ] . ' ' . $goods_v[ 'sku_name' ];
+
+ // 文字加粗
+ if ($data[ 'goods_name' ][ 'fontWeight' ] == 'bold') {
+ $content .= "";
+ }
+
+ // 文字大小
+ if ($data[ 'goods_name' ][ 'fontSize' ] == 'big') {
+ $content .= "";
+ }
+
+ $content .= " | ";
+
+ $content .= " | ";
+ $content .= "x" . $goods_v[ 'num' ] . " | ";
+
+ if ($data[ 'goods_price' ][ 'status' ] == 1) {
+ $content .= "";
+
+ // 文字大小
+ if ($data[ 'goods_price' ][ 'fontSize' ] == 'big') {
+ $content .= "";
+ }
+
+ // 文字加粗
+ if ($data[ 'goods_price' ][ 'fontWeight' ] == 'bold') {
+ $content .= "";
+ }
+
+ $content .= "¥" . $goods_v[ 'price' ];
+
+ // 文字加粗
+ if ($data[ 'goods_price' ][ 'fontWeight' ] == 'bold') {
+ $content .= "";
+ }
+
+ // 文字大小
+ if ($data[ 'goods_price' ][ 'fontSize' ] == 'big') {
+ $content .= "";
+ }
+
+ $content .= " | ";
+ }
+ $content .= "
";
+
+ }
+
+ $content .= "
\n";
+ $content .= str_repeat('.', 32);
+ return $content;
+ }
+
+ /**
+ * 获取 买家/收货信息内容
+ * @param $data
+ * @param $order_info
+ * @return string
+ */
+ private function getMemberInfoContent($data, $order_info)
+ {
+ $content = '';
+
+ // 会员基础信息
+ if ($data[ 'member_basic_info' ][ 'status' ] == 1) {
+
+ // 买家昵称
+ if (in_array('nickname', $data[ 'member_basic_info' ][ 'value' ])) {
+ $content .= '会员昵称:' . $order_info[ 'member' ][ 'nickname' ] . "\n";
+ }
+
+ // 账户余额
+ if (in_array('account_balance', $data[ 'member_basic_info' ][ 'value' ])) {
+ $content .= '账户余额:¥' . $order_info[ 'member' ][ 'balance' ] . "\n";
+ }
+
+ // 账户积分
+ if (in_array('account_point', $data[ 'member_basic_info' ][ 'value' ])) {
+ $content .= '账户积分:' . $order_info[ 'member' ][ 'point' ] . "\n";
+ }
+
+ }
+
+ // 买家手机号
+ if ($data[ 'buyer_mobile' ][ 'status' ] == 1 && !empty($order_info[ 'member' ][ 'mobile' ])) {
+
+ // 文字大小
+ if ($data[ 'buyer_mobile' ][ 'fontSize' ] == 'big') {
+ $content .= "";
+ }
+
+ // 文字加粗
+ if ($data[ 'buyer_mobile' ][ 'fontWeight' ] == 'bold') {
+ $content .= "";
+ }
+
+ if ($data[ 'buyer_mobile' ][ 'value' ] == 'yes') {
+ $content .= '会员手机号:' . substr($order_info[ 'member' ][ 'mobile' ], 0, 3) . '****' . substr($order_info[ 'member' ][ 'mobile' ], 6 + 1);
+ } else {
+ $content .= '会员手机号:' . $order_info[ 'member' ][ 'mobile' ];
+ }
+
+ if ($data[ 'buyer_mobile' ][ 'fontWeight' ] == 'bold') {
+ $content .= "";
+ }
+
+ // 文字大小
+ if ($data[ 'buyer_mobile' ][ 'fontSize' ] == 'big') {
+ $content .= "";
+ }
+
+ $content .= "\n";
+
+ $content .= str_repeat('.', 32);
+ }
+
+ // 收货人姓名
+ if ($data[ 'taker_name' ][ 'status' ] == 1 && !empty($order_info[ 'taker_name' ])) {
+
+ // 文字大小
+ if ($data[ 'taker_name' ][ 'fontSize' ] == 'big') {
+ $content .= "";
+ }
+
+ // 文字加粗
+ if ($data[ 'taker_name' ][ 'fontWeight' ] == 'bold') {
+ $content .= "";
+ }
+
+ $content .= '收货人:' . $order_info[ 'taker_name' ];
+
+ if ($data[ 'taker_name' ][ 'fontWeight' ] == 'bold') {
+ $content .= "";
+ }
+
+ // 文字大小
+ if ($data[ 'taker_name' ][ 'fontSize' ] == 'big') {
+ $content .= "";
+ }
+
+ $content .= "\n";
+
+ }
+
+ // 收货人手机号
+ if ($data[ 'taker_mobile' ][ 'status' ] == 1) {
+
+ // 文字大小
+ if ($data[ 'taker_mobile' ][ 'fontSize' ] == 'big') {
+ $content .= "";
+ }
+
+ // 文字加粗
+ if ($data[ 'taker_mobile' ][ 'fontWeight' ] == 'bold') {
+ $content .= "";
+ }
+
+ if ($data[ 'taker_mobile' ][ 'value' ] == 'yes') {
+ $content .= '联系方式:' . substr($order_info[ 'taker_mobile' ], 0, 3) . '****' . substr($order_info[ 'taker_mobile' ], 6 + 1);
+ } else {
+ $content .= '联系方式:' . $order_info[ 'taker_mobile' ];
+ }
+
+ if ($data[ 'taker_mobile' ][ 'fontWeight' ] == 'bold') {
+ $content .= "";
+ }
+
+ // 文字大小
+ if ($data[ 'taker_mobile' ][ 'fontSize' ] == 'big') {
+ $content .= "";
+ }
+
+ $content .= "\n";
+
+ }
+
+ // 收货人地址
+ if ($data[ 'taker_full_address' ][ 'status' ] == 1) {
+
+ // 文字大小
+ if ($data[ 'taker_full_address' ][ 'fontSize' ] == 'big') {
+ $content .= "";
+ }
+
+ // 文字加粗
+ if ($data[ 'taker_full_address' ][ 'fontWeight' ] == 'bold') {
+ $content .= "";
+ }
+
+ $content .= '收货地址:' . $order_info[ 'taker_full_address' ];
+
+ if ($data[ 'taker_full_address' ][ 'fontWeight' ] == 'bold') {
+ $content .= "";
+ }
+
+ // 文字大小
+ if ($data[ 'taker_full_address' ][ 'fontSize' ] == 'big') {
+ $content .= "";
+ }
+
+ $content .= "\n";
+
+ }
+
+ // 买家备注
+ if ($data[ 'member_remark' ][ 'status' ] == 1 && !empty($order_info[ 'member_remark' ])) {
+
+ // 文字大小
+ if ($data[ 'member_remark' ][ 'fontSize' ] == 'big') {
+ $content .= "";
+ }
+
+ // 文字加粗
+ if ($data[ 'member_remark' ][ 'fontWeight' ] == 'bold') {
+ $content .= "";
+ }
+
+ $content .= '买家备注:' . $order_info[ 'member_remark' ];
+
+ if ($data[ 'member_remark' ][ 'fontWeight' ] == 'bold') {
+ $content .= "";
+ }
+
+ // 文字大小
+ if ($data[ 'member_remark' ][ 'fontSize' ] == 'big') {
+ $content .= "";
+ }
+
+ $content .= "\n";
+ }
+
+ if ($data[ 'member_basic_info' ][ 'status' ] == 1 || $data[ 'buyer_mobile' ][ 'status' ] == 1 ||
+ $data[ 'taker_name' ][ 'status' ] == 1 || $data[ 'taker_mobile' ][ 'status' ] == 1 ||
+ $data[ 'taker_full_address' ][ 'status' ] == 1 || $data[ 'member_remark' ][ 'status' ] == 1) {
+ $content .= "\n";
+ }
+
+ return $content;
+ }
+
+ /**
+ * 获取 底部信息内容
+ * @param $data
+ * @return string
+ */
+ private function getBottomInfoContent($data)
+ {
+ $content = '';
+
+ // 二维码
+ if ($data[ 'qrcode' ][ 'status' ] == 1) {
+ $content .= "" . $data[ 'qrcode' ][ 'value' ] . "\n\n";
+ }
+
+ // 小票打印时间
+ if ($data[ 'ticket_print_time' ][ 'status' ] == 1) {
+ $content .= '打印时间:' . date('Y-m-d H:i:s', time()) . "\n";
+ }
+
+ // 底部信息
+ if ($data[ 'bottom_remark' ][ 'status' ] == 1) {
+ $content .= "" . $data[ 'bottom_remark' ][ 'value' ] . "\n";
+ }
+
+ return $content;
+ }
+
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/app/listener/recharge/GiftContentListener.php b/niucloud/addon/shop/app/listener/recharge/GiftContentListener.php
new file mode 100644
index 000000000..c5b82080e
--- /dev/null
+++ b/niucloud/addon/shop/app/listener/recharge/GiftContentListener.php
@@ -0,0 +1,34 @@
+ $v) {
+ $data[ 'detail' ][] = $v[ 'num' ] . '张 ' . ( isset($v[ 'title' ]) ? $v[ 'title' ] : '' );
+ }
+ }
+ return $data;
+ }
+}
diff --git a/niucloud/addon/shop/app/listener/recharge/RechargeAfterListener.php b/niucloud/addon/shop/app/listener/recharge/RechargeAfterListener.php
new file mode 100644
index 000000000..275fe65fa
--- /dev/null
+++ b/niucloud/addon/shop/app/listener/recharge/RechargeAfterListener.php
@@ -0,0 +1,42 @@
+ $value) {
+ if ($key == 'coupon') {
+ Log::write('会员充值赠送优惠券开始', json_encode($value[ 'value' ]));
+ foreach ($value[ 'value' ] as $v) {
+ try {
+ ( new CoreCouponMemberService() )->sendCoupon($member_id, $v[ 'coupon_id' ], $v[ 'num' ]);
+ } catch (CommonException $e) {
+ Log::write('会员充值赠送优惠券“' . $v[ 'coupon_id' ] . '”发放失败,错误原因:' . $e->getMessage() . $e->getFile() . $e->getLine());
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/niucloud/addon/shop/app/listener/refund/AfterShopOrderRefundActiveCreate.php b/niucloud/addon/shop/app/listener/refund/AfterShopOrderRefundActiveCreate.php
new file mode 100644
index 000000000..8d9859fc3
--- /dev/null
+++ b/niucloud/addon/shop/app/listener/refund/AfterShopOrderRefundActiveCreate.php
@@ -0,0 +1,48 @@
+add([
+ 'order_refund_no' => $refund_data[ 'order_refund_no' ],
+ 'status' => $refund_data[ 'status' ],
+ 'main_type' => $main_type,//todo 可以是传入的
+ 'main_id' => $main_id,
+ 'type' => OrderRefundDict::SHOP_ACTIVE_REFUND_ACTION,
+ 'content' => '商品【'.$order_goods_info['goods_name'].' '.$order_goods_info['sku_name'].'】商家主动退款,退款金额:'.$refund_data['money'].'元,退款说明:'.$refund_data['remark']
+ ]);
+
+ //todo 消息发送
+
+ if ($refund_data[ 'status' ] == OrderRefundDict::STORE_AGREE_REFUND_WAIT_TRANSFER) {
+ if ($refund_data['money'] > 0) {
+ //订单到达待付款
+ (new CoreRefundService())->toTransfer($refund_data, $main_type, $main_id);
+ } else {
+ (new CoreRefundService())->finish([
+ 'order_refund_no' => $refund_data['order_refund_no'],
+ 'main_type' => $main_type,
+ 'main_id' => $main_id
+ ]);
+ }
+ }
+ }
+}
diff --git a/niucloud/addon/shop/app/listener/refund/AfterShopOrderRefundApply.php b/niucloud/addon/shop/app/listener/refund/AfterShopOrderRefundApply.php
new file mode 100644
index 000000000..cd3841249
--- /dev/null
+++ b/niucloud/addon/shop/app/listener/refund/AfterShopOrderRefundApply.php
@@ -0,0 +1,41 @@
+where([ [ 'order_id', '=', $refund_data[ 'order_id' ] ] ])->findOrEmpty();
+ //通知三方应用更新订单状态
+ if(!empty($order['relate_source'])){
+ (new CoreOrderNoticeService())->sendRefundApplyNotice($refund_data,$order['relate_source'],$order['relate_order_id']);
+ }
+ //日志
+ (new CoreRefundLogService())->add([
+ 'order_refund_no' => $refund_data['order_refund_no'],
+ 'status' => $refund_data['status'],
+ 'main_type' => $main_type,//todo 可以是传入的
+ 'main_id' => $main_id,
+ 'type' => OrderRefundDict::APPLY_ACTION,
+ 'content' => ''
+ ]);
+ //消息发送
+
+ }
+}
diff --git a/niucloud/addon/shop/app/listener/refund/AfterShopOrderRefundAuditApply.php b/niucloud/addon/shop/app/listener/refund/AfterShopOrderRefundAuditApply.php
new file mode 100644
index 000000000..211591462
--- /dev/null
+++ b/niucloud/addon/shop/app/listener/refund/AfterShopOrderRefundAuditApply.php
@@ -0,0 +1,55 @@
+add([
+ 'order_refund_no' => $refund_data[ 'order_refund_no' ],
+ 'status' => $refund_data[ 'status' ],
+ 'main_type' => $main_type,//todo 可以是传入的
+ 'main_id' => $main_id,
+ 'type' => $log_type,
+ 'content' => ''
+ ]);
+
+ //消息发送
+ $message_key = $refund_data[ 'status' ] == OrderRefundDict::STORE_REFUSE_REFUND_GOODS_APPLY_WAIT_BUYER ? 'shop_refund_refuse' : 'shop_refund_agree';
+ ( new NoticeService() )->send($message_key, [ 'order_refund_no' => $refund_data[ 'order_refund_no' ] ]);
+ if ($refund_data[ 'status' ] == OrderRefundDict::STORE_AGREE_REFUND_WAIT_TRANSFER) {
+ if ($refund_data[ 'money' ] > 0) {
+ //订单到达待付款
+ ( new CoreRefundService() )->toTransfer($refund_data, $main_type, $main_id);
+ } else {
+ ( new CoreRefundService() )->finish([
+ 'order_refund_no' => $refund_data[ 'order_refund_no' ],
+ 'main_type' => $main_type,
+ 'main_id' => $main_id
+ ]);
+ }
+ }
+
+ }
+}
diff --git a/niucloud/addon/shop/app/listener/refund/AfterShopOrderRefundAuditRefundGoods.php b/niucloud/addon/shop/app/listener/refund/AfterShopOrderRefundAuditRefundGoods.php
new file mode 100644
index 000000000..80696e211
--- /dev/null
+++ b/niucloud/addon/shop/app/listener/refund/AfterShopOrderRefundAuditRefundGoods.php
@@ -0,0 +1,52 @@
+add([
+ 'order_refund_no' => $refund_data['order_refund_no'],
+ 'status' => $refund_data['status'],
+ 'main_type' => $main_type,//todo 可以是传入的
+ 'main_id' => $main_id,
+ 'type' => $log_type,
+ 'content' => ''
+ ]);
+ //消息发送
+
+ if($refund_data['status'] == OrderRefundDict::STORE_AGREE_REFUND_WAIT_TRANSFER){
+ if($refund_data['money'] > 0){
+ //订单到达待付款
+ (new CoreRefundService())->toTransfer($refund_data, $main_type, $main_id);
+ }else{
+ (new CoreRefundService())->finish([
+ 'order_refund_no' => $refund_data['order_refund_no'],
+ 'main_type' => $main_type,
+ 'main_id' => $main_id
+ ]);
+ }
+ }
+
+ }
+}
diff --git a/niucloud/addon/shop/app/listener/refund/AfterShopOrderRefundClose.php b/niucloud/addon/shop/app/listener/refund/AfterShopOrderRefundClose.php
new file mode 100644
index 000000000..b6b4973af
--- /dev/null
+++ b/niucloud/addon/shop/app/listener/refund/AfterShopOrderRefundClose.php
@@ -0,0 +1,50 @@
+where([['order_id', '=', $refund_data['order_id']]])->findOrEmpty();
+ if(!$order->isEmpty()){
+ if($order['status'] == OrderDict::WAIT_DELIVERY) {
+ //校验一下订单项是否全部发货
+ (new CoreOrderDeliveryService())->checkFinish(
+ ['order_id' => $refund_data['order_id']]
+ );
+ }
+ }
+ $main_type = $data['main_type'] ?? OrderRefundLogDict::MEMBER;
+ $main_id = $data['main_id'] ?? $refund_data['member_id'];
+ //通知三方应用更新订单状态
+ if(!empty($order['relate_source'])){
+ (new CoreOrderNoticeService())->sendRefundCloseNotice($refund_data,$order['relate_source'],$order['relate_order_id']);
+ }
+ //日志
+ (new CoreRefundLogService())->add([
+ 'order_refund_no' => $refund_data['order_refund_no'],
+ 'status' => $refund_data['status'],
+ 'main_type' => $main_type,//todo 可以是传入的
+ 'main_id' => $main_id,
+ 'type' => OrderRefundDict::CLOSE_ACTION,
+ 'content' => ''
+ ]);
+
+ }
+}
diff --git a/niucloud/addon/shop/app/listener/refund/AfterShopOrderRefundDelivery.php b/niucloud/addon/shop/app/listener/refund/AfterShopOrderRefundDelivery.php
new file mode 100644
index 000000000..bdddc8133
--- /dev/null
+++ b/niucloud/addon/shop/app/listener/refund/AfterShopOrderRefundDelivery.php
@@ -0,0 +1,32 @@
+add([
+ 'order_refund_no' => $refund_data['order_refund_no'],
+ 'status' => $refund_data['status'],
+ 'main_type' => $main_type,//todo 可以是传入的
+ 'main_id' => $main_id,
+ 'type' => OrderRefundDict::DELIVERY_ACTION,
+ 'content' => ''
+ ]);
+ //消息发送
+ }
+}
diff --git a/niucloud/addon/shop/app/listener/refund/AfterShopOrderRefundEdit.php b/niucloud/addon/shop/app/listener/refund/AfterShopOrderRefundEdit.php
new file mode 100644
index 000000000..f0a951e0d
--- /dev/null
+++ b/niucloud/addon/shop/app/listener/refund/AfterShopOrderRefundEdit.php
@@ -0,0 +1,32 @@
+add([
+ 'order_refund_no' => $refund_data['order_refund_no'],
+ 'status' => $refund_data['status'],
+ 'main_type' => $main_type,
+ 'main_id' => $main_id,
+ 'type' => OrderRefundDict::EDIT_APPLY_ACTION,
+ 'content' => ''
+ ]);
+ //消息发送
+ }
+}
diff --git a/niucloud/addon/shop/app/listener/refund/AfterShopOrderRefundEditDelivery.php b/niucloud/addon/shop/app/listener/refund/AfterShopOrderRefundEditDelivery.php
new file mode 100644
index 000000000..354a2d8e3
--- /dev/null
+++ b/niucloud/addon/shop/app/listener/refund/AfterShopOrderRefundEditDelivery.php
@@ -0,0 +1,32 @@
+add([
+ 'order_refund_no' => $refund_data['order_refund_no'],
+ 'status' => $refund_data['status'],
+ 'main_type' => $main_type,
+ 'main_id' => $main_id,
+ 'type' => OrderRefundDict::EDIT_DELIVERY_ACTION,
+ 'content' => ''
+ ]);
+ //消息发送
+ }
+}
diff --git a/niucloud/addon/shop/app/listener/refund/AfterShopOrderRefundFinish.php b/niucloud/addon/shop/app/listener/refund/AfterShopOrderRefundFinish.php
new file mode 100644
index 000000000..cda4f15b6
--- /dev/null
+++ b/niucloud/addon/shop/app/listener/refund/AfterShopOrderRefundFinish.php
@@ -0,0 +1,70 @@
+where([ [ 'order_id', '=', $refund_data[ 'order_id' ] ] ])->findOrEmpty();
+
+ //满减送订单退款完成后退还赠品
+ ( new CoreManjianService() )->refundGift($refund_data);
+
+ if (!$order->isEmpty()) {
+ if ($order[ 'status' ] == OrderDict::WAIT_DELIVERY) {
+ //校验一下订单项是否全部发货
+ ( new CoreOrderDeliveryService() )->checkFinish(
+ [ 'order_id' => $refund_data[ 'order_id' ]]
+ );
+ }
+ //校验一下是否全部退款
+ if ($order[ 'status' ] != OrderDict::CLOSE) {
+ ( new CoreOrderCloseService() )->checkAllClose([ 'order_id' => $refund_data[ 'order_id' ] ]);
+ }
+ }
+ //商城统计
+ CoreStatService::addStat([ 'refund_money' => $refund_data[ 'money' ] ]);
+
+ ( new CoreGoodsStatService() )->saveGoodsRefundNumAndMoneyByOrderId($refund_data); // 商品退款数量 金额统计数据
+
+ //日志
+ $main_type = $data[ 'main_type' ] ?? OrderRefundLogDict::SYSTEM;
+ $main_id = $data[ 'main_id' ] ?? 0;
+ //日志
+ ( new CoreRefundLogService() )->add([
+ 'order_refund_no' => $refund_data[ 'order_refund_no' ],
+ 'status' => $refund_data[ 'status' ],
+ 'main_type' => $main_type,
+ 'main_id' => $main_id,
+ 'type' => OrderRefundDict::FINISH_ACTION,
+ 'content' => ''
+ ]);
+ //消息发送
+
+ //通知三方应用更新订单状态
+ if(!empty($order['relate_source'])){
+ (new CoreOrderNoticeService())->sendRefundFinishNotice($refund_data,$order['relate_source'],$order['relate_order_id']);
+ }
+ }
+}
diff --git a/niucloud/addon/shop/app/listener/refund_export/ShopOrderRefundExportDataListener.php b/niucloud/addon/shop/app/listener/refund_export/ShopOrderRefundExportDataListener.php
new file mode 100644
index 000000000..3b5129447
--- /dev/null
+++ b/niucloud/addon/shop/app/listener/refund_export/ShopOrderRefundExportDataListener.php
@@ -0,0 +1,68 @@
+withSearch([ 'order_refund_no', 'status', 'create_time' ], $param['where'])
+ ->field($field)
+ ->with(
+ [
+ 'order_goods' => function($query) {
+ $query->field('order_goods_id, order_id, member_id, goods_id, sku_id, goods_name, sku_name, goods_image, sku_image, price, num, goods_money,discount_money, is_enable_refund, goods_type')->append([ 'goods_image_thumb_small' ]);
+ },
+ 'member' => function($query) {
+ $query->field('member_id, nickname');
+ }
+ ])->order($order)->append([ 'status_name', 'refund_type_name' ]);
+ if ($param['page']['page'] > 0 && $param['page']['limit'] > 0) {
+ $data = $search_model->page($param['page']['page'], $param['page']['limit'])->select()->toArray();
+ } else {
+ $data = $search_model->select()->toArray();
+ }
+ foreach ($data as $key => $val) {
+ $data[$key]['nickname'] = $val['member']['nickname'];
+ }
+ foreach ($data as $key => $val) {
+ $data[$key]['order_refund_no'] = $val['order_refund_no']."\t";
+ $data[$key]['nickname'] = !empty($val['member']) ? $val['member']['nickname'] : '';
+ $data[$key]['goods_info'] = $val['order_goods']['goods_name'].' '.$val['order_goods']['sku_name'];
+ $data[$key]['refund_num'] = $val['order_goods']['num'];
+ $data[$key]['create_time'] = !empty($val['create_time']) ? $val['create_time'] : '';
+ $data[$key]['transfer_time'] = !empty($val['transfer_time']) ? $val['transfer_time'] : '';
+ $data[$key]['refund_no'] = $val['refund_no']."\t";
+ $data[$key]['contact_name'] = !empty($val['refund_address']) ? $val['refund_address']['contact_name'] : '';
+ $data[$key]['refund_address'] = !empty($val['refund_address']) ? $val['refund_address']['full_address'] : '';
+ $data[$key]['express_number'] = !empty($val['delivery']) ? $val['delivery']['express_number'] : '';
+ $data[$key]['express_company'] = !empty($val['delivery']) ? $val['delivery']['express_company'] : '';
+ }
+ }
+ return $data;
+ }
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/app/listener/refund_export/ShopOrderRefundExportTypeListener.php b/niucloud/addon/shop/app/listener/refund_export/ShopOrderRefundExportTypeListener.php
new file mode 100644
index 000000000..4f26d189b
--- /dev/null
+++ b/niucloud/addon/shop/app/listener/refund_export/ShopOrderRefundExportTypeListener.php
@@ -0,0 +1,48 @@
+ [
+ 'name' => '退款售后',
+ 'column' => [
+ 'order_refund_no' => [ 'name' => '退款单号'],
+ 'nickname' => [ 'name' => '会员昵称'],
+ 'refund_type_name' => [ 'name' => '退款方式'],
+ 'apply_money' => [ 'name' => '申请退款金额'],
+ 'goods_info' => [ 'name' => '退货商品信息'],
+ 'refund_num' => [ 'name' => '退货数量'],
+ 'money' => [ 'name' => '实际退款金额'],
+ 'status_name' => [ 'name' => '退款状态'],
+ 'create_time' => [ 'name' => '申请时间'],
+ 'transfer_time' => [ 'name' => '转账时间'],
+ 'refund_no' => [ 'name' => '退款交易号'],
+ 'reason' => [ 'name' => '退款原因'],
+ 'shop_reason' => [ 'name' => '拒绝原因'],
+ 'contact_name' => [ 'name' => '退货联系人'],
+ 'refund_address' => [ 'name' => '退货地址'],
+ 'express_number' => [ 'name' => '退货物流单号'],
+ 'express_company' => [ 'name' => '退货物流公司'],
+ ]
+ ]
+ ];
+ }
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/app/listener/seckill/SeckillOrderCreateListener.php b/niucloud/addon/shop/app/listener/seckill/SeckillOrderCreateListener.php
new file mode 100644
index 000000000..0267e2e0b
--- /dev/null
+++ b/niucloud/addon/shop/app/listener/seckill/SeckillOrderCreateListener.php
@@ -0,0 +1,30 @@
+checkGoods($params);
+ }
+ }
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/app/listener/seckill/SeckillOrderPushListener.php b/niucloud/addon/shop/app/listener/seckill/SeckillOrderPushListener.php
new file mode 100644
index 000000000..e25d9d734
--- /dev/null
+++ b/niucloud/addon/shop/app/listener/seckill/SeckillOrderPushListener.php
@@ -0,0 +1,59 @@
+$params['order_from'] ?? '',
+ 'member_id'=>$params['member_id'],
+ 'extend_data'=>[
+ 'relate_id'=>$params['seckill_id'],
+ 'relate_order_id'=>$params['id'],
+ 'relate_source'=>'seckill'
+ ],
+ 'delivery'=>[
+ 'delivery_type'=>'express',
+ ],
+ 'take_address'=>[
+ 'taker_name' => $params[ 'taker_name' ],
+ 'taker_mobile' => $params[ 'taker_mobile' ],
+ 'taker_province' => $params[ 'taker_province' ],
+ 'taker_city' => $params[ 'taker_city' ],
+ 'taker_district' => $params[ 'taker_district' ],
+ 'taker_address' => $params[ 'taker_address' ],
+ 'taker_full_address' => $params[ 'taker_full_address' ],
+ 'taker_longitude' => $params[ 'taker_longitude' ] ?? '',
+ 'taker_latitude' => $params[ 'taker_latitude' ] ?? '',
+ ],
+ 'sku_data'=>[
+ [
+ 'sku_id'=>$params['source_sku_id'],
+ 'num'=>$params['num'],
+ 'seckill_price'=>$params['goods_price']
+ ]
+ ],
+ 'pay'=>$params['pay']
+ ];
+ return $order_model->create($data);
+ }
+ }catch (\Exception $e){
+ Log::write("订单创建出错".$e->getMessage().'行号:'.$e->getLine());
+ return false;
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/app/listener/seckill/SeckillSupportAddonListener.php b/niucloud/addon/shop/app/listener/seckill/SeckillSupportAddonListener.php
new file mode 100644
index 000000000..47a016b23
--- /dev/null
+++ b/niucloud/addon/shop/app/listener/seckill/SeckillSupportAddonListener.php
@@ -0,0 +1,30 @@
+ 'shop',
+ 'name' => '商城'
+ ],
+ ];
+ }
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/app/listener/seckill/SeckillSupportGoodsInfoListener.php b/niucloud/addon/shop/app/listener/seckill/SeckillSupportGoodsInfoListener.php
new file mode 100644
index 000000000..141cb0d80
--- /dev/null
+++ b/niucloud/addon/shop/app/listener/seckill/SeckillSupportGoodsInfoListener.php
@@ -0,0 +1,30 @@
+getOfferGoodsInfo($params);
+ }
+ }
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/app/listener/seckill/SeckillSupportGoodsListener.php b/niucloud/addon/shop/app/listener/seckill/SeckillSupportGoodsListener.php
new file mode 100644
index 000000000..c72e4c9ad
--- /dev/null
+++ b/niucloud/addon/shop/app/listener/seckill/SeckillSupportGoodsListener.php
@@ -0,0 +1,32 @@
+getOfferGoodsList($params);
+ }
+ }
+
+
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/app/listener/sow_community/RuleContentListener.php b/niucloud/addon/shop/app/listener/sow_community/RuleContentListener.php
new file mode 100644
index 000000000..f3bc6f51e
--- /dev/null
+++ b/niucloud/addon/shop/app/listener/sow_community/RuleContentListener.php
@@ -0,0 +1,34 @@
+ $v) {
+ $data[ 'detail' ][] = $v[ 'num' ] . '张 ' . $v[ 'title' ];
+ }
+ }
+ return $data;
+ }
+}
diff --git a/niucloud/addon/shop/app/listener/sow_community/SettleRewardListener.php b/niucloud/addon/shop/app/listener/sow_community/SettleRewardListener.php
new file mode 100644
index 000000000..b123d7105
--- /dev/null
+++ b/niucloud/addon/shop/app/listener/sow_community/SettleRewardListener.php
@@ -0,0 +1,38 @@
+sendCoupon($member_id, $value[ 'coupon_id' ], $value[ 'num' ]);
+ } catch (CommonException $e) {
+ Log::write('种草赠送优惠券“' . $value[ 'coupon_id' ] . '”发放失败,错误原因:' . $e->getMessage() . $e->getFile() . $e->getLine());
+ }
+ }
+ }
+}
diff --git a/niucloud/addon/shop/app/listener/stat/StatExecuteListener.php b/niucloud/addon/shop/app/listener/stat/StatExecuteListener.php
new file mode 100644
index 000000000..17dd94111
--- /dev/null
+++ b/niucloud/addon/shop/app/listener/stat/StatExecuteListener.php
@@ -0,0 +1,24 @@
+ [
+ 'name' => '商城订单',
+ ],
+ 'shopRechargeOrder' => [
+ 'name' => '商城会员充值',
+ ],
+ ];
+ }
+}
diff --git a/niucloud/addon/shop/app/listener/system/ShowCustomerListener.php b/niucloud/addon/shop/app/listener/system/ShowCustomerListener.php
new file mode 100644
index 000000000..c4abbffe4
--- /dev/null
+++ b/niucloud/addon/shop/app/listener/system/ShowCustomerListener.php
@@ -0,0 +1,87 @@
+ [
+
+ ],
+ // 营销工具
+ MenuDict::ADDON_CHILD_MENU_DICT_MARKING_TOOL => [
+ [
+ 'title' => '商品榜单',
+ 'desc' => '展示热销商品排行榜',
+ 'icon' => 'static/resource/images/marketing/goods_rank.png',
+ 'key' => 'shop_goods_rank',
+ 'url' => '/shop/marketing/goods_rank/config',
+ ],
+ ],
+ // 营销活动
+ MenuDict::ADDON_CHILD_MENU_DICT_MARKING_ACTIVE => [
+ [
+ 'title' => '优惠券',
+ 'desc' => '设置商家优惠券',
+ 'icon' => 'static/resource/images/marketing/coupon.png',
+ 'key' => 'shop_goods_coupon',
+ 'url' => '/shop/marketing/coupon/list',
+ ],
+ [
+ 'title' => '满减送',
+ 'desc' => '购满指定金额享受优惠',
+ 'icon' => 'static/resource/images/marketing/manjian.png',
+ 'key' => 'shop_goods_manjian',
+ 'url' => '/shop/marketing/manjian/list',
+ ],
+ [
+ 'title' => '限时折扣',
+ 'desc' => '商品限时促销打折',
+ 'icon' => 'static/resource/images/marketing/discount.png',
+ 'key' => 'shop_goods_discount',
+ 'url' => '/shop/marketing/discount/list',
+ ],
+ [
+ 'title' => '积分商城',
+ 'desc' => '客户积分兑换更多好物',
+ 'icon' => 'static/resource/images/marketing/exchange.png',
+ 'key' => 'shop_point_goods',
+ 'url' => '/shop/marketing/exchange/goods_list',
+ ],
+ [
+ 'title' => '新人专享',
+ 'desc' => '新人专属优惠活动',
+ 'icon' => 'static/resource/images/marketing/newcomer.png',
+ 'key' => 'shop_goods_newcomer_discount',
+ 'url' => '/shop/marketing/newcomer/config',
+ ],
+ ]
+ ];
+ }
+}
diff --git a/niucloud/addon/shop/app/listener/system/ShowMarketingListener.php b/niucloud/addon/shop/app/listener/system/ShowMarketingListener.php
new file mode 100644
index 000000000..a8bd23988
--- /dev/null
+++ b/niucloud/addon/shop/app/listener/system/ShowMarketingListener.php
@@ -0,0 +1,81 @@
+ [
+
+ ],
+ // 工具
+ 'tool' => [
+ [
+ 'title' => '商品榜单',
+ 'desc' => '展示热销商品排行榜',
+ 'icon' => 'static/resource/images/marketing/goods_rank.png',
+ 'key' => 'shop_goods_rank',
+ 'url' => '/shop/marketing/goods_rank/config',
+ ],
+ ],
+ // 营销
+ 'marketing' => [
+ [
+ 'title' => '优惠券',
+ 'desc' => '设置商家优惠券',
+ 'icon' => 'static/resource/images/marketing/coupon.png',
+ 'key' => 'shop_goods_coupon',
+ 'url' => '/shop/marketing/coupon/list',
+ ],
+ [
+ 'title' => '满减送',
+ 'desc' => '购满指定金额享受优惠',
+ 'icon' => 'static/resource/images/marketing/manjian.png',
+ 'key' => 'shop_goods_manjian',
+ 'url' => '/shop/marketing/manjian/list',
+ ],
+ [
+ 'title' => '限时折扣',
+ 'desc' => '商品限时促销打折',
+ 'icon' => 'static/resource/images/marketing/discount.png',
+ 'key' => 'shop_goods_discount',
+ 'url' => '/shop/marketing/discount/list',
+ ],
+ [
+ 'title' => '积分商城',
+ 'desc' => '客户积分兑换更多好物',
+ 'icon' => 'static/resource/images/marketing/exchange.png',
+ 'key' => 'shop_point_goods',
+ 'url' => '/shop/marketing/exchange/goods_list',
+ ],
+ [
+ 'title' => '新人专享',
+ 'desc' => '新人专属优惠活动',
+ 'icon' => 'static/resource/images/marketing/newcomer.png',
+ 'key' => 'shop_goods_newcomer_discount',
+ 'url' => '/shop/marketing/newcomer/config',
+ ],
+ ]
+ ];
+ }
+}
diff --git a/niucloud/addon/shop/app/listener/third_addon/SupportAddonListener.php b/niucloud/addon/shop/app/listener/third_addon/SupportAddonListener.php
new file mode 100644
index 000000000..7729063c1
--- /dev/null
+++ b/niucloud/addon/shop/app/listener/third_addon/SupportAddonListener.php
@@ -0,0 +1,35 @@
+ 'shop',
+ 'name' => '商城'
+ ];
+ $data = [
+ 'friend_help' => $shop_arr,
+ 'seckill' => $shop_arr,
+ 'pintuan' => $shop_arr,
+ 'relay' => $shop_arr
+ ];
+ return [$data[$source]] ?? [];
+ }
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/app/listener/third_addon/goods/GoodsOutPutDataInfoListener.php b/niucloud/addon/shop/app/listener/third_addon/goods/GoodsOutPutDataInfoListener.php
new file mode 100644
index 000000000..f85ce2776
--- /dev/null
+++ b/niucloud/addon/shop/app/listener/third_addon/goods/GoodsOutPutDataInfoListener.php
@@ -0,0 +1,21 @@
+getOfferGoodsInfo($params);
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/app/listener/third_addon/goods/GoodsOutPutDataListener.php b/niucloud/addon/shop/app/listener/third_addon/goods/GoodsOutPutDataListener.php
new file mode 100644
index 000000000..37eb2a5cf
--- /dev/null
+++ b/niucloud/addon/shop/app/listener/third_addon/goods/GoodsOutPutDataListener.php
@@ -0,0 +1,21 @@
+getOfferGoodsList($params);
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/app/listener/third_addon/goods/GoodsOutPutWhereInitListener.php b/niucloud/addon/shop/app/listener/third_addon/goods/GoodsOutPutWhereInitListener.php
new file mode 100644
index 000000000..d0f7811f9
--- /dev/null
+++ b/niucloud/addon/shop/app/listener/third_addon/goods/GoodsOutPutWhereInitListener.php
@@ -0,0 +1,21 @@
+getWhereInit();
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/app/listener/third_addon/order/BackUpThirdOrderListener.php b/niucloud/addon/shop/app/listener/third_addon/order/BackUpThirdOrderListener.php
new file mode 100644
index 000000000..316675a27
--- /dev/null
+++ b/niucloud/addon/shop/app/listener/third_addon/order/BackUpThirdOrderListener.php
@@ -0,0 +1,65 @@
+ $data['source_id'] ?? 0,
+ 'order_count' => isset($data['order_data']) ? count($data['order_data']) : 0
+ ]));
+
+ try {
+ $return = [];
+ switch ($source) {
+ case 'relay':
+ Log::write("SHOP-RELAYBackUpThirdOrder 开始处理接龙订单");
+ $return = (new CoreCreateOrderService())->relayCreateOrder($data);
+ Log::write("SHOP-RELAYBackUpThirdOrder 接龙订单处理完成");
+ break;
+ case 'pintuan':
+ Log::write("SHOP-PINTUANBackUpThirdOrder 开始处理拼团订单");
+ $return = (new CoreCreateOrderService())->pintuanCreateOrder($data);
+ Log::write("SHOP-PINTUANBackUpThirdOrder 拼团订单处理完成");
+ break;
+ case 'friend_help':
+ Log::write("SHOP-FRIEND_HELPBackUpThirdOrder 开始处理好友助力订单");
+ $return = (new CoreCreateOrderService())->friendHelpCreateOrder($data);
+ Log::write("SHOP-FRIEND_HELPBackUpThirdOrder 好友助力订单处理完成");
+ break;
+ case 'seckill':
+ $order_model = new CoreSeckillOrderCreateService();
+ return $order_model->create($data);
+ default:
+ Log::write("SHOP-PINTUANBackUpThirdOrder 未知订单来源: {$source}");
+ }
+
+ Log::write("SHOP-PINTUANBackUpThirdOrder 订单处理流程正常结束,来源: {$source}");
+ return $return;
+ } catch (\Exception $e) {
+ // 合并异常日志:包含消息和堆栈
+ Log::error("PINTUAN-BackUpThirdOrder 订单处理异常(来源: {$source}): {$e->getMessage()}\n堆栈: {$e->getTraceAsString()}");
+ throw $e;
+ }
+ }
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/app/listener/third_addon/order/OrderAmountServiceListener.php b/niucloud/addon/shop/app/listener/third_addon/order/OrderAmountServiceListener.php
new file mode 100644
index 000000000..dc6d556d9
--- /dev/null
+++ b/niucloud/addon/shop/app/listener/third_addon/order/OrderAmountServiceListener.php
@@ -0,0 +1,73 @@
+ '配送费',
+// 'key' => 'delivery_money',
+// 'amount' => 20
+// ],
+// [
+// 'name' => '服务费',
+// 'key' => 'service_money',
+// 'amount' => 10
+// ]
+// ];
+ $this->getDeliveryMoney($data);
+ if (!empty($this->return)) {
+ return $this->return;
+ }
+ }
+ } catch (CommonException $e) {
+ throw new CommonException($e->getMessage());
+ }
+ }
+
+ private function getDeliveryMoney($data)
+ {
+ //必要参数,不传地址将获取用户默认地址
+ $data = [
+ 'member_id' => $data['member_id'],
+ 'province_id' => $data['address_info']['province_id'] ?? '',
+ 'city_id' => $data['address_info']['city_id'] ?? '',
+ 'district_id' => $data['address_info']['district_id'] ?? '',
+ 'source_sku_id' => $data['source_sku_id'],//商品skuID
+ 'num' => $data['num'], //购买数量
+ ];
+ $order_model = new CoreOrderDeliveryService();
+ //计算运费
+ $delivery_money = $order_model->calculate($data);
+ if ($delivery_money > 0) {
+ $this->return[] = [
+ 'name' => '配送费',
+ 'key' => 'delivery_money',
+ 'amount' => $delivery_money
+ ];
+ }
+ }
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/app/listener/third_addon/order/OrderDeliveryServiceListener.php b/niucloud/addon/shop/app/listener/third_addon/order/OrderDeliveryServiceListener.php
new file mode 100644
index 000000000..e70ee04f1
--- /dev/null
+++ b/niucloud/addon/shop/app/listener/third_addon/order/OrderDeliveryServiceListener.php
@@ -0,0 +1,57 @@
+ 0,
+ 'msg' => '商品参数不完整'
+ ];
+ }
+ if(empty($data['member_id'])){
+ return [
+ 'code' => 0,
+ 'msg' => '会员ID为空'
+ ];
+ }
+ //必要参数,不传地址将获取用户默认地址
+ $data = [
+ 'member_id'=>$data['member_id'],
+ 'province_id'=>$data['province_id'] ?? '',
+ 'city_id' => $data['city_id'] ?? '',
+ 'district_id'=>$data['district_id'] ?? '',
+ 'source_sku_id'=>$data['source_sku_id'],//商品skuID
+ 'num'=>$data['num'] //购买数量
+ ];
+ $order_model = new CoreOrderDeliveryService();
+ //计算运费
+ $delivery_money = $order_model->calculate($data);
+ return [
+ 'code' => 1,
+ 'delivery_money'=>$delivery_money
+ ];
+ }
+ return [];
+ }
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/app/listener/third_addon/order/OrderServicePathListener.php b/niucloud/addon/shop/app/listener/third_addon/order/OrderServicePathListener.php
new file mode 100644
index 000000000..c82cdd979
--- /dev/null
+++ b/niucloud/addon/shop/app/listener/third_addon/order/OrderServicePathListener.php
@@ -0,0 +1,68 @@
+whereNotIn('status', [OrderRefundDict::CLOSE, OrderRefundDict::SHOP_ACTIVE_CLOSE_REFUND])->where('order_id', $order_id)->findOrEmpty();
+ if ($refund_info->isEmpty()) {
+ $refund_path = sprintf($this->refund_apply_path, $order_goods_id, $order_id);
+ } else {
+ $refund_path = sprintf($this->refund_detail_path, $refund_info['order_refund_no']);
+ }
+ $order_info = (new Order())->findOrEmpty($order_id)->toArray();
+ if ($order_info['is_enable_refund'] == 0){//特殊处理 商城的订单已完成就不允许售后了(配置项),拼团是允许的则 商城不允许退款之后就直接返回空地址,这样拼团就不展示售后按钮了
+ $refund_path = '';
+ }
+
+ $detail_path = sprintf($this->detail_path, $order_id);
+ $admin_detail_path = sprintf($this->admin_detail_path, $order_id);
+ return [
+ 'refund' => ['name' => '商城-退款相关地址', 'url' => $refund_path],
+ 'detail' => ['name' => '查看关联订单', 'url' => $detail_path],
+ 'admin_detail' => ['name' => '查看关联订单', 'url' => $admin_detail_path],
+ ];
+ }
+ }
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/app/listener/treasure/TreasureDataListener.php b/niucloud/addon/shop/app/listener/treasure/TreasureDataListener.php
new file mode 100644
index 000000000..88757076e
--- /dev/null
+++ b/niucloud/addon/shop/app/listener/treasure/TreasureDataListener.php
@@ -0,0 +1,83 @@
+field($field)
+ ->withJoin([
+ 'goodsSku' => [ 'goods_id', 'sku_name', 'price' ]
+ ])->where($sku_where)->order($order)->append([ 'goods_cover_thumb_mid' ]);
+ $treasure_list = [];
+ if (!empty($params[ 'page' ])) {
+ $list = $search_model->paginate([
+ 'list_rows' => $params[ 'page' ][ 'limit' ],
+ 'page' => $params[ 'page' ][ 'page' ],
+ ])->toArray();
+ if (!empty($list[ 'data' ])) {
+ $data = [];
+ foreach ($list[ 'data' ] as $k => $v) {
+ $data[ $k ][ 'treasure_name' ] = $v[ 'goods_name' ]; // 宝贝名称
+ $data[ $k ][ 'treasure_sub_name' ] = $v[ 'sub_title' ]; // 宝贝副标题
+ $data[ $k ][ 'treasure_image' ] = empty($v[ 'goods_cover_thumb_mid' ]) ? $v[ 'goods_cover' ] : $v[ 'goods_cover_thumb_mid' ]; // 宝贝图片
+ $data[ $k ][ 'treasure_price' ] = $v[ 'goodsSku' ][ 'price' ]; // 宝贝价格
+ $data[ $k ][ 'treasure_url' ] = '/addon/shop/pages/goods/detail?goods_id=' . $v[ 'goods_id' ]; // 宝贝跳转链接
+ $data[ $k ][ 'relate_id' ] = $v[ 'goods_id' ]; // 关联业务id
+ $data[ $k ][ 'relate_type' ] = 'shop'; // 关联业务类型
+ }
+ $list[ 'data' ] = $data;
+ }
+ $treasure_list = $list;
+ } else {
+ $list = $search_model->select()->toArray();
+ foreach ($list as $k => $v) {
+ $treasure_list[ $k ][ 'treasure_name' ] = $v[ 'goods_name' ]; // 宝贝名称
+ $treasure_list[ $k ][ 'treasure_sub_name' ] = $v[ 'sub_title' ]; // 宝贝副标题
+ $treasure_list[ $k ][ 'treasure_image' ] = empty($v[ 'goods_cover_thumb_mid' ]) ? $v[ 'goods_cover' ] : $v[ 'goods_cover_thumb_mid' ]; // 宝贝图片
+ $treasure_list[ $k ][ 'treasure_price' ] = $v[ 'goodsSku' ][ 'price' ]; // 宝贝价格
+ $treasure_list[ $k ][ 'treasure_url' ] = '/addon/shop/pages/goods/detail?goods_id=' . $v[ 'goods_id' ]; // 宝贝跳转链接
+ $treasure_list[ $k ][ 'relate_id' ] = $v[ 'goods_id' ]; // 关联业务id
+ $treasure_list[ $k ][ 'relate_type' ] = 'shop'; // 关联业务类型
+ }
+ }
+ return $treasure_list;
+ }
+ }
+}
diff --git a/niucloud/addon/shop/app/listener/treasure/TreasureTypeListener.php b/niucloud/addon/shop/app/listener/treasure/TreasureTypeListener.php
new file mode 100644
index 000000000..2bac1b987
--- /dev/null
+++ b/niucloud/addon/shop/app/listener/treasure/TreasureTypeListener.php
@@ -0,0 +1,28 @@
+ '商品'
+ ];
+ }
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/app/listener/verify/VerifyCheckListener.php b/niucloud/addon/shop/app/listener/verify/VerifyCheckListener.php
new file mode 100644
index 000000000..0523e3a42
--- /dev/null
+++ b/niucloud/addon/shop/app/listener/verify/VerifyCheckListener.php
@@ -0,0 +1,88 @@
+where([['order_goods_id', '=', $order_goods_id]])->with([
+ 'goods' => function ($q) {
+ $q->field('goods_id,status');
+ }
+ ])->findOrEmpty()->toArray();
+ $un_use_msg = '';
+ if (in_array($order_goods_info['delivery_status'], [OrderDeliveryDict::TAKED, OrderDeliveryDict::EXPIRE])) {
+ $params['un_use_msg'][] = get_lang('SHOP_ORDER_ITEM_HAS_BEEN_WRITTEN_OFF_OR_EXPIRED');
+ $params['is_can_use'] = 0;
+ $un_use_msg = get_lang('SHOP_ORDER_ITEM_HAS_BEEN_WRITTEN_OFF_OR_EXPIRED');
+ } else if (in_array($order_goods_info['status'], [OrderGoodsDict::REFUNDING, OrderGoodsDict::REFUND_FINISH])) {
+ $params['un_use_msg'][] = get_lang('SHOP_THE_ITEM_IS_BEING_REFUNDED_OR_HAS_BEEN_REFUNDED');
+ $params['is_can_use'] = 0;
+ $un_use_msg = get_lang('SHOP_THE_ITEM_IS_BEING_REFUNDED_OR_HAS_BEEN_REFUNDED');
+ } else if ($order_goods_info['goods']['status'] != 1) {
+ $params['un_use_msg'][] = '商品已下架';
+ $params['is_can_use'] = 0;
+ $un_use_msg = '商品已下架';
+ }
+ $params['value']['list'][0]['un_use_msg'] = $un_use_msg;
+ return $params;
+ } else if ($params['type'] == 'shopPickUpOrder') {//自提订单
+ $order_id = $data['order_id'] ?? 0;
+ //todo 订单存在退款
+ $order_goods_list = (new OrderGoods())->where([['order_id', '=', $order_id]])->with([
+ 'goods' => function ($q) {
+ $q->field('goods_id,status,goods_name');
+ }
+ ])->select()->toArray();
+ $verify_list = $params['value']['list'];
+ foreach ($verify_list as &$value) {
+ $value['un_use_msg'] = '';
+ foreach ($order_goods_list as $order_goods_info) {
+ if ($value['order_goods_id'] == $order_goods_info['order_goods_id']) {
+ if (in_array($order_goods_info['status'], [OrderGoodsDict::REFUNDING, OrderGoodsDict::REFUND_FINISH])) {
+ $params['un_use_msg'][] = get_lang('SHOP_THE_ITEM_IS_BEING_REFUNDED_OR_HAS_BEEN_REFUNDED');
+ $params['is_can_use'] = 0;
+ $value['un_use_msg'] = get_lang('SHOP_THE_ITEM_IS_BEING_REFUNDED_OR_HAS_BEEN_REFUNDED');
+ continue;
+ }
+ if ($order_goods_info['goods']['status'] != 1) {
+ $params['un_use_msg'][] = $order_goods_info['goods']['goods_name'] . '已下架';
+ $params['is_can_use'] = 0;
+ $value['un_use_msg'] = '商品已下架';
+ }
+ }
+ }
+ }
+ $params['value']['list'] = $verify_list;
+ return $params;
+ }
+
+ }
+}
diff --git a/niucloud/addon/shop/app/listener/verify/VerifyCreateListener.php b/niucloud/addon/shop/app/listener/verify/VerifyCreateListener.php
new file mode 100644
index 000000000..06301f29b
--- /dev/null
+++ b/niucloud/addon/shop/app/listener/verify/VerifyCreateListener.php
@@ -0,0 +1,163 @@
+where([['order_goods_id', '=', $order_goods_id], ['member_id', '=', $member_id]])->findOrEmpty();
+ if ($order_goods_info->isEmpty()) throw new CommonException('SHOP_ORDER_NOT_FOUND');
+ if (in_array($order_goods_info[ 'delivery_status' ], [ OrderDeliveryDict::TAKED, OrderDeliveryDict::EXPIRE ])) throw new CommonException('SHOP_ORDER_ITEM_HAS_BEEN_WRITTEN_OFF_OR_EXPIRED');
+ //todo 判断订单项状态(已收货 已核销 核销已过期)
+ $order_info = ( new Order() )->where([ [ 'order_id', '=', $order_goods_info[ 'order_id' ] ], [ 'member_id', '=', $member_id ] ])->findOrEmpty();
+ if ($order_info->isEmpty()) throw new CommonException('SHOP_ORDER_NOT_FOUND');
+ if (in_array($order_info[ 'status' ], [ OrderDict::FINISH, OrderDict::CLOSE ])) throw new CommonException('SHOP_ORDER_HAS_BEEN_CLOSED_OR_COMPLETED');
+ $goods_id = $order_goods_info[ 'goods_id' ];
+ $goods_info = ( new Goods() )->findOrEmpty($goods_id);
+ if ($goods_info->isEmpty()) throw new CommonException('SHOP_GOODS_NOT_EXIST');
+ $virtual_receive_type = $goods_info[ 'virtual_receive_type' ];
+ if ($virtual_receive_type != 'verify') throw new CommonException('SHOP_GOODS_CURRENT_PRODUCT_DOES_NOT_SUPPORT_WRITE_OFF');
+
+ $count = $order_goods_info['num'] - $order_goods_info['verify_count'];
+ return [
+ 'count' => $count,
+ 'relate_tag' => $order_goods_id,
+ 'body' => $order_goods_info[ 'goods_name' ] . $order_goods_info[ 'sku_name' ],
+ 'expire_time' => empty($order_goods_info[ 'verify_expire_time' ]) ? 0 : strtotime($order_goods_info[ 'verify_expire_time' ]),
+ 'data' => [
+ 'list' => [
+ [
+ 'name' => $order_goods_info['goods_name'],
+ 'sub_name' => $order_goods_info['sku_name'],
+ 'cover' => $order_goods_info['goods_image'],
+ 'num' => $order_goods_info['num'],
+ 'verify_num' => 1,//虚拟核销商品单词核销一个
+ ]
+ ],
+ 'content' => [
+ 'fixed' => [
+
+ ],
+ 'diy' => [
+ [
+ 'title' => '订单信息',
+ 'list' => [
+ [
+ 'title' => '订单编号',
+ 'value' => $order_info[ 'order_no' ],
+ ],
+ [
+ 'title' => '支付时间',
+ 'value' => $order_info[ 'pay_time' ],
+ ],
+ ]
+ ],
+ ]
+ ]
+ ]
+ ];
+
+ } else if ($params[ 'type' ] == 'shopPickUpOrder') {//自提订单
+ $data = $params[ 'data' ] ?? [];
+ $member_id = $params[ 'member_id' ];
+ $order_id = $data[ 'order_id' ] ?? 0;
+ $list = [];
+ $order_info = (new Order())->where([['order_id', '=', $order_id], ['member_id', '=', $member_id]])->findOrEmpty();
+ if ($order_info->isEmpty()) throw new CommonException('SHOP_ORDER_NOT_FOUND');
+ //TODO:: 非自提订单 提示语待修正
+ if ($order_info[ 'delivery_type' ] != DeliveryDict::STORE) throw new CommonException('SHOP_ORDER_HAS_BEEN_CLOSED_OR_COMPLETED');
+
+ if (in_array($order_info[ 'status' ], [ OrderDict::FINISH, OrderDict::CLOSE ])) throw new CommonException('SHOP_ORDER_HAS_BEEN_CLOSED_OR_COMPLETED');
+
+ $order_goods_list = (new OrderGoods())->where([['order_id', '=', $order_id], ['member_id', '=', $member_id]])->select()->toArray();
+ $expire_time = 0;
+ $body = [];
+ foreach ($order_goods_list as $order_goods_info) {
+ //todo 判断订单项状态(已收货 已核销 核销已过期)
+ if (in_array($order_goods_info[ 'delivery_status' ], [ OrderDeliveryDict::TAKED, OrderDeliveryDict::EXPIRE ])) {
+ continue;
+ }
+ $list[] = [
+ 'order_goods_id' => $order_goods_info['order_goods_id'],
+ 'name' => $order_goods_info['goods_name'],
+ 'sub_name' => $order_goods_info['sku_name'],
+ 'cover' => $order_goods_info['goods_image'],
+ 'num' => $order_goods_info['num'],
+ 'verify_num'=>$order_goods_info['num']//自提订单统一进行核销
+ ];
+
+ $temp_expire_time = empty($order_goods_info[ 'verify_expire_time' ]) ? 0 : strtotime($order_goods_info[ 'verify_expire_time' ]);
+ if ($temp_expire_time > $expire_time) {
+ $expire_time = $temp_expire_time;
+ }
+ $body[] = $order_goods_info[ 'goods_name' ] . $order_goods_info[ 'sku_name' ];
+ }
+
+ return [
+ 'count' => 1,
+ 'relate_tag' => $order_id,
+ 'body' => mb_substr(implode(',', $body), 0, 100),
+ 'expire_time' => $expire_time,
+ 'data' => [
+ 'list' => $list,
+ 'taker_info' => [
+ 'taker_name' => $order_info[ 'taker_name' ] ?? "",//自提人姓名
+ 'taker_mobile' => $order_info[ 'taker_mobile' ] ?? "",//自提人手机号
+ 'buyer_ask_delivery_time' => $order_info[ 'buyer_ask_delivery_time' ] ?? "",//自提人期望的时间
+ ],
+ 'content' => [
+ 'fixed' => [
+
+ ],
+ 'diy' => [
+ [
+ 'title' => '订单信息',
+ 'list' => [
+ [
+ 'title' => '订单编号',
+ 'value' => $order_info[ 'order_no' ],
+ ],
+ [
+ 'title' => '支付时间',
+ 'value' => $order_info[ 'pay_time' ],
+ ],
+ ]
+ ],
+ ]
+ ]
+ ]
+ ];
+ }
+
+ }
+}
diff --git a/niucloud/addon/shop/app/listener/verify/VerifyInfoListener.php b/niucloud/addon/shop/app/listener/verify/VerifyInfoListener.php
new file mode 100644
index 000000000..a16b64c68
--- /dev/null
+++ b/niucloud/addon/shop/app/listener/verify/VerifyInfoListener.php
@@ -0,0 +1,51 @@
+where([ [ 'order_goods_id', '=', $order_goods_id ], [ 'is_verify', '=', 1 ] ])->findOrEmpty()->toArray();
+ if ($order_goods_info) {
+ $info = [
+ [
+ 'name' => '核销次数/总次数',
+ 'value' => $order_goods_info[ 'verify_count' ] . '/' . $order_goods_info[ 'num' ]
+ ]
+ ];
+ }
+ } else if ($params[ 'type' ] == 'shopPickUpOrder') {
+ // todo 自提订单核销 后续做了拆分处理再添加逻辑
+ $info = [
+ [
+ 'name' => '核销次数/总次数',
+ 'value' => '1/1'
+ ]
+ ];
+ }
+ return $info;
+ }
+}
diff --git a/niucloud/addon/shop/app/listener/verify/VerifyListener.php b/niucloud/addon/shop/app/listener/verify/VerifyListener.php
new file mode 100644
index 000000000..ce2ab48ee
--- /dev/null
+++ b/niucloud/addon/shop/app/listener/verify/VerifyListener.php
@@ -0,0 +1,86 @@
+where([[ 'order_goods_id', '=', $order_goods_id ] ])->findOrEmpty();
+ if ($order_goods_info->isEmpty()) throw new CommonException('SHOP_ORDER_NOT_FOUND');
+
+ if (in_array($order_goods_info[ 'delivery_status' ], [ OrderDeliveryDict::TAKED, OrderDeliveryDict::EXPIRE ])) throw new CommonException('SHOP_ORDER_ITEM_HAS_BEEN_WRITTEN_OFF_OR_EXPIRED');
+ if (in_array($order_goods_info[ 'status' ], [ OrderGoodsDict::REFUNDING, OrderGoodsDict::REFUND_FINISH ])) throw new CommonException('SHOP_THE_ITEM_IS_BEING_REFUNDED_OR_HAS_BEEN_REFUNDED');
+ if (strtotime($order_goods_info[ 'verify_expire_time' ]) > 0 && strtotime($order_goods_info[ 'verify_expire_time' ]) < time()) throw new CommonException('SHOP_ORDER_ITEM_HAS_EXPIRED');
+ if ($order_goods_info[ 'verify_count' ] >= $order_goods_info[ 'num' ]) throw new CommonException('SHOP_ORDER_MAXIMUM_NUMBER_OF_WRITE_OFFS_HAS_BEEN_REACHED');
+
+ //todo 判断订单项状态(已收货 已核销 核销已过期)
+ $order_info = ( new Order() )->where([ [ 'order_id', '=', $order_goods_info[ 'order_id' ] ] ])->findOrEmpty();
+ if ($order_info->isEmpty()) throw new CommonException('SHOP_ORDER_NOT_FOUND');
+ if (in_array($order_info[ 'status' ], [ OrderDict::FINISH, OrderDict::CLOSE ])) throw new CommonException('SHOP_ORDER_HAS_BEEN_CLOSED_OR_COMPLETED');
+ //核销次数累加1,达到最大核销次数后订单自动完成
+ $order_goods_info->save([
+ 'verify_count' => $order_goods_info[ 'verify_count' ] + 1,
+ ]);
+ //核销完成,顺便订单完成
+ if ($order_goods_info[ 'verify_count' ] >= $order_goods_info[ 'num' ]) {
+ ( new CoreOrderFinishService() )->finish([
+ 'main_type' => OrderLogDict::SYSTEM,
+ 'main_id' => 0,
+ 'order_id' => $order_goods_info[ 'order_id' ],
+ ]);
+ }
+ //存库
+ } else if ($params[ 'type' ] == 'shopPickUpOrder') {
+ $param = $params[ 'data' ];//订单信息
+ $order_id = $param[ 'order_id' ];
+ $order_info = ( new Order() )->where([ [ 'order_id', '=', $order_id ] ])->findOrEmpty();
+ if ($order_info->isEmpty()) throw new CommonException('SHOP_ORDER_NOT_FOUND');
+ if (in_array($order_info[ 'status' ], [ OrderDict::FINISH, OrderDict::CLOSE ])) throw new CommonException('SHOP_ORDER_HAS_BEEN_CLOSED_OR_COMPLETED');
+ $order_goods_list = ( new OrderGoods() )->where([
+ [ 'order_id', '=', $order_id ],
+ ])->select()->toArray();
+ foreach ($order_goods_list as $order_goods_info) {
+ if (in_array($order_goods_info[ 'delivery_status' ], [ OrderDeliveryDict::TAKED, OrderDeliveryDict::EXPIRE ])) throw new CommonException('SHOP_ORDER_ITEM_HAS_BEEN_WRITTEN_OFF_OR_EXPIRED');
+ if (in_array($order_goods_info[ 'status' ], [ OrderGoodsDict::REFUNDING, OrderGoodsDict::REFUND_FINISH ])) throw new CommonException('SHOP_THE_ITEM_IS_BEING_REFUNDED_OR_HAS_BEEN_REFUNDED');
+ }
+ //暂时自提订单核销为统一核销 故校验完数据后直接结束该自提订单
+ ( new CoreOrderFinishService() )->finish([
+ 'main_type' => OrderLogDict::SYSTEM,
+ 'main_id' => 0,
+ 'order_id' => $order_id,
+ ]);
+ }
+ return;
+ }
+}
diff --git a/niucloud/addon/shop/app/listener/verify/VerifyTypeListener.php b/niucloud/addon/shop/app/listener/verify/VerifyTypeListener.php
new file mode 100644
index 000000000..7f3d5a04b
--- /dev/null
+++ b/niucloud/addon/shop/app/listener/verify/VerifyTypeListener.php
@@ -0,0 +1,34 @@
+ [
+ 'name' => '商城虚拟商品'
+ ],
+ 'shopPickUpOrder' => [
+ 'name' => '商城自提订单'
+ ],
+ ];
+ }
+}
diff --git a/niucloud/addon/shop/app/model/ShopStat.php b/niucloud/addon/shop/app/model/ShopStat.php
new file mode 100644
index 000000000..c6d3374e5
--- /dev/null
+++ b/niucloud/addon/shop/app/model/ShopStat.php
@@ -0,0 +1,43 @@
+ 'timestamp',
+ ];
+
+}
diff --git a/niucloud/addon/shop/app/model/active/Active.php b/niucloud/addon/shop/app/model/active/Active.php
new file mode 100644
index 000000000..25fed41a0
--- /dev/null
+++ b/niucloud/addon/shop/app/model/active/Active.php
@@ -0,0 +1,172 @@
+ 'timestamp',
+ 'end_time' => 'timestamp',
+ 'create_time' => 'timestamp',
+ 'update_time' => 'timestamp',
+ ];
+
+ // 设置json类型字段
+ protected $json = [ 'active_goods_info', 'active_value'];
+
+ // 设置JSON数据返回数组
+ protected $jsonAssoc = true;
+
+ /**
+ * 活动商品项
+ * @return \think\model\relation\HasMany
+ */
+ public function activeGoods()
+ {
+ return $this->hasMany(ActiveGoods::class, 'active_id', 'active_id');
+ }
+
+ /**
+ * 活动状态
+ * @param $value
+ * @param $data
+ * @return mixed|string
+ */
+ public function getActiveStatusNameAttr($value, $data)
+ {
+ if (empty($data['active_status']))
+ {
+ return '';
+ }
+ return ActiveDict::getStatus()[$data['active_status']] ?? '';
+ }
+
+ /**
+ * 活动类型
+ * @param $value
+ * @param $data
+ * @return mixed|string
+ */
+ public function getActiveTypeNameAttr($value, $data)
+ {
+ if (empty($data['active_type']))
+ {
+ return '';
+ }
+ return ActiveDict::getType()[$data['active_type']] ?? '';
+ }
+
+ /**
+ * 活动商品类型
+ * @param $value
+ * @param $data
+ * @return mixed|string
+ */
+ public function getActiveGoodsTypeNameAttr($value, $data)
+ {
+ if (empty($data['active_goods_type']))
+ {
+ return '';
+ }
+ return ActiveDict::getGoodsType()[$data['active_goods_type']] ?? '';
+ }
+
+ /**
+ * 活动类别
+ * @param $value
+ * @param $data
+ * @return mixed|string
+ */
+ public function getActiveClassNameAttr($value, $data)
+ {
+ if (empty($data['active_class']))
+ {
+ return '';
+ }
+ return ActiveDict::getClass()[$data['active_class']] ?? '';
+ }
+
+ /**
+ * 搜索器:标题
+ * @param $value
+ * @param $data
+ */
+ public function searchActiveNameAttr($query, $value, $data)
+ {
+ if ($value != '') {
+ $query->where("active_name", 'like', '%' . $this->handelSpecialCharacter($value) . '%');
+ }
+ }
+
+ /**
+ * 搜索器:活动类型
+ * @param $value
+ * @param $data
+ */
+ public function searchActiveTypeAttr($query, $value, $data)
+ {
+ if ($value) {
+ $query->where("active_type", '=', $value);
+ }
+ }
+
+ /**
+ * 搜索器:状态
+ * @param $value
+ * @param $data
+ */
+ public function searchActiveStatusAttr($query, $value, $data)
+ {
+ if ($value) {
+ $query->where("active_status", '=', $value);
+ }
+ }
+
+ /**
+ * 活动结束时间搜索器
+ * @param Query $query
+ * @param $value
+ * @param $data
+ */
+ public function searchEndTimeAttr(Query $query, $value, $data)
+ {
+ $start_time = empty($value[0]) ? 0 : strtotime($value[0]);
+ $end_time = empty($value[1]) ? 0 : strtotime($value[1]);
+ if ($start_time > 0 && $end_time > 0) {
+ $query->whereBetweenTime('end_time', $start_time, $end_time);
+ } else if ($start_time > 0 && $end_time == 0) {
+ $query->where([['end_time', '>=', $start_time]]);
+ } else if ($start_time == 0 && $end_time > 0) {
+ $query->where([['end_time', '<=', $end_time]]);
+ }
+ }
+}
diff --git a/niucloud/addon/shop/app/model/active/ActiveGoods.php b/niucloud/addon/shop/app/model/active/ActiveGoods.php
new file mode 100644
index 000000000..69324d8bb
--- /dev/null
+++ b/niucloud/addon/shop/app/model/active/ActiveGoods.php
@@ -0,0 +1,92 @@
+hasOne(Goods::class, 'goods_id', 'goods_id');
+ }
+
+ /**
+ * 关联默认商品规格
+ * @return \think\model\relation\HasOne
+ */
+ public function goodsSku()
+ {
+ return $this->hasOne(GoodsSku::class, 'goods_id', 'goods_id');
+ }
+
+ /**
+ * 关联默认商品规格
+ * @return \think\model\relation\HasOne
+ */
+ public function goodsSkuOne()
+ {
+ return $this->hasOne(GoodsSku::class, 'sku_id', 'sku_id');
+ }
+
+ /**
+ * 优惠券商品项
+ * @return \think\model\relation\HasOne
+ */
+ public function active()
+ {
+ return $this->hasOne(Active::class, 'active_id', 'active_id');
+ }
+
+ /**
+ * 活动状态
+ * @param $value
+ * @param $data
+ * @return mixed|string
+ */
+ public function getActiveGoodsStatusNameAttr($value, $data)
+ {
+ if (empty($data['active_goods_status']))
+ {
+ return '';
+ }
+ return ActiveDict::getStatus()[$data['active_goods_status']] ?? '';
+ }
+}
diff --git a/niucloud/addon/shop/app/model/cart/Cart.php b/niucloud/addon/shop/app/model/cart/Cart.php
new file mode 100644
index 000000000..80bcf326a
--- /dev/null
+++ b/niucloud/addon/shop/app/model/cart/Cart.php
@@ -0,0 +1,184 @@
+where("id", $value);
+ }
+ }
+
+ /**
+ * 搜索器:购物车会员ID
+ * @param $value
+ * @param $data
+ */
+ public function searchMemberIdAttr($query, $value, $data)
+ {
+ if ($value) {
+ $query->where("member_id", $value);
+ }
+ }
+
+ /**
+ * 搜索器:购物车商品ID
+ * @param $value
+ * @param $data
+ */
+ public function searchGoodsIdAttr($query, $value, $data)
+ {
+ if ($value) {
+ $query->where("goods_id", $value);
+ }
+ }
+
+ /**
+ * 搜索器:购物车sku id
+ * @param $value
+ * @param $data
+ */
+ public function searchSkuIdAttr($query, $value, $data)
+ {
+ if ($value) {
+ $query->where("sku_id", $value);
+ }
+ }
+
+ /**
+ * 搜索器:购物车活动类型
+ * @param $value
+ * @param $data
+ */
+ public function searchMarketTypeAttr($query, $value, $data)
+ {
+ if ($value) {
+ $query->where("market_type", $value);
+ }
+ }
+
+ /**
+ * 搜索器:购物车活动id
+ * @param $value
+ * @param $data
+ */
+ public function searchMarketTypeIdAttr($query, $value, $data)
+ {
+ if ($value) {
+ $query->where("market_type_id", $value);
+ }
+ }
+
+ /**
+ * 搜索器:购物车添加时间
+ * @param $value
+ * @param $data
+ */
+ public function searchCreateTimeAttr($query, $value, $data)
+ {
+ if ($value) {
+ $query->where("create_time", $value);
+ }
+ }
+
+ /**
+ * 搜索器:购物车商品状态
+ * @param $value
+ * @param $data
+ */
+ public function searchStatusAttr($query, $value, $data)
+ {
+ if ($value) {
+ $query->where("status", $value);
+ }
+ }
+
+ /**
+ * 搜索器:购物车失效原因
+ * @param $value
+ * @param $data
+ */
+ public function searchInvalidRemarkAttr($query, $value, $data)
+ {
+ if ($value) {
+ $query->where("invalid_remark", $value);
+ }
+ }
+
+ /**
+ * 关联商品主表
+ * @return \think\model\relation\HasOne
+ */
+ public function goods()
+ {
+ return $this->hasOne(Goods::class, 'goods_id', 'goods_id')
+ ->joinType('inner')
+ ->withTrashed()
+ ->withField('goods_id, goods_name, goods_type, sub_title, goods_cover, unit, stock, sale_num + virtual_sale_num as sale_num, status,delete_time')
+ ->append([ 'goods_type_name', 'goods_cover_thumb_small', 'goods_cover_thumb_mid' ]);
+ }
+
+ /**
+ * 关联商品规格
+ * @return \think\model\relation\HasOne
+ */
+ public function goodsSku()
+ {
+ return $this->hasOne(GoodsSku::class, 'sku_id', 'sku_id')
+ ->joinType('inner')
+ ->withField('sku_id, sku_name, sku_image, sku_no, goods_id, sku_spec_format, price, market_price, sale_price, stock, weight, volume, is_default')
+ ->append([ 'sku_image_thumb_small', 'sku_image_thumb_mid', 'sku_image_thumb_big' ]);
+ }
+
+ /**
+ * 关联商品规格列表
+ * @return \think\model\relation\HasMany
+ */
+ public function goodsSpec()
+ {
+ return $this->hasMany(GoodsSpec::class, 'goods_id', 'goods_id');
+ }
+
+}
diff --git a/niucloud/addon/shop/app/model/coupon/Coupon.php b/niucloud/addon/shop/app/model/coupon/Coupon.php
new file mode 100644
index 000000000..534c40f07
--- /dev/null
+++ b/niucloud/addon/shop/app/model/coupon/Coupon.php
@@ -0,0 +1,207 @@
+ 'timestamp',
+ 'end_time' => 'timestamp',
+ 'valid_start_time' => 'timestamp',
+ 'valid_end_time' => 'timestamp',
+ ];
+ /**
+ * 优惠券商品项
+ * @return \think\model\relation\HasMany
+ */
+ public function goods()
+ {
+ return $this->hasMany(CouponGoods::class, 'coupon_id', 'id');
+ }
+
+ /**
+ * 关联商品项
+ * @param $value
+ * @param $data
+ * @return CouponGoods[]|array|\think\Collection
+ * @throws \think\db\exception\DataNotFoundException
+ * @throws \think\db\exception\DbException
+ * @throws \think\db\exception\ModelNotFoundException
+ */
+// public function getGoodsDataAttr($value, $data)
+// {
+// $coupon_id = $data['id'] ?? 0;
+// $list = [];
+// if($coupon_id > 0) {
+// $coupon_id = $data['id'];
+// $list = (new CouponGoods())->where([['coupon_id', '=', $coupon_id]])->select();
+// }
+// return $list;
+// }
+
+
+ public function getCouponPriceAttr($value, $data)
+ {
+ if (empty($data['price']))
+ {
+ return 0;
+ }
+ return rtrim(rtrim($data['price'], '0'), '.');
+
+ }
+
+ public function getCouponMinPriceAttr($value, $data)
+ {
+ if (empty($data['min_condition_money']))
+ {
+ return 0;
+ }
+ return rtrim(rtrim($data['min_condition_money'], '0'), '.');
+
+ }
+
+ /**
+ * 搜索器:标题
+ * @param $value
+ * @param $data
+ */
+ public function searchTitleAttr($query, $value, $data)
+ {
+ if ($value != '') {
+ $query->where("title", 'like', '%' . $this->handelSpecialCharacter($value) . '%');
+ }
+ }
+
+ /**
+ * 搜索器:状态
+ * @param $value
+ * @param $data
+ */
+ public function searchStatusAttr($query, $value, $data)
+ {
+ if ($value != '') {
+ $query->where("status",'=',$value);
+ }
+ }
+
+
+ /**
+ * 类型
+ * @param $value
+ * @param $data
+ * @return string
+ */
+ public function getTypeNameAttr($value, $data)
+ {
+ if (empty($data['type']))
+ return '';
+ return CouponDict::getType()[$data['type']] ?? '';
+ }
+
+ /**
+ * 领取类型
+ * @param $value
+ * @param $data
+ * @return string
+ */
+ public function getReceiveTypeNameAttr($value, $data)
+ {
+ if (empty($data['receive_type']))
+ return '';
+ return CouponDict::getReceiveType()[$data['receive_type']] ?? '';
+ }
+
+ /**
+ * 优惠券状态
+ * @param $value
+ * @param $data
+ * @return string
+ */
+ public function getStatusNameAttr($value, $data)
+ {
+ return CouponDict::getStatus()[$data['status']] ?? '';
+ }
+
+ /**
+ * 发券按钮是否展示
+ * @param $value
+ * @param $data
+ * @return string
+ */
+ public function getIsShowSendAttr($value, $data)
+ {
+ if($data['status'] != CouponDict::NORMAL){
+ return 0;
+ }
+ return 1;
+ }
+
+
+ /**
+ * 活动开始时间搜索器
+ * @param Query $query
+ * @param $value
+ * @param $data
+ */
+ public function searchStartTimeAttr(Query $query, $value, $data)
+ {
+ $start_time = empty($value[0]) ? 0 : strtotime($value[0]);
+ $end_time = empty($value[1]) ? 0 : strtotime($value[1]);
+ if ($start_time > 0 && $end_time > 0) {
+ $query->whereBetweenTime('start_time', $start_time, $end_time);
+ } else if ($start_time > 0 && $end_time == 0) {
+ $query->where([['start_time', '>=', $start_time]]);
+ } else if ($start_time == 0 && $end_time > 0) {
+ $query->where([['start_time', '<=', $end_time]]);
+ }
+ }
+
+ /**
+ * 活动结束时间搜索器
+ * @param Query $query
+ * @param $value
+ * @param $data
+ */
+ public function searchEndTimeAttr(Query $query, $value, $data)
+ {
+ $start_time = empty($value[0]) ? 0 : strtotime($value[0]);
+ $end_time = empty($value[1]) ? 0 : strtotime($value[1]);
+ if ($start_time > 0 && $end_time > 0) {
+ $query->whereBetweenTime('end_time', $start_time, $end_time);
+ } else if ($start_time > 0 && $end_time == 0) {
+ $query->where([['end_time', '>=', $start_time]]);
+ } else if ($start_time == 0 && $end_time > 0) {
+ $query->where([['end_time', '<=', $end_time]]);
+ }
+ }
+}
diff --git a/niucloud/addon/shop/app/model/coupon/CouponGoods.php b/niucloud/addon/shop/app/model/coupon/CouponGoods.php
new file mode 100644
index 000000000..ad6188929
--- /dev/null
+++ b/niucloud/addon/shop/app/model/coupon/CouponGoods.php
@@ -0,0 +1,41 @@
+hasOne(Goods::class , 'goods_id', 'goods_id');
+ }
+
+}
diff --git a/niucloud/addon/shop/app/model/coupon/CouponMember.php b/niucloud/addon/shop/app/model/coupon/CouponMember.php
new file mode 100644
index 000000000..0ff7fccd8
--- /dev/null
+++ b/niucloud/addon/shop/app/model/coupon/CouponMember.php
@@ -0,0 +1,121 @@
+ 'timestamp',
+ 'use_time' => 'timestamp',
+ ];
+
+ public function coupon()
+ {
+ return $this->hasOne(Coupon::class, 'id', 'coupon_id')->joinType('left')
+ ->withField('title, price, min_condition_money, type');
+ }
+
+ public function member()
+ {
+ return $this->hasOne(Member::class, 'member_id', 'member_id')->joinType('left')
+ ->withField('member_id,member_no, username, mobile, nickname');
+ }
+
+ /**
+ * 优惠券商品项
+ * @return \think\model\relation\HasMany
+ */
+ public function goods()
+ {
+ return $this->hasMany(CouponGoods::class, 'coupon_id', 'coupon_id');
+ }
+
+ public function getStatusNameAttr($value, $data)
+ {
+ if (empty($data[ 'status' ]))
+ return '';
+ $temp = CouponMemberDict::getStatus()[ $data[ 'status' ] ] ?? [];
+ return $temp ?? '';
+
+ }
+
+ public function getReceiveTypeNameAttr($value, $data)
+ {
+
+ if (empty($data[ 'receive_type' ]))
+ return '';
+ $receive_type = event('CouponReceiveType', []);
+ if (empty($receive_type)) {
+ return [];
+ }
+ foreach ($receive_type as &$value) {
+ foreach ($value as $v) {
+ $type[] = $v[ 'name' ];
+ $info[] = $v;
+ }
+ }
+
+ $key = array_search($data[ 'receive_type' ], $type);
+
+ $temp = $info[ $key ][ 'title' ] ?? [];
+ return $temp ?? '';
+
+ }
+
+ public function getCouponPriceAttr($value, $data)
+ {
+ if (empty($data[ 'price' ])) {
+ return 0;
+ }
+ return rtrim(rtrim($data[ 'price' ], '0'), '.');
+
+ }
+
+ public function getCouponMinPriceAttr($value, $data)
+ {
+ if (empty($data[ 'min_condition_money' ])) {
+ return 0;
+ }
+ return rtrim(rtrim($data[ 'min_condition_money' ], '0'), '.');
+
+ }
+
+ public function getTypeNameAttr($value, $data)
+ {
+ if (empty($data[ 'type' ]))
+ return '';
+ return CouponDict::getType()[ $data[ 'type' ] ] ?? '';
+ }
+}
diff --git a/niucloud/addon/shop/app/model/coupon/CouponSendRecord.php b/niucloud/addon/shop/app/model/coupon/CouponSendRecord.php
new file mode 100644
index 000000000..9c81f7bd9
--- /dev/null
+++ b/niucloud/addon/shop/app/model/coupon/CouponSendRecord.php
@@ -0,0 +1,122 @@
+ 'timestamp',
+ 'create_time' => 'timestamp',
+ 'update_time' => 'timestamp',
+ ];
+ protected $json = ['range_param'];
+
+ // 设置JSON数据返回数组
+ protected $jsonAssoc = true;
+
+ /**
+ * 关联优惠券
+ * @return \think\model\relation\HasOne
+ */
+ public function coupon()
+ {
+ return $this->hasOne(Coupon::class, 'id', 'coupon_id');
+ }
+
+ /**
+ * 获取范围名称
+ * @param $value
+ * @param $data
+ * @return array|mixed|string
+ */
+ public function getRangeTypeNameAttr($value, $data)
+ {
+ if (empty($data[ 'range_type' ]))
+ return '';
+ return CouponDict::getSendCouponRangeTypeDesc($data[ 'range_type' ]) ?? '';
+ }
+
+ /**
+ * 获取状态
+ * @param $value
+ * @param $data
+ * @return array|mixed|string
+ */
+ public function getStatusNameAttr($value, $data)
+ {
+ if (empty($data['status']))
+ return '';
+ return CouponDict::getSendCouponStatus($data['status']) ?? '';
+ }
+
+ /**
+ * 获取参数值
+ * @param $value
+ * @param $data
+ * @return array|string
+ */
+ public function getRangeParamValueAttr($value, $data)
+ {
+ if (empty($data['range_type']))
+ return '';
+ if ($data['range_type'] == CouponDict::SEND_RANGE_MEMBER_LEVEL){
+ return $data['range_param']['level_name'] ??"";
+ }
+ if ($data['range_type'] == CouponDict::SEND_RANGE_MEMBER_LABEL){
+ return $data['range_param']['label_name'] ??"";
+ }
+ if ($data['range_type'] == CouponDict::SEND_RANGE_MEMBER){
+ return $data['range_param']['member_ids'] ?? [];
+ }
+ return '全体会员';
+ }
+
+ /**
+ * 创建时间搜索器
+ * @param $query
+ * @param $value
+ * @param $data
+ */
+ public function searchCreateTimeAttr($query, $value, $data)
+ {
+ $start_time = empty($value[ 0 ]) ? 0 : strtotime($value[ 0 ]);
+ $end_time = empty($value[ 1 ]) ? 0 : strtotime($value[ 1 ]);
+ if ($start_time > 0 && $end_time > 0) {
+ $query->whereBetweenTime('create_time', $start_time, $end_time);
+ } else if ($start_time > 0 && $end_time == 0) {
+ $query->where([ [ 'create_time', '>=', $start_time ] ]);
+ } else if ($start_time == 0 && $end_time > 0) {
+ $query->where([ [ 'create_time', '<=', $end_time ] ]);
+ }
+ }
+}
diff --git a/niucloud/addon/shop/app/model/delivery/Company.php b/niucloud/addon/shop/app/model/delivery/Company.php
new file mode 100644
index 000000000..eff961e43
--- /dev/null
+++ b/niucloud/addon/shop/app/model/delivery/Company.php
@@ -0,0 +1,79 @@
+where("company_id", $value);
+ }
+ }
+
+ /**
+ * 搜索器:物流公司名称
+ * @param $value
+ * @param $data
+ */
+ public function searchCompanyNameAttr($query, $value, $data)
+ {
+ if ($value != '') {
+ $query->where("company_name", 'like', '%' . $value . '%');
+ }
+ }
+
+ /**
+ * 搜索器:是否支持电子面单(0:不支持,1:支持)
+ * @param $value
+ * @param $data
+ */
+ public function searchElectronicSheetSwitchAttr($query, $value, $data)
+ {
+ if ($value !== '') {
+ $query->where("electronic_sheet_switch", $value);
+ }
+ }
+
+}
diff --git a/niucloud/addon/shop/app/model/delivery/Deliver.php b/niucloud/addon/shop/app/model/delivery/Deliver.php
new file mode 100644
index 000000000..72e990f31
--- /dev/null
+++ b/niucloud/addon/shop/app/model/delivery/Deliver.php
@@ -0,0 +1,63 @@
+where("deliver_name", 'like', '%' . $value . '%');
+ }
+ }
+
+ /**
+ * 搜索器:配送员手机号
+ * @param $value
+ * @param $data
+ */
+ public function searchDeliverMobileAttr($query, $value)
+ {
+ if ($value != '') {
+ $query->where("deliver_mobile", 'like', '%' . $value . '%');
+
+ }
+ }
+}
diff --git a/niucloud/addon/shop/app/model/delivery/ElectronicSheet.php b/niucloud/addon/shop/app/model/delivery/ElectronicSheet.php
new file mode 100644
index 000000000..71655b2ef
--- /dev/null
+++ b/niucloud/addon/shop/app/model/delivery/ElectronicSheet.php
@@ -0,0 +1,135 @@
+hasOne(Company::class, 'company_id', 'express_company_id');
+ }
+
+ /**
+ * 搜索器:电子面单
+ * @param $value
+ * @param $data
+ */
+ public function searchIdAttr($query, $value, $data)
+ {
+ if ($value) {
+ $query->where("id", $value);
+ }
+ }
+
+ /**
+ * 搜索器:电子面单模板名称
+ * @param $value
+ * @param $data
+ */
+ public function searchTemplateNameAttr($query, $value, $data)
+ {
+ if ($value != '') {
+ $query->where("template_name", 'like', '%' . $this->handelSpecialCharacter($value) . '%');
+ }
+ }
+
+ /**
+ * 搜索器:电子面单物流公司id
+ * @param $value
+ * @param $data
+ */
+ public function searchExpressCompanyIdAttr($query, $value, $data)
+ {
+ if ($value) {
+ $query->where("express_company_id", $value);
+ }
+ }
+
+ /**
+ * 搜索器:电子面单快递员上门揽件(0:否,1:是)
+ * @param $value
+ * @param $data
+ */
+ public function searchIsNoticeAttr($query, $value, $data)
+ {
+ if ($value) {
+ $query->where("is_notice", $value);
+ }
+ }
+
+ /**
+ * 搜索器:电子面单状态(1:开启,0:关闭)
+ * @param $value
+ * @param $data
+ */
+ public function searchStatusAttr($query, $value, $data)
+ {
+ if ($value !== '') {
+ $query->where("status", $value);
+ }
+ }
+
+ public function getKdbirdConfigAttr($value, $data)
+ {
+ if(!empty($data['interface_data'])){
+ $interface_data = json_decode($data['interface_data'], true);
+ return is_array($interface_data) && $interface_data['kdbird'] ? $interface_data['kdbird'] : [];
+ }
+ }
+
+ public function getKd100ConfigAttr($value, $data)
+ {
+ if(!empty($data['interface_data'])){
+ $interface_data = json_decode($data['interface_data'], true);
+ return is_array($interface_data) && $interface_data['kd100'] ? $interface_data['kd100'] : [];
+ }
+ }
+
+
+
+}
diff --git a/niucloud/addon/shop/app/model/delivery/Local.php b/niucloud/addon/shop/app/model/delivery/Local.php
new file mode 100644
index 000000000..bd1eecfa4
--- /dev/null
+++ b/niucloud/addon/shop/app/model/delivery/Local.php
@@ -0,0 +1,42 @@
+ 'json',
+ 'area' => 'json',
+ 'delivery_type' => 'json',
+ 'delivery_time' => 'json'
+ ];
+}
diff --git a/niucloud/addon/shop/app/model/delivery/ShippingTemplate.php b/niucloud/addon/shop/app/model/delivery/ShippingTemplate.php
new file mode 100644
index 000000000..8bc4d7e38
--- /dev/null
+++ b/niucloud/addon/shop/app/model/delivery/ShippingTemplate.php
@@ -0,0 +1,53 @@
+where([ [ 'template_name', 'like', "%$value%" ] ]);
+ }
+ }
+
+ /**
+ * 获取计费类型
+ * @param $value
+ * @param $data
+ * @return array|mixed|string
+ */
+ public function getFeeTypeNameAttr($value, $data)
+ {
+ if (isset($data[ 'fee_type' ])) return ShippingTemplateDict::getFeeType($data[ 'fee_type' ]);
+ }
+}
diff --git a/niucloud/addon/shop/app/model/delivery/ShippingTemplateItem.php b/niucloud/addon/shop/app/model/delivery/ShippingTemplateItem.php
new file mode 100644
index 000000000..a66849fa2
--- /dev/null
+++ b/niucloud/addon/shop/app/model/delivery/ShippingTemplateItem.php
@@ -0,0 +1,46 @@
+ 'float',
+ 'xprice' => 'float'
+ ];
+
+ /**
+ * 模型名称
+ * @var string
+ */
+ protected $name = 'shop_delivery_shipping_template_item';
+
+ public function getAreaIdsAttr($value, $data)
+ {
+ return explode(',', $value);
+ }
+}
diff --git a/niucloud/addon/shop/app/model/delivery/Store.php b/niucloud/addon/shop/app/model/delivery/Store.php
new file mode 100644
index 000000000..ad97cc581
--- /dev/null
+++ b/niucloud/addon/shop/app/model/delivery/Store.php
@@ -0,0 +1,72 @@
+ 'timestamp',
+ 'update_time' => 'timestamp',
+ ];
+ protected $json = ['time_week','trade_time_json'];
+ protected $jsonAssoc = true;
+
+ /**
+ * 搜索器:自提门店门店名称
+ * @param $value
+ * @param $data
+ */
+ public function searchStoreNameAttr($query, $value, $data)
+ {
+ if ($value != '') {
+ $query->where("store_name", "like", "%" . $value . "%");
+ }
+ }
+
+ /**
+ * 创建时间搜索器
+ * @param $value
+ */
+ public function searchCreateTimeAttr(Query $query, $value, $data)
+ {
+ $start_time = empty($value[ 0 ]) ? 0 : strtotime($value[ 0 ]);
+ $end_time = empty($value[ 1 ]) ? 0 : strtotime($value[ 1 ]);
+ if ($start_time > 0 && $end_time > 0) {
+ $query->whereBetweenTime('create_time', $start_time, $end_time);
+ } else if ($start_time > 0 && $end_time == 0) {
+ $query->where([ [ 'create_time', '>=', $start_time ] ]);
+ } else if ($start_time == 0 && $end_time > 0) {
+ $query->where([ [ 'create_time', '<=', $end_time ] ]);
+ }
+ }
+}
diff --git a/niucloud/addon/shop/app/model/discount/Discount.php b/niucloud/addon/shop/app/model/discount/Discount.php
new file mode 100644
index 000000000..0252370c0
--- /dev/null
+++ b/niucloud/addon/shop/app/model/discount/Discount.php
@@ -0,0 +1,103 @@
+ 'timestamp',
+ 'end_time' => 'timestamp',
+ 'create_time' => 'timestamp',
+ 'update_time' => 'timestamp',
+ ];
+
+
+ /**
+ * 活动商品项
+ * @return \think\model\relation\HasMany
+ */
+ public function activeGoods()
+ {
+ return $this->hasMany(DiscountGoods::class, 'discount_id', 'discount_id');
+ }
+
+ /**
+ * 状态
+ * @param $value
+ * @param $data
+ * @return mixed|string
+ */
+ public function getStatusNameAttr($value, $data)
+ {
+ if (empty($data['status']))
+ {
+ return '';
+ }
+ return DiscountDict::getStatus()[$data['status']] ?? '';
+ }
+
+ /**
+ * 搜索器:标题
+ * @param $value
+ * @param $data
+ */
+ public function searchNameAttr($query, $value, $data)
+ {
+ if ($value != '') {
+ $query->where("name", 'like', '%' . $this->handelSpecialCharacter($value) . '%');
+ }
+ }
+ /**
+ * 搜索器:状态
+ * @param $value
+ * @param $data
+ */
+ public function searchStatusAttr($query, $value, $data)
+ {
+ if ($value) {
+ $query->where("status", '=', $value);
+ }
+ }
+
+ /**
+ * 搜索器:id
+ * @param $value
+ * @param $data
+ */
+ public function searchActiveIdAttr($query, $value, $data)
+ {
+ if (!empty($value)) {
+ $query->where("discount_id", 'in', $value);
+ }
+ }
+}
diff --git a/niucloud/addon/shop/app/model/discount/DiscountGoods.php b/niucloud/addon/shop/app/model/discount/DiscountGoods.php
new file mode 100644
index 000000000..7426fbd5e
--- /dev/null
+++ b/niucloud/addon/shop/app/model/discount/DiscountGoods.php
@@ -0,0 +1,95 @@
+ 'timestamp',
+ 'update_time' => 'timestamp',
+ ];
+
+ /**
+ * 限时折扣
+ * @return \think\model\relation\HasOne
+ */
+ public function discount()
+ {
+ return $this->hasOne(Discount::class, 'discount_id', 'discount_id');
+ }
+
+ /**
+ * 商品
+ * @return \think\model\relation\HasOne
+ */
+ public function goods()
+ {
+ return $this->hasOne(Goods::class, 'goods_id', 'goods_id');
+ }
+
+ /**
+ * 商品规格
+ * @return \think\model\relation\HasOne
+ */
+ public function goodsSku()
+ {
+ return $this->hasOne(GoodsSku::class, 'sku_id', 'sku_id');
+ }
+
+ /**
+ * 获取封面缩略图(小)
+ */
+ public function getGoodsCoverThumbSmallAttr($value, $data)
+ {
+ if (isset($data[ 'goods_cover' ]) && $data[ 'goods_cover' ] != '') {
+ return get_thumb_images($data[ 'goods_cover' ], FileDict::SMALL);
+ }
+ return [];
+ }
+
+ /**
+ * 状态字段转化
+ * @param $value
+ * @param $data
+ * @return mixed
+ */
+ public function getGoodsTypeNameAttr($value, $data)
+ {
+ if (!empty($data[ 'goods_type' ])) {
+ return GoodsDict::getType($data[ 'goods_type' ])[ 'name' ] ?? '';
+ }
+ return '';
+ }
+
+}
diff --git a/niucloud/addon/shop/app/model/exchange/Exchange.php b/niucloud/addon/shop/app/model/exchange/Exchange.php
new file mode 100644
index 000000000..7040c970a
--- /dev/null
+++ b/niucloud/addon/shop/app/model/exchange/Exchange.php
@@ -0,0 +1,315 @@
+ 'timestamp',
+ 'update_time' => 'timestamp',
+ ];
+
+ // 设置json类型字段
+ protected $json = ['product_detail'];
+
+ // 设置JSON数据返回数组
+ protected $jsonAssoc = true;
+
+ protected $autoWriteTimestamp = false;
+
+
+
+ /**
+ * 搜索器商品名称
+ * @param $value
+ * @param $data
+ */
+ public function searchNamesAttr($query, $value, $data)
+ {
+ if ($value != '') {
+ $query->where("names", 'like', '%' . $this->handelSpecialCharacter($value) . '%');
+ }
+ }
+
+ /**
+ * 搜索器ids
+ * @param $value
+ * @param $data
+ */
+ public function searchIdsAttr($query, $value, $data)
+ {
+ if ($value) {
+ $query->where("id", 'in', $value);
+ }
+ }
+
+ /**
+ * 搜索器商品sku 查询订单使用
+ * @param $value
+ * @param $data
+ */
+ public function searchProductDetailAttr($query, $value, $data)
+ {
+ if ($value) {
+ $query->where("product_detail", 'like', '%' . $value . '%');
+ }
+ }
+
+ /**
+ * 搜索器商品sku 查询sku
+ * @param $value
+ * @param $data
+ */
+ public function searchSkuIdAttr($query, $value, $data)
+ {
+
+ if ($value) {
+ $query->where('product_detail', 'like', '%' . '"sku_id":' . $value . ',' . '%');
+ }
+ }
+
+ /**
+ * 搜索器商品sku 查询sku
+ * @param $value
+ * @param $data
+ */
+ public function searchGoodsIdAttr($query, $value, $data)
+ {
+ if ($value) {
+ $query->where('product_detail', 'like', '%' . '"goods_id":' . $value . ',' . '%');
+ }
+ }
+
+ /**
+ * 创建时间搜索器
+ * @param Query $query
+ * @param $value
+ * @param $data
+ */
+ public function searchCreateTimeAttr(Query $query, $value, $data)
+ {
+ $start_time = empty($value[0]) ? 0 : strtotime($value[0]);
+ $end_time = empty($value[1]) ? 0 : strtotime($value[1]);
+ if ($start_time > 0 && $end_time > 0) {
+ $query->whereBetweenTime('create_time', $start_time, $end_time);
+ } else if ($start_time > 0 && $end_time == 0) {
+ $query->where([['create_time', '>=', $start_time]]);
+ } else if ($start_time == 0 && $end_time > 0) {
+ $query->where([['create_time', '<=', $end_time]]);
+ }
+ }
+
+ /**
+ * 搜索器:状态
+ * @param $value
+ * @param $data
+ */
+ public function searchStatusAttr($query, $value, $data)
+ {
+ if ($value != '') {
+ $query->where("status", '=', $value);
+ }
+ }
+
+ /**
+ * 搜索器:ID in 查询
+ * @param $value
+ * @param $data
+ */
+ public function searchIdAttr($query, $value, $data)
+ {
+ if ($value) {
+ $query->where("id", 'in', $value);
+ }
+ }
+
+ /**
+ * 活动商品类型
+ * @param $value
+ * @param $data
+ * @return mixed|string
+ */
+ public function getTypeNameAttr($value, $data)
+ {
+ if (empty($data['type'])) {
+ return '';
+ }
+ return ExchangeDict::getType()[$data['type']] ?? '';
+ }
+
+ /**
+ * 活动状态
+ * @param $value
+ * @param $data
+ * @return mixed|string
+ */
+ public function getStatusNameAttr($value, $data)
+ {
+ if (empty($data['status']) && $data['status'] != 0) {
+ return '';
+ }
+ return ExchangeDict::getStatus()[$data['status']] ?? '';
+ }
+
+ /**
+ * 获取封面缩略图(小)
+ */
+ public function getGoodsCoverThumbSmallAttr($value, $data)
+ {
+ $data['goods_cover'] = explode(',', $data['image'])[0];
+ if (isset($data['goods_cover']) && $data['goods_cover'] != '') {
+ return get_thumb_images($data['goods_cover'], FileDict::SMALL);
+ }
+ return [];
+ }
+
+ /**
+ * 获取封面缩略图(中)
+ */
+ public function getGoodsCoverThumbMidAttr($value, $data)
+ {
+ $data['goods_cover'] = explode(',', $data['image'])[0];
+ if (isset($data['goods_cover']) && $data['goods_cover'] != '') {
+ return get_thumb_images($data['goods_cover'], FileDict::MID);
+ }
+ return [];
+ }
+
+ /**
+ * 获取封面缩略图(大)
+ */
+ public function getGoodsCoverThumbBigAttr($value, $data)
+ {
+ $data['goods_cover'] = explode(',', $data['image'])[0];
+ if (isset($data['goods_cover']) && $data['goods_cover'] != '') {
+ return get_thumb_images($data['goods_cover'], FileDict::BIG);
+ }
+ return [];
+ }
+
+ /**
+ * 获取商品图片缩略图(小)
+ */
+ public function getGoodsImageThumbSmallAttr($value, $data)
+ {
+ if (isset($data['image']) && $data['image'] != '') {
+ $goods_image = explode(',', $data['image']);
+ $img_arr = [];
+ foreach ($goods_image as $k => $v) {
+ $img = get_thumb_images($v, FileDict::SMALL);
+ if (!empty($img)) {
+ $img_arr[] = $img;
+ }
+ }
+ return $img_arr;
+ }
+ return [];
+ }
+
+ /**
+ * 获取商品图片缩略图(中)
+ */
+ public function getGoodsImageThumbMidAttr($value, $data)
+ {
+ if (isset($data['image']) && $data['image'] != '') {
+ $goods_image = explode(',', $data['image']);
+ $img_arr = [];
+ foreach ($goods_image as $k => $v) {
+ $img = get_thumb_images($v, FileDict::MID);
+ if (!empty($img)) {
+ $img_arr[] = $img;
+ }
+ }
+ return $img_arr;
+ }
+ return [];
+ }
+
+ /**
+ * 获取商品图片缩略图(大)
+ */
+ public function getGoodsImageThumbBigAttr($value, $data)
+ {
+ if (isset($data['image']) && $data['image'] != '') {
+ $goods_image = explode(',', $data['image']);
+ $img_arr = [];
+ foreach ($goods_image as $k => $v) {
+ $img = get_thumb_images($v, FileDict::BIG);
+ if (!empty($img)) {
+ $img_arr[] = $img;
+ }
+ }
+ return $img_arr;
+ }
+ return [];
+ }
+
+ public function getGoodsBrandAttr($value, $data)
+ {
+ $product_detail = !is_array($data['product_detail']) ? json_decode($data['product_detail'], true) : $data['product_detail'];
+ $goods_id = $product_detail[0]['goods_id'];
+ $brand_id = (new Goods())->where([
+ ['goods_id', '=', $goods_id],
+ ])->value('brand_id') ?? 0;
+ $brand = (new Brand())->where([['brand_id', '=', $brand_id]])->field('brand_name,brand_id,color_json,logo')->findOrEmpty();
+ return $brand->isEmpty() ? null : $brand->toArray();
+ }
+
+ public function getGoodsLabelAttr($value, $data)
+ {
+ $product_detail = !is_array($data['product_detail']) ? json_decode($data['product_detail'], true) : $data['product_detail'];
+ $goods_id = $product_detail[0]['goods_id'];
+ $label_ids = (new Goods())->where([
+ ['goods_id', '=', $goods_id],
+ ])->value('label_ids') ?? [];
+ return (new Label())->where([ ['label_id', 'in', $label_ids]])->field('label_id,label_name,color_json,style_type,icon')->select()->toArray();
+
+ }
+
+ /**
+ * 搜索器:id
+ * @param $value
+ * @param $data
+ */
+ public function searchActiveIdAttr($query, $value, $data)
+ {
+ if (!empty($value)) {
+ $query->where("id", 'in', $value);
+ }
+ }
+
+}
diff --git a/niucloud/addon/shop/app/model/goods/Attr.php b/niucloud/addon/shop/app/model/goods/Attr.php
new file mode 100644
index 000000000..3e827622a
--- /dev/null
+++ b/niucloud/addon/shop/app/model/goods/Attr.php
@@ -0,0 +1,74 @@
+where("attr_id", $value);
+ }
+ }
+
+
+ /**
+ * 搜索器:商品参数商品参数id
+ * @param $value
+ * @param $data
+ */
+ public function searchAttrIdArrAttr($query, $value, $data)
+ {
+ if ($value) {
+ $query->where("attr_id", 'in', $value);
+ }
+ }
+
+ /**
+ * 搜索器:商品参数参数名称
+ * @param $value
+ * @param $data
+ */
+ public function searchAttrNameAttr($query, $value, $data)
+ {
+ if ($value != '') {
+ $query->where("attr_name", 'like', '%' . $this->handelSpecialCharacter($value) . '%');
+ }
+ }
+
+}
diff --git a/niucloud/addon/shop/app/model/goods/Brand.php b/niucloud/addon/shop/app/model/goods/Brand.php
new file mode 100644
index 000000000..69ba41a4f
--- /dev/null
+++ b/niucloud/addon/shop/app/model/goods/Brand.php
@@ -0,0 +1,55 @@
+where("brand_name", "like", "%" . $this->handelSpecialCharacter($value) . "%");
+ }
+ }
+
+}
diff --git a/niucloud/addon/shop/app/model/goods/Browse.php b/niucloud/addon/shop/app/model/goods/Browse.php
new file mode 100644
index 000000000..5400c0884
--- /dev/null
+++ b/niucloud/addon/shop/app/model/goods/Browse.php
@@ -0,0 +1,57 @@
+ 'timestamp',
+ ];
+ /**
+ * 商品信息
+ * @return HasOne
+ */
+ public function goods()
+ {
+ return $this->hasOne(Goods::class, 'goods_id', 'goods_id')->joinType('left')->withField('goods_id, goods_name,goods_cover,status')->append([ 'goods_cover_thumb_mid' ])->bind([ 'goods_name', 'goods_cover_thumb_mid','member_discount','status' ]);
+ }
+
+ /**
+ * 关联默认商品规格
+ * @return HasOne
+ */
+ public function goodsSku()
+ {
+ return $this->hasOne(GoodsSku::class, 'sku_id', 'sku_id')->bind(['price','market_price','member_price','sale_price']);
+ }
+
+}
diff --git a/niucloud/addon/shop/app/model/goods/Category.php b/niucloud/addon/shop/app/model/goods/Category.php
new file mode 100644
index 000000000..8a6e58e79
--- /dev/null
+++ b/niucloud/addon/shop/app/model/goods/Category.php
@@ -0,0 +1,72 @@
+where("category_name", "like", "%" . $value . "%");
+ }
+ }
+
+ /**
+ * 搜索器:商品分类id
+ * @param $value
+ * @param $data
+ */
+ public function searchCategoryIdAttr($query, $value, $data)
+ {
+ if ($value) {
+ $query->where("category_id", "=", $value );
+ }
+ }
+
+ /**
+ * 搜索器:pid
+ * @param $value
+ * @param $data
+ */
+ public function searchPidAttr($query, $value, $data)
+ {
+ if ($value) {
+ $query->where("pid", "=", $value );
+ }
+ }
+
+}
diff --git a/niucloud/addon/shop/app/model/goods/Evaluate.php b/niucloud/addon/shop/app/model/goods/Evaluate.php
new file mode 100644
index 000000000..659a7b88d
--- /dev/null
+++ b/niucloud/addon/shop/app/model/goods/Evaluate.php
@@ -0,0 +1,154 @@
+hasOne(Goods::class, 'goods_id', 'goods_id')->withField('goods_id, goods_name, goods_cover')
+ ->append([ 'goods_cover_thumb_small', 'goods_cover_thumb_mid' ]);
+ }
+
+ public function orderGoods()
+ {
+ return $this->hasOne(OrderGoods::class, 'order_goods_id', 'order_goods_id');
+ }
+
+ /**
+ * 审核状态转换
+ * @param $value
+ * @param $data
+ * @return mixed|string
+ */
+ public function getAuditNameAttr($value, $data)
+ {
+ return EvaluateDict::getStatus()[ $data[ 'is_audit' ] ] ?? '';
+ }
+
+ /**
+ * 缩略图生成-小图
+ * @param $value
+ * @param $data
+ * @return array|mixed
+ * @throws \Exception
+ */
+ public function getImageSmallAttr($value, $data)
+ {
+ if (!empty($data[ 'images' ])) {
+ $small_arr = [];
+ foreach ($data[ 'images' ] as $k => $v) {
+ $small_arr[] = get_thumb_images($v, FileDict::SMALL);
+ }
+ return $small_arr;
+ }
+ return [];
+ }
+
+ /**
+ * 缩略图生成-大图
+ * @param $value
+ * @param $data
+ * @return array|mixed
+ * @throws \Exception
+ */
+ public function getImageBigAttr($value, $data)
+ {
+ if (!empty($data[ 'images' ])) {
+ $small_arr = [];
+ foreach ($data[ 'images' ] as $k => $v) {
+ $small_arr[] = get_thumb_images($v, FileDict::BIG);
+ }
+ return $small_arr;
+ }
+ return [];
+ }
+
+ /**
+ * 缩略图生成-中图
+ * @param $value
+ * @param $data
+ * @return array|mixed
+ * @throws \Exception
+ */
+ public function getImageMidAttr($value, $data)
+ {
+ if (!empty($data[ 'images' ])) {
+ $small_arr = [];
+ foreach ($data[ 'images' ] as $k => $v) {
+ $small_arr[] = get_thumb_images($v, FileDict::MID);
+ }
+ return $small_arr;
+ }
+ return [];
+ }
+
+ /**
+ * 评分搜索器
+ * @param $query
+ * @param $value
+ * @param $data
+ */
+ public function searchScoresAttr($query, $value, $data)
+ {
+ if ($value) {
+ $query->where("scores", "in", $value);
+ }
+ }
+
+ public function searchGoodsIdAttr($query, $value, $data)
+ {
+ if ($value) {
+ $query->where("goods_id", "=", $value);
+ }
+ }
+
+ public function getMemberNameAttr($value, $data)
+ {
+ if (isset($data[ 'is_anonymous' ]) && $data[ 'is_anonymous' ] == 1) {
+ return '匿名买家';
+ }
+ return $value;
+ }
+}
diff --git a/niucloud/addon/shop/app/model/goods/Goods.php b/niucloud/addon/shop/app/model/goods/Goods.php
new file mode 100644
index 000000000..1f083127f
--- /dev/null
+++ b/niucloud/addon/shop/app/model/goods/Goods.php
@@ -0,0 +1,500 @@
+getDeliveryConfig();
+ $configKeys = array_keys($deliver_list); // 缓存配置数组的键
+ $result = [];
+
+ // 筛选可用的配送方式并按配置顺序排序
+ foreach ($data[ 'delivery_type' ] as $type) {
+ if (isset($deliver_list[ $type ]) && $deliver_list[ $type ][ 'status' ] === 1) {
+ $position = array_search($type, $configKeys);
+ $result[ $position ] = [ $type => $deliver_list[ $type ] ];
+ }
+ }
+ // 按键排序(保持配置中的原始顺序)
+ ksort($result);
+ // 转换为一维数组(保持原始代码的输出结构)
+ return array_merge([], ...array_values($result));
+ }
+ return [];
+ }
+
+ /**
+ * 获取封面缩略图(小)
+ */
+ public function getGoodsCoverThumbSmallAttr($value, $data)
+ {
+ if (isset($data[ 'goods_cover' ]) && $data[ 'goods_cover' ] != '') {
+ return get_thumb_images($data[ 'goods_cover' ], FileDict::SMALL);
+ }
+ return [];
+ }
+
+ /**
+ * 获取封面缩略图(中)
+ */
+ public function getGoodsCoverThumbMidAttr($value, $data)
+ {
+ if (isset($data[ 'goods_cover' ]) && $data[ 'goods_cover' ] != '') {
+ return get_thumb_images($data[ 'goods_cover' ], FileDict::MID);
+ }
+ return [];
+ }
+
+ /**
+ * 获取封面缩略图(大)
+ */
+ public function getGoodsCoverThumbBigAttr($value, $data)
+ {
+ if (isset($data[ 'goods_cover' ]) && $data[ 'goods_cover' ] != '') {
+ return get_thumb_images($data[ 'goods_cover' ], FileDict::BIG);
+ }
+ return [];
+ }
+
+ /**
+ * 获取商品图片缩略图(小)
+ */
+ public function getGoodsImageThumbSmallAttr($value, $data)
+ {
+ if (isset($data[ 'goods_image' ]) && $data[ 'goods_image' ] != '') {
+ $goods_image = explode(',', $data[ 'goods_image' ]);
+ $img_arr = [];
+ foreach ($goods_image as $k => $v) {
+ $img = get_thumb_images($v, FileDict::SMALL);
+ if (!empty($img)) {
+ $img_arr[] = $img;
+ }
+ }
+ return $img_arr;
+ }
+ return [];
+ }
+
+ /**
+ * 获取商品图片缩略图(中)
+ */
+ public function getGoodsImageThumbMidAttr($value, $data)
+ {
+ if (isset($data[ 'goods_image' ]) && $data[ 'goods_image' ] != '') {
+ $goods_image = explode(',', $data[ 'goods_image' ]);
+ $img_arr = [];
+ foreach ($goods_image as $k => $v) {
+ $img = get_thumb_images($v, FileDict::MID);
+ if (!empty($img)) {
+ $img_arr[] = $img;
+ }
+ }
+ return $img_arr;
+ }
+ return [];
+ }
+
+ /**
+ * 获取商品图片缩略图(大)
+ */
+ public function getGoodsImageThumbBigAttr($value, $data)
+ {
+ if (isset($data[ 'goods_image' ]) && $data[ 'goods_image' ] != '') {
+ $goods_image = explode(',', $data[ 'goods_image' ]);
+ $img_arr = [];
+ foreach ($goods_image as $k => $v) {
+ $img = get_thumb_images($v, FileDict::BIG);
+ if (!empty($img)) {
+ $img_arr[] = $img;
+ }
+ }
+ return $img_arr;
+ }
+ return [];
+ }
+
+ /**
+ * 获取商品分类
+ */
+ public function getGoodsCategoryAttr($value, $data)
+ {
+ if (!is_array($value)) {
+ $value = json_decode($value, true);
+ }
+ if (!empty($value)) {
+ return array_map(function ($item) {
+ return (int) $item;
+ }, $value);
+ }
+ return [];
+ }
+
+ public function getGoodsLabelNameAttr($value, $data)
+ {
+ if (isset($data[ 'label_ids' ]) && !empty($data[ 'label_ids' ])) {
+ $goods_label_model = new Label();
+ return $goods_label_model->where([
+ [ 'label_id', 'in', $data[ 'label_ids' ] ],
+ [ 'status', '=', 1 ]
+ ])->field('label_id, label_name, style_type,color_json,icon')->order('sort desc,label_id desc')->select()->toArray();
+ }
+
+ }
+
+ public function getGoodsBrandAttr($value, $data)
+ {
+ if (isset($data[ 'brand_id' ]) && !empty($data[ 'brand_id' ])) {
+ $goods_brand_model = new Brand();
+ $info = $goods_brand_model->where([
+ [ 'brand_id', '=', $data[ 'brand_id' ] ],
+ ])->field('brand_id,brand_name,logo,color_json')
+ ->findOrEmpty()->toArray();
+ return $info;
+ }
+ }
+
+ /**
+ * 状态字段转化
+ * @param $value
+ * @param $data
+ * @return mixed
+ */
+ public function getDiscountStatusNameAttr($value, $data)
+ {
+ if (!empty($data[ 'discount_status' ])) {
+ return DiscountDict::getStatus($data[ 'discount_status' ]) ?? '';
+ }
+ return '';
+ }
+
+ /**
+ * 搜索器:商品商品id
+ * @param $value
+ * @param $data
+ */
+ public function searchGoodsIdAttr($query, $value, $data)
+ {
+ if ($value) {
+ $query->where("goods_id", $value);
+ }
+ }
+
+ /**
+ * 搜索器:商品商品名称
+ * @param $value
+ * @param $data
+ */
+ public function searchGoodsNameAttr($query, $value, $data)
+ {
+ if ($value != '') {
+ $query->where("goods_name", "like", "%" . $this->handelSpecialCharacter($value) . "%");
+ }
+ }
+
+ /**
+ * 搜索器:商品副标题
+ * @param $value
+ * @param $data
+ */
+ public function searchSubTitleAttr($query, $value, $data)
+ {
+ if ($value != '') {
+ $query->where("sub_title", "like", "%" . $value . "%");
+ }
+ }
+
+ /**
+ * 搜索器:商品商品类型
+ * @param $value
+ * @param $data
+ */
+ public function searchGoodsTypeAttr($query, $value, $data)
+ {
+ if ($value) {
+ $query->where("goods_type", $value);
+ }
+ }
+
+ /**
+ * 搜索器:商品商品品牌id
+ * @param $value
+ * @param $data
+ */
+ public function searchBrandIdAttr($query, $value, $data)
+ {
+ if ($value) {
+ $query->where("brand_id", $value);
+ }
+ }
+
+ /**
+ * 搜索器:商品商品分类
+ * @param $value
+ * @param $data
+ */
+ public function searchGoodsCategoryAttr(Query $query, $value, $data)
+ {
+ if ($value) {
+ if (is_array($value)) {
+ $temp_where = array_map(function ($item) {
+ return '%"' . $item . '"%';
+ }, $value);
+ } else {
+ $temp_where = [ '%"' . $value . '"%' ];
+ }
+ $query->where('goods_category', 'like', $temp_where, 'or');
+ }
+ }
+
+ /**
+ * 搜索器:商品标签组
+ * @param $value
+ * @param $data
+ */
+ public function searchLabelIdsAttr($query, $value, $data)
+ {
+ if ($value) {
+ if (is_array($value)) {
+ $temp_where = array_map(function ($item) {
+ return '%"' . $item . '"%';
+ }, $value);
+ } else {
+ $temp_where = [ '%"' . $value . '"%' ];
+ }
+ $query->where('label_ids', 'like', $temp_where, 'or');
+ }
+ }
+
+ /**
+ * 搜索器:商品服务
+ * @param $value
+ * @param $data
+ */
+ public function searchServiceIdsAttr($query, $value, $data)
+ {
+ if ($value) {
+ if (is_array($value)) {
+ $temp_where = array_map(function ($item) {
+ return '%"' . $item . '"%';
+ }, $value);
+ } else {
+ $temp_where = [ '%"' . $value . '"%' ];
+ }
+ $query->where('service_ids', 'like', $temp_where, 'or');
+ }
+ }
+
+ /**
+ * 搜索器:商品支持的配送方式
+ * @param $value
+ * @param $data
+ */
+ public function searchDeliveryTypeAttr($query, $value, $data)
+ {
+ if ($value) {
+ if (gettype($value) == 'array') {
+ $like_arr = [];
+ foreach ($value as $k => $v) {
+ $like_arr[] = "%" . $v . "%";
+ }
+ $query->where("delivery_type", "like", $like_arr, 'or');
+ } else {
+ $query->where("delivery_type", "like", '%' . $value . '%');
+ }
+ }
+ }
+
+ /**
+ * 搜索器:商品销量
+ * @param $value
+ * @param $data
+ */
+ public function searchSaleNumAttr($query, $value, $data)
+ {
+ if (!empty($data[ 'start_sale_num' ]) && !empty($data[ 'end_sale_num' ])) {
+ $money = [ $data[ 'start_sale_num' ], $data[ 'end_sale_num' ] ];
+ sort($money);
+ $query->where('goods.sale_num', 'between', $money);
+ } else if (!empty($data[ 'start_sale_num' ])) {
+ $query->where('goods.sale_num', '>=', $data[ 'start_sale_num' ]);
+ } else if (!empty($data[ 'end_sale_num' ])) {
+ $query->where('goods.sale_num', '<=', $data[ 'end_sale_num' ]);
+ }
+
+ }
+
+ /**
+ * 搜索器:商品商品状态(1.正常0下架)
+ * @param $value
+ * @param $data
+ */
+ public function searchStatusAttr($query, $value, $data)
+ {
+ if ($value !== '') {
+ $query->where("status", $value);
+ }
+ }
+
+ /**
+ * 搜索器:供应商id
+ * @param $value
+ * @param $data
+ */
+ public function searchSupplierIdAttr($query, $value, $data)
+ {
+ if ($value) {
+ $query->where("supplier_id", $value);
+ }
+ }
+
+ /**
+ * 关联默认商品规格
+ * @return \think\model\relation\HasOne
+ */
+ public function goodsSku()
+ {
+ return $this->hasOne(GoodsSku::class, 'goods_id', 'goods_id');
+ }
+
+ /**
+ * 关联活动
+ * @return \think\model\relation\HasOne
+ */
+ public function activeGoods()
+ {
+ return $this->hasOne(ActiveGoods::class, 'goods_id', 'goods_id');
+ }
+
+ /**
+ * 关联活动
+ * @return \think\model\relation\hasOne
+ */
+ public function discountGoods()
+ {
+ return $this->hasOne(discountGoods::class, 'goods_id', 'goods_id');
+ }
+
+ /**
+ * 关联商品规格列表
+ * @return \think\model\relation\HasMany
+ */
+ public function skuList()
+ {
+ return $this->hasMany(GoodsSku::class, 'goods_id', 'goods_id');
+ }
+
+ /**
+ * 关联商品规格列表
+ * @return \think\model\relation\HasMany
+ */
+ public function goodsSpec()
+ {
+ return $this->hasMany(GoodsSpec::class, 'goods_id', 'goods_id');
+ }
+
+ /**
+ * 关联商品品牌
+ * @return \think\model\relation\HasOne
+ */
+ public function brand()
+ {
+ return $this->hasOne(Brand::class, 'brand_id', 'brand_id')
+ ->joinType('left')
+ ->withField('brand_id, brand_name, logo, desc');
+ }
+
+}
diff --git a/niucloud/addon/shop/app/model/goods/GoodsCollect.php b/niucloud/addon/shop/app/model/goods/GoodsCollect.php
new file mode 100644
index 000000000..78d0b3480
--- /dev/null
+++ b/niucloud/addon/shop/app/model/goods/GoodsCollect.php
@@ -0,0 +1,56 @@
+hasOne(Goods::class, 'goods_id', 'goods_id')->joinType('left')->withField('goods_id, goods_name,goods_cover,status')->append([ 'goods_cover_thumb_mid' ])->bind([ 'goods_name', 'goods_cover_thumb_mid','status' ]);
+ }
+
+ /**
+ * 关联默认商品规格
+ * @return \think\model\relation\HasOne
+ */
+ public function goodsSku()
+ {
+ return $this->hasOne(GoodsSku::class, 'goods_id', 'goods_id')->joinType('left')->withField('goods_id,sku_id,sku_name,price,member_price,sale_price')->bind([ 'sku_id', 'sku_name', 'price', 'member_price', 'sale_price' ]);
+ }
+
+}
diff --git a/niucloud/addon/shop/app/model/goods/GoodsSku.php b/niucloud/addon/shop/app/model/goods/GoodsSku.php
new file mode 100644
index 000000000..3e191564c
--- /dev/null
+++ b/niucloud/addon/shop/app/model/goods/GoodsSku.php
@@ -0,0 +1,300 @@
+where("sku_id", $value);
+ }
+ }
+
+ /**
+ * 搜索器:商品规格商品sku名称
+ * @param $value
+ * @param $data
+ */
+ public function searchSkuNameAttr($query, $value, $data)
+ {
+ if ($value != '') {
+ $query->where("sku_name", "like", "%" . $value . "%");
+ }
+ }
+
+ /**
+ * 搜索器:商品规格商品sku编码
+ * @param $value
+ * @param $data
+ */
+ public function searchSkuNoAttr($query, $value, $data)
+ {
+ if ($value != '') {
+ $query->where("sku_no", "like", "%" . $value . "%");
+ }
+ }
+
+ /**
+ * 搜索器:商品规格商品id
+ * @param $value
+ * @param $data
+ */
+ public function searchGoodsIdAttr($query, $value, $data)
+ {
+ if ($value) {
+ $query->where("goods_id", 'in', $value);
+ }
+ }
+
+ /**
+ * 搜索器:商品规格sku规格格式
+ * @param $value
+ * @param $data
+ */
+ public function searchSkuSpecFormatAttr($query, $value, $data)
+ {
+ if ($value) {
+ $query->where("sku_spec_format", $value);
+ }
+ }
+
+ /**
+ * 搜索器:商品规格sku单价
+ * @param $value
+ * @param $data
+ */
+ public function searchPriceAttr($query, $value, $data)
+ {
+ if ($value) {
+ $query->where("price", $value);
+ }
+ }
+
+ /**
+ * 搜索器:商品规格划线价
+ * @param $value
+ * @param $data
+ */
+ public function searchMarketPriceAttr($query, $value, $data)
+ {
+ if ($value) {
+ $query->where("market_price", $value);
+ }
+ }
+
+ /**
+ * 搜索器:商品规格实际卖价(有活动显示活动价,默认原价)
+ * @param $value
+ * @param $data
+ */
+ public function searchSalePriceAttr($query, $value, $data)
+ {
+ if ($value) {
+ $query->where("sale_price", $value);
+ }
+ }
+
+ /**
+ * 搜索器:商品规格sku成本价
+ * @param $value
+ * @param $data
+ */
+ public function searchCostPriceAttr($query, $value, $data)
+ {
+ if ($value) {
+ $query->where("cost_price", $value);
+ }
+ }
+
+ /**
+ * 搜索器:商品规格商品sku库存
+ * @param $value
+ * @param $data
+ */
+ public function searchStockAttr($query, $value, $data)
+ {
+ if ($value) {
+ $query->where("stock", $value);
+ }
+ }
+
+ /**
+ * 搜索器:商品规格重量(单位kg)
+ * @param $value
+ * @param $data
+ */
+ public function searchWeightAttr($query, $value, $data)
+ {
+ if ($value) {
+ $query->where("weight", $value);
+ }
+ }
+
+ /**
+ * 搜索器:商品规格体积(单位立方米)
+ * @param $value
+ * @param $data
+ */
+ public function searchVolumeAttr($query, $value, $data)
+ {
+ if ($value) {
+ $query->where("volume", $value);
+ }
+ }
+
+ /**
+ * 搜索器:商品规格销量
+ * @param $value
+ * @param $data
+ */
+ public function searchSaleNumAttr($query, $value, $data)
+ {
+ if ($value) {
+ $query->where("sale_num", $value);
+ }
+ }
+
+ /**
+ * 搜索器:商品规格sku主图
+ * @param $value
+ * @param $data
+ */
+ public function searchSkuImageAttr($query, $value, $data)
+ {
+ if ($value) {
+ $query->where("sku_image", $value);
+ }
+ }
+
+ /**
+ * 搜索器:商品规格是否默认
+ * @param $value
+ * @param $data
+ */
+ public function searchIsDefaultAttr($query, $value, $data)
+ {
+ if ($value) {
+ $query->where("is_default", $value);
+ }
+ }
+
+ /**
+ * 关联商品主表
+ * @return \think\model\relation\HasOne
+ */
+ public function goods()
+ {
+ return $this->hasOne(Goods::class, 'goods_id', 'goods_id')
+ ->joinType('left')
+ ->withField('goods_id, is_discount, goods_name, goods_type, sub_title, goods_cover, goods_image,goods_desc,brand_id,label_ids,service_ids, unit, stock, sale_num + virtual_sale_num as sale_num, is_limit, limit_type, max_buy, min_buy, status, is_free_shipping, fee_type, delivery_type, delivery_money, delivery_template_id, goods_category,attr_ids,attr_format,member_discount,is_discount,form_id')
+ ->append([ 'goods_type_name', 'goods_cover_thumb_small', 'goods_cover_thumb_mid', 'delivery_type_list', 'goods_image_thumb_small', 'goods_image_thumb_mid', 'goods_image_thumb_big' ]);
+ }
+
+ /**
+ * 关联商品规格列表
+ * @return \think\model\relation\HasMany
+ */
+ public function skuList()
+ {
+ return $this->hasMany(GoodsSku::class, 'goods_id', 'goods_id');
+ }
+
+ /**
+ * 关联商品规格列表
+ * @return \think\model\relation\HasMany
+ */
+ public function goodsSpec()
+ {
+ return $this->hasMany(GoodsSpec::class, 'goods_id', 'goods_id');
+ }
+
+ /**
+ * 关联商品主表
+ * @return \think\model\relation\HasOne
+ */
+ public function goodsInfo()
+ {
+ return $this->hasOne(Goods::class, 'goods_id', 'goods_id')
+ ->joinType('left');
+ }
+
+ /**
+ * 关联商品主表(自定义字段)
+ * @return \think\model\relation\HasOne
+ */
+ public function goodsSingle()
+ {
+ return $this->hasOne(Goods::class, 'goods_id', 'goods_id')->joinType('left');
+ }
+
+}
diff --git a/niucloud/addon/shop/app/model/goods/GoodsSpec.php b/niucloud/addon/shop/app/model/goods/GoodsSpec.php
new file mode 100644
index 000000000..58f7f58d8
--- /dev/null
+++ b/niucloud/addon/shop/app/model/goods/GoodsSpec.php
@@ -0,0 +1,86 @@
+where("spec_id", $value);
+ }
+ }
+
+ /**
+ * 搜索器:商品规格值关联商品id
+ * @param $value
+ * @param $data
+ */
+ public function searchGoodsIdAttr($query, $value, $data)
+ {
+ if ($value) {
+ $query->where("goods_id", $value);
+ }
+ }
+
+ /**
+ * 搜索器:商品规格值规格项名称
+ * @param $value
+ * @param $data
+ */
+ public function searchSpecNameAttr($query, $value, $data)
+ {
+ if ($value) {
+ $query->where("spec_name", $value);
+ }
+ }
+
+ /**
+ * 搜索器:商品规格值规格值名称,多个逗号隔开
+ * @param $value
+ * @param $data
+ */
+ public function searchSpecValuesAttr($query, $value, $data)
+ {
+ if ($value) {
+ $query->where("spec_values", $value);
+ }
+ }
+
+}
diff --git a/niucloud/addon/shop/app/model/goods/Label.php b/niucloud/addon/shop/app/model/goods/Label.php
new file mode 100644
index 000000000..48817d143
--- /dev/null
+++ b/niucloud/addon/shop/app/model/goods/Label.php
@@ -0,0 +1,74 @@
+where("label_name", "like", "%" . $this->handelSpecialCharacter($value) . "%");
+ }
+ }
+
+ /**
+ * 搜索器:商品标签分组id
+ * @param $value
+ * @param $data
+ */
+ public function searchGroupIdAttr($query, $value, $data)
+ {
+ if ($value) {
+ $query->where("group_id", "=", $value);
+ }
+ }
+
+ /**
+ * 关联商品标签分组
+ * @return \think\model\relation\HasOne
+ */
+ public function group()
+ {
+ return $this->hasOne(LabelGroup::class, 'group_id', 'group_id');
+ }
+
+}
diff --git a/niucloud/addon/shop/app/model/goods/LabelGroup.php b/niucloud/addon/shop/app/model/goods/LabelGroup.php
new file mode 100644
index 000000000..2380ff349
--- /dev/null
+++ b/niucloud/addon/shop/app/model/goods/LabelGroup.php
@@ -0,0 +1,46 @@
+where("group_name", "like", "%" . $this->handelSpecialCharacter($value) . "%");
+ }
+ }
+}
diff --git a/niucloud/addon/shop/app/model/goods/Rank.php b/niucloud/addon/shop/app/model/goods/Rank.php
new file mode 100644
index 000000000..c7db56ecb
--- /dev/null
+++ b/niucloud/addon/shop/app/model/goods/Rank.php
@@ -0,0 +1,111 @@
+where("name", "like", "%" . $this->handelSpecialCharacter($value) . "%");
+ }
+ }
+
+ /**
+ * 搜索器:排行榜名称
+ * @param $value
+ * @param $data
+ */
+ public function searchRankTypeAttr($query, $value, $data)
+ {
+ if ($value) {
+ $query->where("rank_type", '=', $value);
+ }
+ }
+
+ /**
+ * 排行周期
+ * @param $value
+ * @param $data
+ * @return mixed|string
+ */
+ public function getRankTypeNameAttr($value, $data)
+ {
+ if (empty($data['rank_type']))
+ {
+ return '';
+ }
+ return RankDict::getRankType()[$data['rank_type']] ?? '';
+ }
+
+ /**
+ * 来源类型
+ * @param $value
+ * @param $data
+ * @return mixed|string
+ */
+ public function getGoodsSourceNameAttr($value, $data)
+ {
+ if (empty($data['goods_source']))
+ {
+ return '';
+ }
+ return RankDict::getGoodsSource()[$data['goods_source']] ?? '';
+ }
+
+ /**
+ * 排序规则
+ * @param $value
+ * @param $data
+ * @return mixed|string
+ */
+ public function getRuleTypeNameAttr($value, $data)
+ {
+ if (empty($data['rule_type']))
+ {
+ return '';
+ }
+ return RankDict::getRuleType()[$data['rule_type']] ?? '';
+ }
+
+}
diff --git a/niucloud/addon/shop/app/model/goods/Service.php b/niucloud/addon/shop/app/model/goods/Service.php
new file mode 100644
index 000000000..2a31e6b2a
--- /dev/null
+++ b/niucloud/addon/shop/app/model/goods/Service.php
@@ -0,0 +1,60 @@
+where("service_id", $value);
+ }
+ }
+
+ /**
+ * 搜索器:商品服务服务名称
+ * @param $value
+ * @param $data
+ */
+ public function searchServiceNameAttr($query, $value, $data)
+ {
+ if ($value != '') {
+ $query->where("service_name", "like", "%" . $this->handelSpecialCharacter($value) . "%");
+ }
+ }
+
+}
diff --git a/niucloud/addon/shop/app/model/goods/Stat.php b/niucloud/addon/shop/app/model/goods/Stat.php
new file mode 100644
index 000000000..1c61ebd59
--- /dev/null
+++ b/niucloud/addon/shop/app/model/goods/Stat.php
@@ -0,0 +1,63 @@
+ 'timestamp',
+ ];
+
+ /**
+ * 关联默认商品
+ * @return \think\model\relation\HasOne
+ */
+ public function goods()
+ {
+ return $this->hasOne(Goods::class, 'goods_id', 'goods_id');
+ }
+
+ /**
+ * 获取封面缩略图(小)
+ */
+ public function getGoodsCoverThumbSmallAttr($value, $data)
+ {
+ if (isset($data[ 'goods_cover' ]) && $data[ 'goods_cover' ] != '') {
+ return get_thumb_images($data[ 'goods_cover' ], FileDict::SMALL);
+ }
+ return [];
+ }
+
+}
diff --git a/niucloud/addon/shop/app/model/manjian/Manjian.php b/niucloud/addon/shop/app/model/manjian/Manjian.php
new file mode 100644
index 000000000..2104e96bd
--- /dev/null
+++ b/niucloud/addon/shop/app/model/manjian/Manjian.php
@@ -0,0 +1,136 @@
+ 'timestamp',
+ 'end_time' => 'timestamp',
+ ];
+
+ // 设置json类型字段
+ protected $json = [ 'rule_json', 'goods_ids', 'level_ids', 'label_ids' ];
+
+ // 设置JSON数据返回数组
+ protected $jsonAssoc = true;
+
+ /**
+ * 活动商品项
+ * @return \think\model\relation\HasMany
+ */
+ public function activeGoods()
+ {
+ return $this->hasMany(ManjianGoods::class, 'manjian_id', 'manjian_id');
+ }
+
+ /**
+ * 活动状态
+ * @param $value
+ * @param $data
+ * @return mixed|string
+ */
+ public function getStatusNameAttr($value, $data)
+ {
+ return ManjianDict::getStatus()[ $data[ 'status' ] ] ?? '';
+ }
+
+ /**
+ * 参与商品
+ * @param $value
+ * @param $data
+ * @return mixed|string
+ */
+ public function getGoodsTypeNameAttr($value, $data)
+ {
+ if (empty($data[ 'goods_type' ])) {
+ return '';
+ }
+ return ManjianDict::getGoodsType()[ $data[ 'goods_type' ] ] ?? '';
+ }
+
+ /**
+ * 搜索器:标题
+ * @param $value
+ * @param $data
+ */
+ public function searchManjianNameAttr($query, $value, $data)
+ {
+ if ($value != '') {
+ $query->where("manjian_name", 'like', '%' . $this->handelSpecialCharacter($value) . '%');
+ }
+ }
+
+ /**
+ * 搜索器:状态
+ * @param $value
+ * @param $data
+ */
+ public function searchStatusAttr($query, $value, $data)
+ {
+ if ($value != '') {
+ $query->where("status", '=', $value);
+ }
+ }
+
+ /**
+ * 活动结束时间搜索器
+ * @param Query $query
+ * @param $value
+ * @param $data
+ */
+ public function searchCreateTimeAttr(Query $query, $value, $data)
+ {
+ $start_time = empty($value[ 0 ]) ? 0 : strtotime($value[ 0 ]);
+ $end_time = empty($value[ 1 ]) ? 0 : strtotime($value[ 1 ]);
+ if ($start_time > 0 && $end_time > 0) {
+ $query->whereBetweenTime('end_time', $start_time, $end_time);
+ } else if ($start_time > 0 && $end_time == 0) {
+ $query->where([ [ 'end_time', '>=', $start_time ] ]);
+ } else if ($start_time == 0 && $end_time > 0) {
+ $query->where([ [ 'end_time', '<=', $end_time ] ]);
+ }
+ }
+
+ /**
+ * 搜索器:id
+ * @param $value
+ * @param $data
+ */
+ public function searchActiveIdAttr($query, $value, $data)
+ {
+ if (!empty($value)) {
+ $query->where("manjian_id", 'in', $value);
+ }
+ }
+}
diff --git a/niucloud/addon/shop/app/model/manjian/ManjianGiveRecords.php b/niucloud/addon/shop/app/model/manjian/ManjianGiveRecords.php
new file mode 100644
index 000000000..b9aeb631f
--- /dev/null
+++ b/niucloud/addon/shop/app/model/manjian/ManjianGiveRecords.php
@@ -0,0 +1,54 @@
+hasOne(Order::class, 'order_id', 'order_id');
+ }
+}
diff --git a/niucloud/addon/shop/app/model/manjian/ManjianGoods.php b/niucloud/addon/shop/app/model/manjian/ManjianGoods.php
new file mode 100644
index 000000000..06f4f5607
--- /dev/null
+++ b/niucloud/addon/shop/app/model/manjian/ManjianGoods.php
@@ -0,0 +1,77 @@
+hasOne(Goods::class, 'goods_id', 'goods_id');
+ }
+
+ /**
+ * 关联默认商品规格
+ * @return \think\model\relation\HasOne
+ */
+ public function goodsSku()
+ {
+ return $this->hasOne(GoodsSku::class, 'goods_id', 'goods_id');
+ }
+
+ /**
+ * 关联默认商品规格
+ * @return \think\model\relation\HasOne
+ */
+ public function goodsSkuOne()
+ {
+ return $this->hasOne(GoodsSku::class, 'sku_id', 'sku_id');
+ }
+
+ /**
+ * 关联满减活动
+ * @return \think\model\relation\HasOne
+ */
+ public function manjian()
+ {
+ return $this->hasOne(Manjian::class, 'manjian_id', 'manjian_id');
+ }
+}
diff --git a/niucloud/addon/shop/app/model/newcomer/NewcomerRecords.php b/niucloud/addon/shop/app/model/newcomer/NewcomerRecords.php
new file mode 100644
index 000000000..2bc6e4e1f
--- /dev/null
+++ b/niucloud/addon/shop/app/model/newcomer/NewcomerRecords.php
@@ -0,0 +1,43 @@
+ 'timestamp',
+ ];
+
+ /**
+ * 创建时间搜索器
+ * @param Query $query
+ * @param $value
+ * @param $data
+ */
+ public function searchCreateTimeAttr(Query $query, $value, $data)
+ {
+ $start_time = empty($value[ 0 ]) ? 0 : strtotime($value[ 0 ]);
+ $end_time = empty($value[ 1 ]) ? 0 : strtotime($value[ 1 ]);
+ if ($start_time > 0 && $end_time > 0) {
+ $query->whereBetweenTime('create_time', $start_time, $end_time);
+ } else if ($start_time > 0 && $end_time == 0) {
+ $query->where([ [ 'create_time', '>=', $start_time ] ]);
+ } else if ($start_time == 0 && $end_time > 0) {
+ $query->where([ [ 'create_time', '<=', $end_time ] ]);
+ }
+ }
+
+ /**
+ * 开票时间
+ * @param Query $query
+ * @param $value
+ * @param $data
+ * @return void
+ */
+ public function searchInvoiceTimeAttr(Query $query, $value, $data)
+ {
+ $start_time = empty($value[ 0 ]) ? 0 : strtotime($value[ 0 ]);
+ $end_time = empty($value[ 1 ]) ? 0 : strtotime($value[ 1 ]);
+ if ($start_time > 0 && $end_time > 0) {
+ $query->whereBetweenTime('invoice_time', $start_time, $end_time);
+ } else if ($start_time > 0 && $end_time == 0) {
+ $query->where([ [ 'invoice_time', '>=', $start_time ] ]);
+ } else if ($start_time == 0 && $end_time > 0) {
+ $query->where([ [ 'invoice_time', '<=', $end_time ] ]);
+ }
+ }
+
+ /**
+ * 是否已开票
+ * @param Query $query
+ * @param $value
+ * @param $data
+ * @return void
+ */
+ public function searchIsInvoiceAttr(Query $query, $value, $data)
+ {
+ if ($value != 'all') $query->where([ [ 'is_invoice', '=', $value ] ]);
+ }
+
+ /**
+ * 通过抬头类型搜索
+ * @param Query $query
+ * @param $value
+ * @param $data
+ * @return void
+ */
+ public function searchHeaderTypeAttr(Query $query, $value, $data)
+ {
+ if ($value != 'all') $query->where([ [ 'header_type', '=', $value ] ]);
+ }
+
+ /**
+ * 抬头内容
+ * @param Query $query
+ * @param $value
+ * @param $data
+ * @return void
+ */
+ public function searchHeaderNameAttr(Query $query, $value, $data)
+ {
+ if ($value != '') $query->where([ [ 'header_name', 'like', "%" . $this->handelSpecialCharacter($value) . "%" ] ]);
+ }
+
+ /**
+ * @param $value
+ * @param $data
+ * @return mixed|string
+ */
+ public function getHeaderTypeNameAttr($value, $data)
+ {
+ return InvoiceDict::getHeaderType()[ $data[ 'header_type' ] ] ?? '';
+ }
+
+ public function getTypeNameAttr($value, $data)
+ {
+ return InvoiceDict::getType()[ $data[ 'type' ] ] ?? '';
+ }
+
+ /**
+ * 获取开票状态
+ * @param $value
+ * @param $data
+ * @return mixed|string
+ */
+ public function getIsInvoiceNameAttr($value, $data)
+ {
+ return InvoiceDict::getIsInvoice()[ $data[ 'is_invoice' ] ] ?? '';
+ }
+ /**
+ * 获取开票状态
+ * @param $value
+ * @param $data
+ * @return mixed|string
+ */
+ public function getInvoiceTypeNameAttr($value, $data)
+ {
+ return InvoiceDict::getIsInvoice()[ $data[ 'is_invoice' ] ] ?? '';
+ }
+
+ /**
+ * 开票会员
+ * @return HasOne
+ */
+ public function member()
+ {
+ return $this->hasOne(Member::class, 'member_id', 'member_id');
+ }
+
+ /**
+ * 开票订单
+ * @return HasOne
+ */
+ public function shopOrder()
+ {
+ return $this->hasOne(Order::class, 'order_id', 'trade_id');
+ }
+
+ /**
+ * 开票订单
+ * @return \think\model\relation\HasMany
+ */
+ public function orderList()
+ {
+ return $this->hasMany(Order::class, 'invoice_id', 'id');
+ }
+
+ /**
+ * 获取商品图片缩略图(小)
+ */
+ public function getPayVoucherThumbSmallAttr($value, $data)
+ {
+ if (isset($data[ 'pay_voucher' ]) && $data[ 'pay_voucher' ] != '') {
+ $pay_voucher = explode(',', $data[ 'pay_voucher' ]);
+ $img_arr = [];
+ foreach ($pay_voucher as $k => $v) {
+ $img = get_thumb_images($v, FileDict::SMALL);
+ if (!empty($img)) {
+ $img_arr[] = $img;
+ }
+ }
+ return $img_arr;
+ }
+ return [];
+ }
+
+ /**
+ * 获取商品图片缩略图(中)
+ */
+ public function getPayVoucherThumbMidAttr($value, $data)
+ {
+ if (isset($data[ 'pay_voucher' ]) && $data[ 'pay_voucher' ] != '') {
+ $pay_voucher = explode(',', $data[ 'pay_voucher' ]);
+ $img_arr = [];
+ foreach ($pay_voucher as $k => $v) {
+ $img = get_thumb_images($v, FileDict::MID);
+ if (!empty($img)) {
+ $img_arr[] = $img;
+ }
+ }
+ return $img_arr;
+ }
+ return [];
+ }
+
+ /**
+ * 获取商品图片缩略图(大)
+ */
+ public function getPayVoucherThumbBigAttr($value, $data)
+ {
+ if (isset($data[ 'pay_voucher' ]) && $data[ 'pay_voucher' ] != '') {
+ $pay_voucher = explode(',', $data[ 'pay_voucher' ]);
+ $img_arr = [];
+ foreach ($pay_voucher as $k => $v) {
+ $img = get_thumb_images($v, FileDict::BIG);
+ if (!empty($img)) {
+ $img_arr[] = $img;
+ }
+ }
+ return $img_arr;
+ }
+ return [];
+ }
+
+ /**
+ * 获取封面缩略图(小)
+ */
+ public function getInvoiceVoucherThumbSmallAttr($value, $data)
+ {
+ if (isset($data[ 'invoice_voucher' ]) && $data[ 'invoice_voucher' ] != '') {
+ return get_thumb_images($data[ 'invoice_voucher' ], FileDict::SMALL);
+ }
+ return [];
+ }
+
+ /**
+ * 获取封面缩略图(中)
+ */
+ public function getInvoiceVoucherThumbMidAttr($value, $data)
+ {
+ if (isset($data[ 'invoice_voucher' ]) && $data[ 'invoice_voucher' ] != '') {
+ return get_thumb_images($data[ 'invoice_voucher' ], FileDict::MID);
+ }
+ return [];
+ }
+
+ /**
+ * 获取封面缩略图(大)
+ */
+ public function getInvoiceVoucherThumbBigAttr($value, $data)
+ {
+ if (isset($data[ 'invoice_voucher' ]) && $data[ 'invoice_voucher' ] != '') {
+ return get_thumb_images($data[ 'invoice_voucher' ], FileDict::BIG);
+ }
+ return [];
+ }
+}
diff --git a/niucloud/addon/shop/app/model/order/Order.php b/niucloud/addon/shop/app/model/order/Order.php
new file mode 100644
index 000000000..00f2c6a96
--- /dev/null
+++ b/niucloud/addon/shop/app/model/order/Order.php
@@ -0,0 +1,374 @@
+ 'timestamp',
+ 'close_time' => 'timestamp',
+
+ 'delivery_time' => 'timestamp',
+ 'take_time' => 'timestamp',
+ 'finish_time' => 'timestamp',
+ ];
+
+ // 设置json类型字段
+ protected $json = [ 'has_goods_types' ];
+
+ // 设置JSON数据返回数组
+ protected $jsonAssoc = true;
+
+ /**
+ * 定义软删除标记字段.
+ * @var string
+ */
+ protected $deleteTime = 'delete_time';
+
+ protected $defaultSoftDelete = 0;
+
+ /**
+ * 订单项
+ * @return HasMany
+ */
+ public function orderGoods()
+ {
+ return $this->hasMany(OrderGoods::class, 'order_id', 'order_id');
+ }
+
+ /**
+ * 订单会员
+ * @return HasOne
+ */
+ public function member()
+ {
+ return $this->hasOne(Member::class, 'member_id', 'member_id');
+ }
+
+ /**
+ * 支付
+ * @return HasOne
+ */
+ public function pay()
+ {
+ return $this->hasOne(Pay::class, 'out_trade_no', 'out_trade_no');
+ }
+
+ /**
+ * 日志
+ */
+ public function orderLog()
+ {
+ return $this->hasMany(OrderLog::class, 'order_id', 'order_id');
+ }
+
+ /**
+ * 自提点
+ * @return HasOne
+ */
+ public function store()
+ {
+ return $this->hasOne(Store::class, 'store_id', 'take_store_id');
+ }
+
+ /**
+ * 包裹
+ * @return hasMany
+ */
+ public function orderDelivery()
+ {
+ return $this->hasMany(OrderDelivery::class, 'order_id', 'order_id');
+ }
+
+ /**
+ * 优惠表
+ * @return HasOne
+ */
+ public function shopOrderDiscount()
+ {
+ return $this->hasOne(OrderDiscounts::class, 'order_id', 'order_id');
+ }
+
+ /**
+ * 优惠表
+ * @return hasMany
+ */
+ public function orderDiscount()
+ {
+ return $this->hasMany(OrderDiscounts::class, 'order_id', 'order_id');
+ }
+
+ /**
+ * 发票
+ * @return HasOne
+ */
+ public function invoice()
+ {
+ return $this->hasOne(Invoice::class, 'id', 'invoice_id');
+ }
+
+ /**
+ * 来源渠道
+ * @param $value
+ * @param $data
+ * @return mixed|string|void
+ */
+ public function getOrderFromNameAttr($value, $data)
+ {
+ if (empty($data[ 'order_from' ]))
+ return '';
+ $order_from_list = ChannelDict::getType();
+ $from_event_list = array_filter(event('OrderFromList')) ?? [];
+ foreach ($from_event_list as $item) {
+ $order_from_list = array_merge($order_from_list, $item);
+ }
+ return $order_from_list[ $data[ 'order_from' ] ] ?? '';
+ }
+
+ /**
+ * 订单类型
+ * @param $value
+ * @param $data
+ * @return mixed|string
+ */
+ public function getOrderTypeNameAttr($value, $data)
+ {
+ if (empty($data[ 'order_type' ]))
+ return '';
+// return OrderDict::getOrderType($data['order_type']) ?? '';
+ }
+ /**
+ * 订单类型
+ * @param $value
+ * @param $data
+ * @return mixed|string
+ */
+ public function getActivityTypeNameAttr($value, $data)
+ {
+ return OrderDict::getOrderActiveTypeName($data['activity_type']);
+ }
+
+ /**
+ * 订单状态
+ * @param $value
+ * @param $data
+ * @return mixed|string
+ */
+ public function getStatusNameAttr($value, $data)
+ {
+ if (empty($data[ 'status' ]))
+ return '';
+ return OrderDict::getStatus($data[ 'status' ],$data['delivery_type'])?? '';
+ }
+
+ /**
+ * 配送方式
+ * @param $value
+ * @param $data
+ * @return mixed|string
+ */
+ public function getDeliveryTypeNameAttr($value, $data)
+ {
+ if (empty($data[ 'delivery_type' ]))
+ return '';
+ return OrderDeliveryDict::getType()[ $data[ 'delivery_type' ] ] ?? '';
+ }
+
+ /**
+ * 搜索器:订单编号
+ * @param $value
+ * @param $data
+ */
+ public function searchOrderNoAttr($query, $value, $data)
+ {
+ if ($value != '') {
+ $query->where("order_no", "like", "%$value%");
+ }
+ }
+
+ /**
+ * 搜索器:订单内容
+ * @param $value
+ * @param $data
+ */
+ public function searchBodyAttr($query, $value, $data)
+ {
+ if ($value != '') {
+ $query->where("body", "like", "%$value%");
+ }
+ }
+
+ /**
+ * 搜索器:订单状态
+ * @param $value
+ * @param $data
+ */
+ public function searchStatusAttr($query, $value, $data)
+ {
+ if ($value) {
+ $query->where("status", $value);
+ }
+ }
+
+
+ /**
+ * 搜索器:营销类型
+ * @param $value
+ * @param $data
+ */
+ public function searchActivityTypeAttr($query, $value, $data)
+ {
+ if ($value) {
+ $query->where("activity_type", $value);
+ }
+ }
+
+
+ /**
+ * 连表搜索器
+ * @param $query
+ * @param $value
+ * @param $data
+ */
+ public function searchJoinStatusAttr($query, $value, $data)
+ {
+ if ($data[ 'status' ]) {
+ $query->where("order.status", $data[ 'status' ]);
+ }
+ }
+
+ /**
+ * 支付时间搜索器
+ * @param Query $query
+ * @param $value
+ * @param $data
+ */
+ public function searchPayTimeAttr(Query $query, $value, $data)
+ {
+ $start_time = empty($value[ 0 ]) ? 0 : strtotime($value[ 0 ]);
+ $end_time = empty($value[ 1 ]) ? 0 : strtotime($value[ 1 ]);
+ if ($start_time > 0 && $end_time > 0) {
+ $query->whereBetweenTime('pay_time', $start_time, $end_time);
+ } else if ($start_time > 0 && $end_time == 0) {
+ $query->where([ [ 'pay_time', '>=', $start_time ] ]);
+ } else if ($start_time == 0 && $end_time > 0) {
+ $query->where([ [ 'pay_time', '<=', $end_time ] ]);
+ }
+ }
+
+ /**
+ * 支付时间搜索器
+ * @param Query $query
+ * @param $value
+ * @param $data
+ */
+ public function searchJoinPayTimeAttr(Query $query, $value, $data)
+ {
+ $start_time = empty($data[ 'pay_time' ][ 0 ]) ? 0 : strtotime($data[ 'pay_time' ][ 0 ]);
+ $end_time = empty($data[ 'pay_time' ][ 1 ]) ? 0 : strtotime($data[ 'pay_time' ][ 1 ]);
+ if ($start_time > 0 && $end_time > 0) {
+ $query->whereBetweenTime('order.pay_time', $start_time, $end_time);
+ } else if ($start_time > 0 && $end_time == 0) {
+ $query->where([ [ 'order.pay_time', '>=', $start_time ] ]);
+ } else if ($start_time == 0 && $end_time > 0) {
+ $query->where([ [ 'order.pay_time', '<=', $end_time ] ]);
+ }
+ }
+
+ /**
+ * 创建时间搜索器
+ * @param Query $query
+ * @param $value
+ * @param $data
+ */
+ public function searchCreateTimeAttr(Query $query, $value, $data)
+ {
+ $start_time = empty($value[ 0 ]) ? 0 : strtotime($value[ 0 ]);
+ $end_time = empty($value[ 1 ]) ? 0 : strtotime($value[ 1 ]);
+ if ($start_time > 0 && $end_time > 0) {
+ $query->whereBetweenTime('order.create_time', $start_time, $end_time);
+ } else if ($start_time > 0 && $end_time == 0) {
+ $query->where([ [ 'order.create_time', '>=', $start_time ] ]);
+ } else if ($start_time == 0 && $end_time > 0) {
+ $query->where([ [ 'order.create_time', '<=', $end_time ] ]);
+ }
+ }
+
+ /**
+ * 搜索器:订单状态
+ * @param $value
+ * @param $data
+ */
+ public function searchSearchTypeAttr($query, $value, $data)
+ {
+ if ($value && isset($data[ 'search_name' ]) && $data[ 'search_name' ] != '') {
+ $search_name = $this->handelSpecialCharacter($data[ 'search_name' ]);
+ if ($value == 'order_no') $query->where("order_no", "like", "%$search_name%");
+ if ($value == 'out_trade_no') $query->where("order.out_trade_no", "like", "%$search_name%");
+ if ($value == 'goods_name') $query->where("order.body", "like", "%$search_name%");
+ }
+ }
+
+ /**
+ * 搜索器:订单状态
+ * @param $value
+ * @param $data
+ */
+ public function searchOrderFromAttr($query, $value, $data)
+ {
+ if ($value) {
+ $query->where("order_from", $value);
+ }
+ }
+
+ /**
+ * 搜索器:收货人|收货人手机号
+ * @param $value
+ * @param $data
+ */
+ public function searchKeywordAttr($query, $value, $data)
+ {
+ if ($value != '') {
+ $query->whereLike("taker_name|taker_mobile", "%" . $this->handelSpecialCharacter($value) . "%");
+ }
+ }
+}
diff --git a/niucloud/addon/shop/app/model/order/OrderBatchDelivery.php b/niucloud/addon/shop/app/model/order/OrderBatchDelivery.php
new file mode 100644
index 000000000..36938bdf8
--- /dev/null
+++ b/niucloud/addon/shop/app/model/order/OrderBatchDelivery.php
@@ -0,0 +1,137 @@
+ 'timestamp',
+ ];
+ // 设置json类型字段
+ protected $json = [ 'data' ];
+
+ // 设置JSON数据返回数组
+ protected $jsonAssoc = true;
+
+ /**
+ * 管理员
+ * @return \think\model\relation\HasOne
+ */
+ public function user()
+ {
+ return $this->hasOne(SysUser::class, 'uid', 'main_id');
+ }
+
+ /**
+ * 状态
+ * @param $value
+ * @param $data
+ * @return string
+ */
+ public function getStatusNameAttr($value, $data)
+ {
+ if (empty($data[ 'status' ])) return '';
+ return OrderBatchDeliveryDict::getStatus()[ $data[ 'status' ] ] ?? '';
+ }
+
+ /**
+ * 操作类型
+ * @return mixed|string
+ */
+ public function getTypeNameAttr($value, $data)
+ {
+ if (empty($data[ 'type' ]))
+ return '';
+ return OrderBatchDeliveryDict::getType()[ $data[ 'type' ] ] ?? '';
+ }
+
+
+ /**
+ * 退款状态搜索
+ * @param $query
+ * @param $value
+ * @param $data
+ */
+ public function searchStatusAttr($query, $value, $data)
+ {
+ if ($value) {
+ $query->where("status", $value);
+ }
+ }
+
+ /**
+ * 类型搜索
+ * @param $query
+ * @param $value
+ * @param $data
+ */
+ public function searchTypeAttr($query, $value, $data)
+ {
+ if ($value) {
+ $query->where("type", $value);
+ }
+ }
+
+ /**
+ * 操作人搜索
+ * @param $query
+ * @param $value
+ * @param $data
+ */
+ public function searchMainIdAttr($query, $value, $data)
+ {
+ if ($value) {
+ $query->where("main_id", $value);
+ }
+ }
+
+ /**
+ * 创建时间搜索器
+ * @param $query
+ * @param $value
+ * @param $data
+ */
+ public function searchCreateTimeAttr($query, $value, $data)
+ {
+ $start_time = empty($value[ 0 ]) ? 0 : strtotime($value[ 0 ]);
+ $end_time = empty($value[ 1 ]) ? 0 : strtotime($value[ 1 ]);
+ if ($start_time > 0 && $end_time > 0) {
+ $query->whereBetweenTime('create_time', $start_time, $end_time);
+ } else if ($start_time > 0 && $end_time == 0) {
+ $query->where([ [ 'create_time', '>=', $start_time ] ]);
+ } else if ($start_time == 0 && $end_time > 0) {
+ $query->where([ [ 'create_time', '<=', $end_time ] ]);
+ }
+ }
+
+}
diff --git a/niucloud/addon/shop/app/model/order/OrderDelivery.php b/niucloud/addon/shop/app/model/order/OrderDelivery.php
new file mode 100644
index 000000000..9cbf95031
--- /dev/null
+++ b/niucloud/addon/shop/app/model/order/OrderDelivery.php
@@ -0,0 +1,59 @@
+hasOne(Company::class, 'company_id', 'express_company_id');
+ }
+
+ public function getExpressCompanyNameAttr($value, $data)
+ {
+ return (new Company())->find($data['express_company_id'])->company_name ?? '';
+ }
+
+ public function orderGoods()
+ {
+ return $this->hasMany(OrderGoods::class, 'delivery_id', 'id');
+ }
+ public function getThirdDeliveryNameAttr($value, $data)
+ {
+ return DeliveryLocalDict::getType($data['third_delivery'])['name'] ?? "";
+ }
+}
diff --git a/niucloud/addon/shop/app/model/order/OrderDiscounts.php b/niucloud/addon/shop/app/model/order/OrderDiscounts.php
new file mode 100644
index 000000000..b3c3d6f97
--- /dev/null
+++ b/niucloud/addon/shop/app/model/order/OrderDiscounts.php
@@ -0,0 +1,47 @@
+hasOne(Order::class, 'order_id', 'order_id');
+ }
+
+}
diff --git a/niucloud/addon/shop/app/model/order/OrderGoods.php b/niucloud/addon/shop/app/model/order/OrderGoods.php
new file mode 100644
index 000000000..6c4910316
--- /dev/null
+++ b/niucloud/addon/shop/app/model/order/OrderGoods.php
@@ -0,0 +1,220 @@
+ 'timestamp',
+ ];
+
+
+ // 设置json类型字段
+ protected $json = ['extend'];
+
+ // 设置JSON数据返回数组
+ protected $jsonAssoc = true;
+
+ /**
+ * 定义软删除标记字段.
+ * @var string
+ */
+ protected $deleteTime = 'delete_time';
+
+ protected $defaultSoftDelete = 0;
+
+ /**
+ * 包裹
+ * @return HasOne
+ */
+ public function orderDelivery()
+ {
+ return $this->hasOne(OrderDelivery::class, 'id', 'delivery_id');
+ }
+
+ /**
+ * 商品
+ * @return HasOne
+ */
+ public function goods()
+ {
+ return $this->hasOne(Goods::class, 'goods_id', 'goods_id');
+ }
+ /**
+ * 商品
+ * @return HasOne
+ */
+ public function sku()
+ {
+ return $this->hasOne(GoodsSku::class, 'sku_id', 'sku_id');
+ }
+
+ /**
+ * 订单主表
+ * @return BaseModel|HasOne
+ */
+ public function orderMain()
+ {
+ return $this->hasOne(Order::class, 'order_id', 'order_id');
+ }
+
+ /**
+ * 会员
+ * @return HasOne
+ */
+ public function member()
+ {
+ return $this->hasOne(Member::class, 'member_id', 'member_id');
+ } /**
+ * 会员
+ * @return HasOne
+ */
+ public function deliveryInfo()
+ {
+ return $this->hasOne(OrderDelivery::class, 'id', 'delivery_id')->append(['express_company_name']);
+ }
+
+ /**
+ * 缩略图生成-大图
+ * @param $value
+ * @param $data
+ * @return array|mixed
+ * @throws Exception
+ */
+ public function getGoodsImageThumbBigAttr($value, $data)
+ {
+ if (!empty($data['goods_image'])) {
+ return get_thumb_images($data['goods_image'], FileDict::BIG);
+ }
+ return '';
+ }
+
+ /**
+ * 缩略图生成-中图
+ * @param $value
+ * @param $data
+ * @return array|mixed
+ * @throws Exception
+ */
+ public function getGoodsImageThumbMidAttr($value, $data)
+ {
+ if (!empty($data['goods_image'])) {
+ return get_thumb_images($data['goods_image'], FileDict::MID);
+ }
+ return '';
+ }
+
+ /**
+ * 缩略图生成-小图
+ * @param $value
+ * @param $data
+ * @return array|mixed
+ * @throws Exception
+ */
+ public function getGoodsImageThumbSmallAttr($value, $data)
+ {
+ if (!empty($data['goods_image'])) {
+ return get_thumb_images($data['goods_image'], FileDict::SMALL);
+ }
+ return '';
+ }
+
+ /**
+ * 缩略图生成-中图
+ * @param $value
+ * @param $data
+ * @return array|mixed
+ * @throws Exception
+ */
+ public function getSkuImageThumbMidAttr($value, $data)
+ {
+ if (!empty($data['sku_image'])) {
+ return get_thumb_images($data['sku_image'], FileDict::MID);
+ }
+ return '';
+ }
+
+ /**
+ * 转化发货状态
+ */
+ public function getDeliveryStatusNameAttr($value, $data)
+ {
+ if (!empty($data['delivery_status'])) {
+ return OrderDeliveryDict::getStatus($data['delivery_status']);
+ }
+ return '';
+ }
+
+ /**
+ * 转化订单项状态
+ */
+ public function getStatusNameAttr($value, $data)
+ {
+ if (!empty($data['status'])) {
+ return OrderGoodsDict::getRefundStatus($data['status']);
+ }
+ return '';
+ }
+
+ /**
+ * 转化订单项商品类型
+ */
+ public function getGoodsTypeNameAttr($value, $data)
+ {
+ if (!empty($data['goods_type'])) {
+ return GoodsDict::getType($data['goods_type'])['name'];
+ }
+ return '';
+ }
+
+ public function getImpulseBuyInfoAttr($value, $data)
+ {
+ if(!empty($data['extend']) && isset($data['extend']['is_impulse_buy']) && $data['extend']['is_impulse_buy'] == 1){
+ $impulse_buy_price = $data['extend']['impulse_buy_price']/$data['extend']['impulse_buy_goods_num'];
+ $is_impulse_buy = 1;
+ }
+ return [
+ 'is_impulse_buy'=>$is_impulse_buy ?? 0 ,
+ 'impulse_buy_price'=>$impulse_buy_price ?? 0 ,
+ ];
+ }
+
+}
diff --git a/niucloud/addon/shop/app/model/order/OrderLog.php b/niucloud/addon/shop/app/model/order/OrderLog.php
new file mode 100644
index 000000000..3427d9696
--- /dev/null
+++ b/niucloud/addon/shop/app/model/order/OrderLog.php
@@ -0,0 +1,84 @@
+ 'timestamp'
+ ];
+
+ /**
+ * 来源渠道
+ * @param $value
+ * @param $data
+ * @return mixed|string|void
+ */
+ public function getMainTypeNameAttr($value, $data)
+ {
+ if (empty($data[ 'main_type' ]))
+ return '';
+ return OrderLogDict::getMainType() [ $data[ 'main_type' ] ] ?? '';
+ }
+
+ /**
+ * 操作类型转换
+ * @param $value
+ * @param $data
+ * @return mixed|string|void
+ */
+ public function getTypeNameAttr($value, $data)
+ {
+ if (empty($data[ 'type' ]))
+ return '';
+ return OrderDict::getActionType() [ $data[ 'type' ] ] ?? '';
+ }
+
+ /**
+ * 获取操作人
+ * @param $value
+ * @param $data
+ */
+ public function getMainNameAttr($value, $data)
+ {
+ $main_name = '';
+ if (!empty($data[ 'main_type' ]) && !empty($data[ 'main_id' ])) {
+ if ($data[ 'main_type' ] == OrderLogDict::MEMBER) $main_name = ( Member::find([ 'member_id' => $data[ 'main_id' ] ]) )->nickname;
+ if ($data[ 'main_type' ] == OrderLogDict::STORE) $main_name = ( SysUser::find([ 'uid' => $data[ 'main_id' ] ]) )->username;
+ }
+ return $main_name;
+ }
+}
diff --git a/niucloud/addon/shop/app/model/order/OrderRefund.php b/niucloud/addon/shop/app/model/order/OrderRefund.php
new file mode 100644
index 000000000..572e8bfdc
--- /dev/null
+++ b/niucloud/addon/shop/app/model/order/OrderRefund.php
@@ -0,0 +1,172 @@
+ 'timestamp',
+ ];
+
+ // 设置json类型字段
+ protected $json = ['delivery', 'voucher', 'refund_address'];
+
+ // 设置JSON数据返回数组
+ protected $jsonAssoc = true;
+
+ /**
+ * 定义软删除标记字段.
+ * @var string
+ */
+ protected $deleteTime = 'delete_time';
+
+ protected $defaultSoftDelete = 0;
+
+ /**
+ * 关联订单项
+ * @return HasOne
+ */
+ public function orderGoods()
+ {
+ return $this->hasOne(OrderGoods::class, 'order_goods_id', 'order_goods_id');
+ }
+
+ /**
+ * 订单主表
+ * @return BaseModel|HasOne
+ */
+ public function orderMain()
+ {
+ return $this->hasOne(Order::class, 'order_id', 'order_id');
+ }
+
+ /**
+ * 关联退款日志表
+ * @return \think\model\relation\HasMany
+ */
+ public function refundLog()
+ {
+ return $this->hasMany(OrderRefundLog::class, 'order_refund_no', 'order_refund_no');
+ }
+
+ /**
+ * 关联会员表
+ */
+ public function member()
+ {
+ return $this->hasOne(Member::class, 'member_id', 'member_id');
+ }
+
+ /**
+ * 关联退款表
+ */
+ public function payRefund()
+ {
+ return $this->hasOne(Refund::class, 'refund_no', 'refund_no');
+ }
+
+ /**
+ * 获取退款状态
+ * @param $value
+ * @param $data
+ * @return array|mixed|string
+ */
+ public function getStatusNameAttr($value, $data)
+ {
+ if ($data['status']) {
+ return OrderRefundDict::getRefundStatus($data['status']);
+ }
+ }
+
+ /**
+ * 退款类型
+ * @param $value
+ * @param $data
+ * @return array|mixed|string
+ */
+ public function getRefundTypeNameAttr($value, $data)
+ {
+ if ($data['refund_type']) {
+ return OrderRefundDict::getRefundType($data['refund_type']);
+ }
+ }
+
+ /**
+ * 退款编号搜索
+ * @param $query
+ * @param $value
+ * @param $data
+ */
+ public function searchOrderRefundNoAttr($query, $value, $data)
+ {
+ if ($value != '') {
+ $query->where("order_refund_no", "like", "%" . $this->handelSpecialCharacter($value) . "%");
+ }
+ }
+
+ /**
+ * 退款状态搜索
+ * @param $query
+ * @param $value
+ * @param $data
+ */
+ public function searchStatusAttr($query, $value, $data)
+ {
+ if ($value) {
+ $query->where("status", $value);
+ }
+ }
+
+ /**
+ * 创建时间搜索器
+ * @param $query
+ * @param $value
+ * @param $data
+ */
+ public function searchCreateTimeAttr($query, $value, $data)
+ {
+ $start_time = empty($value[0]) ? 0 : strtotime($value[0]);
+ $end_time = empty($value[1]) ? 0 : strtotime($value[1]);
+ if ($start_time > 0 && $end_time > 0) {
+ $query->whereBetweenTime('create_time', $start_time, $end_time);
+ } else if ($start_time > 0 && $end_time == 0) {
+ $query->where([['create_time', '>=', $start_time]]);
+ } else if ($start_time == 0 && $end_time > 0) {
+ $query->where([['create_time', '<=', $end_time]]);
+ }
+ }
+}
diff --git a/niucloud/addon/shop/app/model/order/OrderRefundLog.php b/niucloud/addon/shop/app/model/order/OrderRefundLog.php
new file mode 100644
index 000000000..ec7d032ac
--- /dev/null
+++ b/niucloud/addon/shop/app/model/order/OrderRefundLog.php
@@ -0,0 +1,82 @@
+ $data[ 'main_id' ] ]) )->nickname;
+ if ($data[ 'main_type' ] == OrderRefundLogDict::STORE) $main_name = ( SysUser::find([ 'uid' => $data[ 'main_id' ] ]) )->username;
+ }
+ return $main_name;
+ }
+
+}
diff --git a/niucloud/addon/shop/app/model/shop_address/ShopAddress.php b/niucloud/addon/shop/app/model/shop_address/ShopAddress.php
new file mode 100644
index 000000000..ca510a870
--- /dev/null
+++ b/niucloud/addon/shop/app/model/shop_address/ShopAddress.php
@@ -0,0 +1,60 @@
+where("mobile", "like", "%" . $this->handelSpecialCharacter($value) . "%");
+ }
+ }
+
+ /**
+ * 搜索器:商家地址库地址
+ * @param $value
+ * @param $data
+ */
+ public function searchFullAddressAttr($query, $value, $data)
+ {
+ if ($value != '') {
+ $query->where("full_address", "like", "%" . $this->handelSpecialCharacter($value) . "%");
+ }
+ }
+
+}
diff --git a/niucloud/addon/shop/app/service/admin/StatService.php b/niucloud/addon/shop/app/service/admin/StatService.php
new file mode 100644
index 000000000..9c7e1dacd
--- /dev/null
+++ b/niucloud/addon/shop/app/service/admin/StatService.php
@@ -0,0 +1,56 @@
+getStat($start_date, $end_date);
+ }
+
+ /**
+ * 获取区间统计数据
+ * @param string $start_date
+ * @param string $end_date
+ * @return array|null
+ */
+ public function getStatData(string $start_date, string $end_date)
+ {
+ return ( new CoreStatService() )->getStatData($start_date, $end_date);
+ }
+
+ /**
+ * 获取某天统计数据
+ * @param string $start_date
+ * @param string $end_date
+ * @return array|null
+ */
+ public function getHourStatData(string $date)
+ {
+ return ( new CoreStatService() )->getHourStatData($date);
+ }
+}
diff --git a/niucloud/addon/shop/app/service/admin/delivery/CompanyService.php b/niucloud/addon/shop/app/service/admin/delivery/CompanyService.php
new file mode 100644
index 000000000..412b54b2b
--- /dev/null
+++ b/niucloud/addon/shop/app/service/admin/delivery/CompanyService.php
@@ -0,0 +1,108 @@
+model = new Company();
+ }
+
+ /**
+ * 获取物流公司分页列表
+ * @param array $where
+ * @return array
+ */
+ public function getPage(array $where = [])
+ {
+ $field = 'company_id,company_name,logo,url,express_no,express_no_electronic_sheet,electronic_sheet_switch,print_style,exp_type,create_time,kd100_express_no';
+ $order = 'create_time desc';
+
+ $search_model = $this->model->where([ [ 'company_id', '>', 0 ] ])->withSearch([ "company_name", 'electronic_sheet_switch' ], $where)->field($field)->order($order);
+ $list = $this->pageQuery($search_model);
+ return $list;
+ }
+
+ /**
+ * 获取物流公司列表
+ * @param array $where
+ * @param string $field
+ * @return array
+ */
+ public function getList(array $where = [], $field = 'company_id,company_name,logo,url,express_no,express_no_electronic_sheet,electronic_sheet_switch,print_style,exp_type,create_time')
+ {
+ $order = 'create_time desc';
+
+ return $this->model->where([ [ 'company_id', '>', 0 ] ])->withSearch([ "company_name", 'electronic_sheet_switch' ], $where)->field($field)->order($order)->select()->toArray();
+ }
+
+ /**
+ * 获取物流公司信息
+ * @param int $id
+ * @return array
+ */
+ public function getInfo(int $id)
+ {
+ $field = 'company_id,company_name,logo,url,express_no,express_no_electronic_sheet,electronic_sheet_switch,print_style,exp_type,create_time,kd100_express_no';
+
+ $info = $this->model->field($field)->where([ [ 'company_id', '=', $id ] ])->findOrEmpty()->toArray();
+ return $info;
+ }
+
+ /**
+ * 添加物流公司
+ * @param array $data
+ * @return mixed
+ */
+ public function add(array $data)
+ {
+ $data[ 'create_time' ] = time();
+ $res = $this->model->create($data);
+ return $res->company_id;
+ }
+
+ /**
+ * 物流公司编辑
+ * @param int $id
+ * @param array $data
+ * @return bool
+ */
+ public function edit(int $id, array $data)
+ {
+ $data[ 'update_time' ] = time();
+ $this->model->where([ [ 'company_id', '=', $id ] ])->update($data);
+ return true;
+ }
+
+ /**
+ * 删除物流公司
+ * @param int $id
+ * @return bool
+ */
+ public function del(int $id)
+ {
+ $res = $this->model->where([ [ 'company_id', '=', $id ] ])->delete();
+ return $res;
+ }
+
+}
diff --git a/niucloud/addon/shop/app/service/admin/delivery/DeliverService.php b/niucloud/addon/shop/app/service/admin/delivery/DeliverService.php
new file mode 100644
index 000000000..96e6a16c9
--- /dev/null
+++ b/niucloud/addon/shop/app/service/admin/delivery/DeliverService.php
@@ -0,0 +1,94 @@
+model = new Deliver();
+ }
+
+ /**
+ * 获取配送员列表
+ * @param array $where
+ * @return array
+ */
+ public function getPage(array $where = [])
+ {
+ $field = 'deliver_id,deliver_name,deliver_mobile';
+ $order = 'deliver_id desc';
+
+ $search_model = $this->model->where([['deliver_id', '>', 0] ])->withSearch(["deliver_name", "deliver_mobile"], $where)->field($field)->order($order);
+ $list = $this->pageQuery($search_model);
+ return $list;
+ }
+
+ /**
+ * 获取详情
+ * @param int $id
+ * @return array
+ */
+ public function getInfo(int $id)
+ {
+ $field = 'deliver_id,deliver_name,deliver_mobile';
+ $info = $this->model->field($field)->where([['deliver_id', '=', $id] ])->findOrEmpty()->toArray();
+ return $info;
+ }
+
+ /**
+ * 添加
+ * @param array $data
+ * @return mixed
+ */
+ public function add(array $data)
+ {
+ $data['create_time'] = time();
+ $res = $this->model->create($data);
+ return $res->deliver_id;
+ }
+
+ /**
+ * 编辑
+ * @param int $id
+ * @param array $data
+ * @return bool
+ */
+ public function edit(int $id, array $data)
+ {
+ $data['modify_time'] = time();
+ $this->model->where([['deliver_id', '=', $id] ])->update($data);
+ return true;
+ }
+
+ /**
+ * 删除
+ * @param int $id
+ * @return bool
+ */
+ public function del(int $id)
+ {
+ $res = $this->model->where([['deliver_id', '=', $id] ])->delete();
+ return $res;
+ }
+
+}
diff --git a/niucloud/addon/shop/app/service/admin/delivery/DeliverySearchConfigService.php b/niucloud/addon/shop/app/service/admin/delivery/DeliverySearchConfigService.php
new file mode 100644
index 000000000..b17825e4f
--- /dev/null
+++ b/niucloud/addon/shop/app/service/admin/delivery/DeliverySearchConfigService.php
@@ -0,0 +1,44 @@
+setDeliverySearchConfig($data);
+ }
+
+ /**
+ * 获取物流跟踪查询配置
+ * @return array
+ */
+ public function getConfig()
+ {
+ return $info = ( new CoreConfigService() )->getDeliverySearchConfig();
+ }
+}
diff --git a/niucloud/addon/shop/app/service/admin/delivery/DeliveryService.php b/niucloud/addon/shop/app/service/admin/delivery/DeliveryService.php
new file mode 100644
index 000000000..dfdb26ed9
--- /dev/null
+++ b/niucloud/addon/shop/app/service/admin/delivery/DeliveryService.php
@@ -0,0 +1,61 @@
+core_delivery_config_service = new CoreDeliveryService();
+ }
+
+ /**
+ * 设置名称
+ * @param $key
+ * @param $data
+ * @return array|true
+ */
+ public function setConfig($data)
+ {
+ return $this->core_delivery_config_service->setConfig('SHOP_DELIVERY_CONFIG', $data);
+ }
+
+ /**
+ * 获取配置信息
+ */
+ public function getDeliveryConfigList()
+ {
+ return $this->core_delivery_config_service->getDeliveryList();
+ }
+
+ /**
+ * 获取配置信息
+ */
+ public function getDeliveryList()
+ {
+ return $this->core_delivery_config_service->getDeliveryConfig();
+ }
+
+}
diff --git a/niucloud/addon/shop/app/service/admin/delivery/ElectronicSheetService.php b/niucloud/addon/shop/app/service/admin/delivery/ElectronicSheetService.php
new file mode 100644
index 000000000..3981cc92d
--- /dev/null
+++ b/niucloud/addon/shop/app/service/admin/delivery/ElectronicSheetService.php
@@ -0,0 +1,234 @@
+model = new ElectronicSheet();
+ }
+
+ /**
+ * 获取电子面单分页列表
+ * @param array $where
+ * @param string $field
+ * @return array
+ * @throws \think\db\exception\DbException
+ */
+ public function getPage(array $where = [], $field = 'id,template_name,express_company_id,customer_name,customer_pwd,send_site,send_staff,month_code,pay_type,is_notice,status,exp_type,print_style,is_default,create_time')
+ {
+ $order = 'is_default desc,create_time desc';
+
+ $search_model = $this->model->where([ [ 'electronic_sheet.id', '>', 0 ] ])
+ ->withSearch([ 'id', 'template_name', 'express_company_id', 'pay_type', 'is_notice', 'status', 'is_default' ], $where)
+ ->field($field)
+ ->withJoin([
+ 'company' => [ 'company_name', 'express_no_electronic_sheet' ]
+ ])
+ ->order($order)->append([ 'pay_type_name' ]);
+ $list = $this->pageQuery($search_model);
+ return $list;
+ }
+
+ /**
+ * 获取电子面单列表
+ * @param array $where
+ * @param array $field
+ * @return array
+ */
+ public function getList(array $where = [], $field = 'id,template_name,express_company_id,customer_name,customer_pwd,send_site,send_staff,month_code,pay_type,is_notice,status,exp_type,print_style,is_default,create_time')
+ {
+ $order = 'is_default desc,create_time desc';
+ return $this->model->where([ [ 'id', '>', 0 ] ])->withSearch([ 'id', 'template_name', 'express_company_id', 'pay_type', 'is_notice', 'status', 'is_default' ], $where)->field($field)->order($order)->select()->toArray();
+ }
+
+ /**
+ * 获取电子面单信息
+ * @param int $id
+ * @return array
+ */
+ public function getInfo(int $id)
+ {
+ $field = 'id,template_name,express_company_id,customer_name,customer_pwd,send_site,send_staff,month_code,pay_type,is_notice,status,exp_type,print_style,is_default';
+
+ $info = $this->model->field($field)->where([ [ 'id', '=', $id ] ])->findOrEmpty()->toArray();
+ return $info;
+ }
+
+ /**
+ * 添加电子面单
+ * @param array $data
+ * @return mixed
+ */
+ public function add(array $data)
+ {
+ // 将同类型页面的默认值改为0,默认页面只有一个
+ if (!empty($data[ 'is_default' ])) {
+ $this->model->where([ [ 'id', '>', 0 ] ])->update([ 'is_default' => 0 ]);
+ }
+
+ $interface_data = [
+ 'kdbird'=>[
+ 'customer_name'=>$data['customer_pwd'],
+ 'customer_pwd'=>$data['customer_pwd'],
+ 'send_site'=>$data['send_site'],
+ 'send_staff'=>$data['send_staff'],
+ 'month_code'=>$data['month_code'],
+ 'pay_type'=>$data['pay_type'],
+ 'is_notice'=>$data['is_notice'],
+ 'print_style'=>$data['print_style']
+ ],
+// 'kd100'=>[
+// 'customer_name'=>$data['kd100_customer_pwd'],
+// 'customer_pwd'=>$data['kd100_customer_pwd'],
+// 'send_site'=>$data['kd100_send_site'],
+// 'send_staff'=>$data['kd100_send_staff'],
+// 'month_code'=>$data['kd100_month_code'],
+// 'pay_type'=>$data['kd100_pay_type'],
+// ]
+ ];
+ $data['interface_data'] = json_encode($interface_data);
+ $res = $this->model->create($data);
+ return $res->id;
+ }
+
+ /**
+ * 电子面单编辑
+ * @param int $id
+ * @param array $data
+ * @return bool
+ */
+ public function edit(int $id, array $data)
+ {
+ // 将同类型页面的默认值改为0,默认页面只有一个
+ if (!empty($data[ 'is_default' ])) {
+ $this->model->where([ [ 'id', '>', 0 ] ])->update([ 'is_default' => 0 ]);
+ }
+
+ $interface_data = [
+ 'kdbird'=>[
+ 'customer_name'=>$data['customer_pwd'],
+ 'customer_pwd'=>$data['customer_pwd'],
+ 'send_site'=>$data['send_site'],
+ 'send_staff'=>$data['send_staff'],
+ 'month_code'=>$data['month_code'],
+ 'pay_type'=>$data['pay_type'],
+ 'is_notice'=>$data['is_notice'],
+ 'print_style'=>$data['print_style']
+ ],
+// 'kd100'=>[
+// 'customer_name'=>$data['kd100_customer_pwd'],
+// 'customer_pwd'=>$data['kd100_customer_pwd'],
+// 'send_site'=>$data['kd100_send_site'],
+// 'send_staff'=>$data['kd100_send_staff'],
+// 'month_code'=>$data['kd100_month_code'],
+// 'pay_type'=>$data['kd100_pay_type'],
+// ]
+ ];
+ $data['interface_data'] = json_encode($interface_data);
+ $this->model->where([ [ 'id', '=', $id ] ])->update($data);
+ return true;
+ }
+
+ /**
+ * 删除电子面单
+ * @param int $id
+ * @return bool
+ */
+ public function del(int $id)
+ {
+ $model = $this->model->where([ [ 'id', '=', $id ] ])->find();
+ $res = $model->delete();
+ return $res;
+ }
+
+ /**
+ * 设置默认电子面单模板
+ * @param int $id
+ * @return bool
+ */
+ public function setDefault(int $id)
+ {
+ try {
+ $info = $this->getInfo($id);
+ if (empty($info)) {
+ return false;
+ }
+ Db::startTrans();
+ $this->model->where([ [ 'id', '>', 0 ] ])->update([ 'is_default' => 0, 'update_time' => time() ]);
+ $this->model->where([ [ 'id', '=', $id ] ])->update([ 'is_default' => 1, 'update_time' => time() ]);
+ Db::commit();
+ return true;
+ } catch (Exception $e) {
+ Db::rollback();
+ throw new AdminException($e->getMessage());
+ }
+ return true;
+ }
+
+ /**
+ * 设置 电子面单配置
+ * @param $data
+ * @return bool
+ */
+ public function setConfig($data)
+ {
+ ( new CoreElectronicSheetService() )->setElectronicSheetConfig( $data);
+ return true;
+ }
+
+ /**
+ * 获取 电子面单设置
+ * @return array|mixed
+ */
+ public function getConfig()
+ {
+ return ( new CoreElectronicSheetService() )->getElectronicSheetConfig();
+ }
+
+ /**
+ * 获取邮费支付方式类型
+ * @return array|mixed|string
+ */
+ public function getPayType()
+ {
+ return ElectronicSheetDict::getPayType();
+ }
+
+ /**
+ * 打印电子面单
+ * @param array $data
+ * @return mixed
+ */
+ public function printElectronicSheet($data = [])
+ {
+ $res = ( new CoreElectronicSheetService() )->printElectronicSheet($data);
+ return $res;
+ }
+
+}
diff --git a/niucloud/addon/shop/app/service/admin/delivery/LocalService.php b/niucloud/addon/shop/app/service/admin/delivery/LocalService.php
new file mode 100644
index 000000000..5e94b37fc
--- /dev/null
+++ b/niucloud/addon/shop/app/service/admin/delivery/LocalService.php
@@ -0,0 +1,134 @@
+core_service = new CoreLocalDeliveryService();
+
+ }
+
+ /**
+ * 设置同城配送
+ * @param array $data
+ * @return mixed
+ */
+ public function setLocal(array $data)
+ {
+ (new Local())->where([['local_id', '>', 0]])->delete();
+
+ $create_res = (new Local())->create([
+ 'center' => $data['center'],
+ 'fee_type' => $data['fee_type'],
+ 'base_dist' => $data['base_dist'],
+ 'base_price' => $data['base_price'],
+ 'grad_dist' => $data['grad_dist'],
+ 'grad_price' => $data['grad_price'],
+ 'weight_start' => $data['weight_start'],
+ 'weight_unit' => $data['weight_unit'],
+ 'weight_price' => $data['weight_price'],
+ 'delivery_type' => $data['delivery_type'],
+ 'area' => $data['area'],
+
+ 'time_is_open' => $data['time_is_open'],
+ 'time_type' => $data['time_type'],
+ 'time_week' => $data['time_week'],
+ 'time_interval' => $data['time_interval'],
+ 'advance_day' => $data['advance_day'],
+ 'most_day' => $data['most_day'],
+ 'start_time' => $data['start_time'],
+ 'end_time' => $data['end_time'],
+ 'delivery_time' => $data['delivery_time'],
+ ]);
+ if (in_array(DeliveryLocalDict::DELIVERY_TYPE_THIRD, $data['delivery_type'])) {
+ $this->setThirdPartyConfig($data['third_party_config']);
+ }
+ return $create_res->local_id;
+ }
+
+ /**
+ * 获取同城配送设置
+ * @return array
+ */
+ public function getLocal()
+ {
+ $info = (new Local())->where([['local_id', '>', 0]])->findOrEmpty()->toArray();
+ $config = $this->getThirdPartyConfig();
+ $type_config = DeliveryLocalDict::getType();
+ foreach ($type_config as $type => $value) {
+ foreach ($value['encrypt_params'] as $encrypt_param) {
+ $config[$type][$encrypt_param] = !empty( $config[$type][$encrypt_param] ) ? CommonDict::ENCRYPT_STR : '';
+ }
+ }
+ $info['third_party_config'] = $config;
+ return $info;
+ }
+
+ public function getThirdTypeConfig()
+ {
+ $config = DeliveryLocalDict::getType();
+ $return = [];
+ foreach ($config as $type => $item) {
+ $return[] = [
+ 'type' => $type,
+ 'name' => $item['name']
+ ];
+ }
+ return $return;
+ }
+
+ public function getThirdPartyConfig()
+ {
+ return $this->core_service->getConfig();
+ }
+
+ public function setThirdPartyConfig($data)
+ {
+ if (empty($data)) {
+ return true;
+ }
+ $config = $this->getThirdPartyConfig();
+ $config['default'] = $data['default'] ?? $config['default'];
+ unset($data['default']);
+ foreach ($data as $type => $item) {
+ foreach ($item as $column => $v) {
+ if (empty($v) || $v == CommonDict::ENCRYPT_STR) {
+ $config[$type][$column] = $v ?? $config[$type][$column];
+ } else {
+ $config[$type][$column] = $v;
+ }
+ }
+ }
+ return $this->core_service->setConfig($config);
+ }
+
+ public function thirdDeliveryCallback($params)
+ {
+ $this->core_service->thirdDeliveryCallback($params);
+ }
+}
diff --git a/niucloud/addon/shop/app/service/admin/delivery/ShippingTemplateService.php b/niucloud/addon/shop/app/service/admin/delivery/ShippingTemplateService.php
new file mode 100644
index 000000000..15cc11fc7
--- /dev/null
+++ b/niucloud/addon/shop/app/service/admin/delivery/ShippingTemplateService.php
@@ -0,0 +1,181 @@
+create([
+ 'template_name' => $data[ 'template_name' ],
+ 'fee_type' => $data[ 'fee_type' ],
+ 'create_time' => time(),
+ 'no_delivery' => $data[ 'no_delivery' ],
+ 'is_free_shipping' => $data[ 'is_free_shipping' ]
+ ]);
+
+ $template_item = [];
+ foreach ($data[ 'area' ] as $item) {
+ $template_item[] = [
+ 'template_id' => $create_res->template_id,
+ 'city_id' => $item[ 'city_id' ],
+ 'fee_type' => $data[ 'fee_type' ],
+ 'snum' => round(floatval($item[ 'snum' ] ?? 0), 2),
+ 'sprice' => round(floatval($item[ 'sprice' ] ?? 0), 2),
+ 'xnum' => round(floatval($item[ 'xnum' ] ?? 0), 2),
+ 'xprice' => round(floatval($item[ 'xprice' ] ?? 0), 2),
+ 'fee_area_ids' => $item[ 'fee_area_ids' ] ?? '',
+ 'fee_area_names' => $item[ 'fee_area_names' ] ?? '',
+ 'no_delivery' => $data[ 'no_delivery' ],
+ 'no_delivery_area_ids' => $item[ 'no_delivery_area_ids' ] ?? '',
+ 'no_delivery_area_names' => $item[ 'no_delivery_area_names' ] ?? '',
+ 'is_free_shipping' => $data[ 'is_free_shipping' ],
+ 'free_shipping_area_ids' => $item[ 'free_shipping_area_ids' ] ?? '',
+ 'free_shipping_area_names' => $item[ 'free_shipping_area_names' ] ?? '',
+ 'free_shipping_price' => $item[ 'free_shipping_price' ] ?? 0,
+ 'free_shipping_num' => $item[ 'free_shipping_num' ] ?? 0,
+ ];
+ }
+ ( new ShippingTemplateItem() )->saveAll($template_item);
+
+ Db::commit();
+ return $create_res->template_id;
+ } catch (\Exception $e) {
+ Db::rollback();
+ throw new CommonException($e->getMessage());
+ }
+ }
+
+ /**
+ * 编辑运费模板
+ * @param array $data
+ * @return true
+ */
+ public function edit(int $template_id, array $data)
+ {
+ Db::startTrans();
+ try {
+ ( new ShippingTemplate() )->update([
+ 'template_name' => $data[ 'template_name' ],
+ 'fee_type' => $data[ 'fee_type' ],
+ 'update_time' => time(),
+ 'no_delivery' => $data[ 'no_delivery' ],
+ 'is_free_shipping' => $data[ 'is_free_shipping' ]
+ ], [ 'template_id' => $template_id ]);
+
+ ( new ShippingTemplateItem() )->where([ 'template_id' => $template_id ])->delete();
+ $template_item = [];
+ foreach ($data[ 'area' ] as $item) {
+ $template_item[] = [
+ 'template_id' => $template_id,
+ 'city_id' => $item[ 'city_id' ],
+ 'fee_type' => $data[ 'fee_type' ],
+ 'snum' => round(floatval($item[ 'snum' ] ?? 0), 2),
+ 'sprice' => round(floatval($item[ 'sprice' ] ?? 0), 2),
+ 'xnum' => round(floatval($item[ 'xnum' ] ?? 0), 2),
+ 'xprice' => round(floatval($item[ 'xprice' ] ?? 0), 2),
+ 'fee_area_ids' => $item[ 'fee_area_ids' ] ?? '',
+ 'fee_area_names' => $item[ 'fee_area_names' ] ?? '',
+ 'no_delivery' => $data[ 'no_delivery' ],
+ 'no_delivery_area_ids' => $item[ 'no_delivery_area_ids' ] ?? '',
+ 'no_delivery_area_names' => $item[ 'no_delivery_area_names' ] ?? '',
+ 'is_free_shipping' => $data[ 'is_free_shipping' ],
+ 'free_shipping_area_ids' => $item[ 'free_shipping_area_ids' ] ?? '',
+ 'free_shipping_area_names' => $item[ 'free_shipping_area_names' ] ?? '',
+ 'free_shipping_price' => $item[ 'free_shipping_price' ] ?? 0,
+ 'free_shipping_num' => $item[ 'free_shipping_num' ] ?? 0,
+ ];
+ }
+ ( new ShippingTemplateItem() )->saveAll($template_item);
+
+ Db::commit();
+ return true;
+ } catch (\Exception $e) {
+ Db::rollback();
+ throw new CommonException($e->getMessage());
+ }
+ }
+
+ /**
+ * 删除运费模板
+ * @param int $template_id
+ * @return true
+ */
+ public function delete(int $template_id)
+ {
+ if ((new Goods())->where([ ['delivery_template_id', '=', $template_id]])->count()) throw new CommonException('SHIPPING_TEMPLATE_IN_USE');
+ ( new ShippingTemplate() )->where([ 'template_id' => $template_id ])->delete();
+ ( new ShippingTemplateItem() )->where([ 'template_id' => $template_id ])->delete();
+ return true;
+ }
+
+ /**
+ * 查询运费模板列表
+ * @param array $where
+ * @return array
+ */
+ public function getPage(array $where)
+ {
+ $field = 'template_id, template_name, fee_type, create_time, no_delivery, is_free_shipping';
+ $search_model = ( new ShippingTemplate() )->where([ ['template_id', '>', 0] ])->withSearch([ 'template_name' ], $where)->field($field)->order('create_time desc')->append([ 'fee_type_name' ]);
+ $list = $this->pageQuery($search_model);
+ return $list;
+ }
+
+ /**
+ * 获取运费模板列表
+ * @param array $where
+ * @param string $field
+ * @return array
+ */
+ public function getList(array $where = [], $field = 'template_id, template_name, fee_type, create_time, no_delivery, is_free_shipping')
+ {
+ $order = "create_time desc";
+ return ( new ShippingTemplate() )->where([ ['template_id', '>', 0] ])->withSearch([ "template_name" ], $where)->field($field)->order($order)->select()->toArray();
+ }
+
+ /**
+ * 查询运费模板详情
+ * @return array
+ */
+ public function getInfo(int $template_id)
+ {
+ $field = 'template_id, template_name, fee_type, create_time, no_delivery, is_free_shipping';
+ $detail = ( new ShippingTemplate() )->where([ [ 'template_id', '=', $template_id ] ])->field($field)->append([ 'fee_type_name' ])->findOrEmpty()->toArray();
+ if (!empty($detail)) {
+ $detail[ 'fee_data' ] = ( new ShippingTemplateItem() )->where([ [ 'template_id', '=', $template_id ], [ 'fee_area_ids', '<>', '' ] ])->field('fee_area_ids as area_ids,fee_area_names,snum,sprice,xnum,xprice')->group('fee_area_ids')->select()->toArray();
+ $detail[ 'no_delivery_data' ] = ( new ShippingTemplateItem() )->where([ [ 'template_id', '=', $template_id ], [ 'no_delivery_area_ids', '<>', '' ] ])->field('no_delivery_area_ids as area_ids,no_delivery_area_names')->group('no_delivery_area_ids')->select()->toArray();
+ $detail[ 'free_shipping_data' ] = ( new ShippingTemplateItem() )->where([ [ 'template_id', '=', $template_id ], [ 'free_shipping_area_ids', '<>', '' ] ])->field('free_shipping_area_ids as area_ids,free_shipping_area_names,free_shipping_price,free_shipping_num')->group('free_shipping_area_ids')->select()->toArray();
+ }
+ return $detail;
+ }
+}
diff --git a/niucloud/addon/shop/app/service/admin/delivery/StoreService.php b/niucloud/addon/shop/app/service/admin/delivery/StoreService.php
new file mode 100644
index 000000000..46a522073
--- /dev/null
+++ b/niucloud/addon/shop/app/service/admin/delivery/StoreService.php
@@ -0,0 +1,135 @@
+model = new Store();
+ }
+
+ /**
+ * 获取自提门店列表
+ * @param array $where
+ * @return array
+ */
+ public function getPage(array $where = [])
+ {
+ $field = 'time_week,trade_time_json,time_interval,store_id,store_name,store_desc,store_logo,store_mobile,province_id,city_id,district_id,address,full_address,longitude,latitude,trade_time,create_time,update_time';
+ $order = 'create_time desc';
+
+ $search_model = $this->model->where([ [ 'store_id', '>', 0 ] ])->withSearch([ "store_name", "create_time" ], $where)->field($field)->order($order);
+ $list = $this->pageQuery($search_model);
+ return $list;
+ }
+
+ /**
+ * 获取自提门店信息
+ * @param int $id
+ * @return array
+ */
+ public function getInfo(int $id)
+ {
+ $field = 'time_week,trade_time_json,time_interval,store_id,store_name,store_desc,store_logo,store_mobile,province_id,city_id,district_id,address,full_address,longitude,latitude,trade_time,create_time,update_time';
+ $info = $this->model->field($field)->where([ [ 'store_id', '=', $id ] ])->findOrEmpty()->toArray();
+ $info[ 'province_name' ] = ( new AreaService() )->getAreaName($info[ 'province_id' ]);
+ $info[ 'city_name' ] = ( new AreaService() )->getAreaName($info[ 'city_id' ]);
+ $info[ 'district_name' ] = ( new AreaService() )->getAreaName($info[ 'district_id' ]);
+ if (empty($info[ 'time_interval' ])) $info[ 'time_interval' ] = DeliveryDict::TIME_INTERVAL_30;
+ return $info;
+ }
+
+ public function getInitInfo()
+ {
+ return [
+ 'week_list' => DeliveryDict::getWeekList(),
+ 'time_interval_list' => DeliveryDict::getTimeIntervalList()
+ ];
+ }
+
+ /**
+ * 添加自提门店
+ * @param array $data
+ * @return mixed
+ */
+ public function add(array $data)
+ {
+ $data[ 'create_time' ] = time();
+ $data[ 'update_time' ] = time();
+
+ $data[ 'province_id' ] = ( new AreaService() )->getAreaId($data[ 'province_name' ], 1);
+ $data[ 'city_id' ] = ( new AreaService() )->getAreaId($data[ 'city_name' ], 2);
+ $data[ 'district_id' ] = ( new AreaService() )->getAreaId($data[ 'district_name' ], 3);
+ if ($data[ 'full_address' ] == '') $data[ 'full_address' ] = ( new CoreAreaService() )->getFullAddress($data[ 'province_id' ], $data[ 'city_id' ], $data[ 'district_id' ], $data[ 'address' ], '');
+
+ $res = $this->model->create($data);
+ return $res->store_id;
+ }
+
+ /**
+ * 自提门店编辑
+ * @param int $id
+ * @param array $data
+ * @return bool
+ */
+ public function edit(int $id, array $data, $address)
+ {
+ $data[ 'update_time' ] = time();
+ $data[ 'province_id' ] = ( new AreaService() )->getAreaId($address[ 'province_name' ], 1);
+ $data[ 'city_id' ] = ( new AreaService() )->getAreaId($address[ 'city_name' ], 2);
+ $data[ 'district_id' ] = ( new AreaService() )->getAreaId($address[ 'district_name' ], 3);
+ if ($data[ 'full_address' ] == '') $data[ 'full_address' ] = ( new CoreAreaService() )->getFullAddress($data[ 'province_id' ], $data[ 'city_id' ], $data[ 'district_id' ], $data[ 'address' ], '');
+
+ $this->model->where([ [ 'store_id', '=', $id ] ])->update($data);
+ return true;
+ }
+
+ /**
+ * 删除自提门店
+ * @param int $id
+ * @return bool
+ */
+ public function del(int $id)
+ {
+ $res = $this->model->where([ [ 'store_id', '=', $id ] ])->delete();
+ return $res;
+ }
+
+ /**
+ * 获取自提门店列表
+ * @param array $where
+ * @return array
+ */
+ public function getList(array $where = [])
+ {
+ $field = 'store_id,store_name,store_desc,store_logo,store_mobile,province_id,city_id,district_id,address,full_address,longitude,latitude,trade_time,create_time,update_time';
+ $order = 'create_time desc';
+
+ $list = $this->model->where([ [ 'store_id', '>', 0 ] ])->withSearch([ "store_name", "create_time" ], $where)->field($field)->order($order)->select()->toArray();
+ return $list;
+ }
+
+}
diff --git a/niucloud/addon/shop/app/service/admin/goods/AttrService.php b/niucloud/addon/shop/app/service/admin/goods/AttrService.php
new file mode 100644
index 000000000..55b7c63cf
--- /dev/null
+++ b/niucloud/addon/shop/app/service/admin/goods/AttrService.php
@@ -0,0 +1,148 @@
+model = new Attr();
+ }
+
+ /**
+ * 获取商品参数分页列表
+ * @param array $where
+ * @param string $field
+ * @param string $order
+ * @return array
+ * @throws \think\db\exception\DbException
+ */
+ public function getPage(array $where = [], $field = 'attr_id,attr_name,sort')
+ {
+ $order = 'attr_id desc';
+ if (!empty($where[ 'order' ])) {
+ $order = $where[ 'order' ] . ' ' . $where[ 'sort' ];
+ }
+ $search_model = $this->model->where([ [ 'attr_id', ">", 0 ] ])->withSearch([ "attr_id_arr", "attr_id", "attr_name" ], $where)->field($field)->order($order);
+ $list = $this->pageQuery($search_model);
+ return $list;
+ }
+
+ /**
+ * 获取商品参数列表
+ * @param array $where
+ * @param string $field
+ * @return mixed
+ */
+ public function getList(array $where = [], $field = 'attr_id,attr_name,attr_value_format,sort')
+ {
+ $order = 'sort desc,attr_id desc';
+ if (!empty($where[ 'order' ])) {
+ $order = $where[ 'order' ] . ' ' . $where[ 'sort' ];
+ }
+ return $this->model->where([ [ 'attr_id', ">", 0 ] ])->withSearch([ "attr_id_arr", "attr_id", "attr_name" ], $where)->field($field)->order($order)->select()->toArray();
+ }
+
+ /**
+ * 获取商品参数信息
+ * @param int $id
+ * @param string $field
+ * @return mixed
+ */
+ public function getInfo(int $id, $field = 'attr_id,attr_name,attr_value_format,sort')
+ {
+ $info = $this->model->field($field)->where([ [ 'attr_id', "=", $id ] ])->findOrEmpty()->toArray();
+ return $info;
+ }
+
+ /**
+ * 添加商品参数
+ * @param array $data
+ * @return mixed
+ */
+ public function add(array $data)
+ {
+ $res = $this->model->create($data);
+ return $res->attr_id;
+ }
+
+ /**
+ * 商品参数编辑
+ * @param int $id
+ * @param array $data
+ * @return bool
+ */
+ public function edit(int $id, array $data)
+ {
+ $this->model->where([ [ 'attr_id', '=', $id ] ])->update($data);
+ return true;
+ }
+
+ /**
+ * 删除商品参数
+ * @param int $id
+ * @return bool
+ */
+ public function del(int $id)
+ {
+ $model = $this->model->where([ [ 'attr_id', '=', $id ] ])->find();
+ $res = $model->delete();
+ return $res;
+ }
+
+ /**
+ * 修改商品参数排序号
+ * @param $data
+ * @return mixed
+ */
+ public function modifySort($data)
+ {
+ return $this->model->where([
+ [ 'attr_id', '=', $data[ 'attr_id' ] ],
+ ])->update([ 'sort' => $data[ 'sort' ] ]);
+ }
+
+ /**
+ * 修改商品参数名称
+ * @param $data
+ * @return mixed
+ */
+ public function modifyAttrName($data)
+ {
+ return $this->model->where([
+ [ 'attr_id', '=', $data[ 'attr_id' ] ],
+ ])->update([ 'attr_name' => $data[ 'attr_name' ] ]);
+ }
+
+ /**
+ * 修改商品参数值
+ * @param $data
+ * @return mixed
+ */
+ public function modifyAttrValueFormat($data)
+ {
+ return $this->model->where([
+ [ 'attr_id', '=', $data[ 'attr_id' ] ],
+ ])->update([ 'attr_value_format' => $data[ 'attr_value_format' ] ]);
+ }
+
+}
diff --git a/niucloud/addon/shop/app/service/admin/goods/BrandService.php b/niucloud/addon/shop/app/service/admin/goods/BrandService.php
new file mode 100644
index 000000000..b3a74f84c
--- /dev/null
+++ b/niucloud/addon/shop/app/service/admin/goods/BrandService.php
@@ -0,0 +1,132 @@
+model = new Brand();
+ }
+
+ /**
+ * 获取商品品牌列表
+ * @param array $where
+ * @return array
+ */
+ public function getPage(array $where = [])
+ {
+ $field = 'brand_id,brand_name,logo,color_json,desc,sort,create_time';
+ $order = 'brand_id desc';
+ if (!empty($where[ 'order' ])) {
+ $order = $where[ 'order' ] . ' ' . $where[ 'sort' ];
+ }
+
+ $search_model = $this->model->where([ [ 'brand_id', '>', 0 ] ])->withSearch([ "brand_name" ], $where)->field($field)->order($order);
+ $list = $this->pageQuery($search_model);
+ return $list;
+ }
+
+ /**
+ * 获取商品品牌列表
+ * @param array $where
+ * @param string $field
+ * @return array
+ */
+ public function getList(array $where = [], $field = 'brand_id,brand_name,logo,color_json,desc,sort,create_time')
+ {
+ $order = 'create_time desc';
+ return $this->model->where([ [ 'brand_id', '>', 0 ] ])->withSearch([ "brand_name" ], $where)->field($field)->limit(10)->order($order)->select()->toArray();
+ }
+
+ /**
+ * 获取商品品牌信息
+ * @param int $id
+ * @return array
+ */
+ public function getInfo(int $id)
+ {
+ $field = 'brand_id,brand_name,logo,color_json,desc,sort,create_time';
+ $info = $this->model->field($field)->where([ [ 'brand_id', '=', $id ] ])->findOrEmpty()->toArray();
+ return $info;
+ }
+
+ /**
+ * 添加商品品牌
+ * @param array $data
+ * @return mixed
+ */
+ public function add(array $data)
+ {
+ $data[ 'create_time' ] = time();
+ $brandInfo = $this->model->where([ [ 'brand_name', '=', $data[ 'brand_name' ] ] ])->findOrEmpty()->toArray();
+ if ($brandInfo) {
+ throw new AdminException('品牌已存在,请检查');
+ }
+ $res = $this->model->create($data);
+ return $res->brand_id;
+
+ }
+
+ /**
+ * 商品品牌编辑
+ * @param int $id
+ * @param array $data
+ * @return bool
+ */
+ public function edit(int $id, array $data)
+ {
+ $data[ 'update_time' ] = time();
+ $brandInfo = $this->model->where([ [ 'brand_name', '=', $data[ 'brand_name' ] ] ])->findOrEmpty()->toArray();
+ if ($brandInfo && $brandInfo[ 'brand_id' ] != $id) {
+ throw new AdminException('品牌已存在,请检查');
+ }
+ $this->model->where([ [ 'brand_id', '=', $id ] ])->update($data);
+ return true;
+ }
+
+ /**
+ * 删除商品品牌
+ * @param int $id
+ * @return bool
+ */
+ public function del(int $id)
+ {
+ $model = $this->model->where([ [ 'brand_id', '=', $id ] ])->find();
+ $res = $model->delete();
+ return $res;
+ }
+
+ /**
+ * 修改排序
+ * @param $data
+ * @return Brand
+ */
+ public function modifySort($data)
+ {
+ return $this->model->where([
+ [ 'brand_id', '=', $data[ 'brand_id' ] ],
+ ])->update([ 'sort' => $data[ 'sort' ] ]);
+ }
+
+}
diff --git a/niucloud/addon/shop/app/service/admin/goods/CategoryService.php b/niucloud/addon/shop/app/service/admin/goods/CategoryService.php
new file mode 100644
index 000000000..f88e030f6
--- /dev/null
+++ b/niucloud/addon/shop/app/service/admin/goods/CategoryService.php
@@ -0,0 +1,241 @@
+model = new Category();
+ }
+
+ /**
+ * 获取商品分级查询分类列表
+ * @param array $where
+ * @return array
+ */
+ public function getPage(array $where = [])
+ {
+ $field = 'category_id,category_name,image,level,pid,category_full_name,is_show,sort';
+ $order = 'create_time desc';
+
+ $search_model = $this->model->where([ [ 'category_id', '>', 0 ] ])->withSearch([ "category_name" ], $where)->field($field)->order($order);
+ $list = $this->pageQuery($search_model);
+ return $list;
+ }
+
+ /**
+ * 获取商品分类列表
+ * @param array $where
+ * @param string $field
+ * @return array
+ */
+ public function getList(array $where = [], $field = 'category_id,category_name,image,level,pid,category_full_name,is_show,sort')
+ {
+ $order = 'sort desc,create_time desc';
+ return $this->model->where([ [ 'category_id', '>', 0 ] ])->withSearch([ "category_name", 'level' ], $where)->field($field)->order($order)->select()->toArray();
+ }
+
+ /**
+ * 查询商品分类树结构
+ * @param string $field
+ * @param string $order
+ * @return array
+ */
+ public function getTree()
+ {
+ return ( new CoreGoodsCategoryService() )->getTree([ [ 'category_id', '>', 0 ] ]);
+ }
+
+ /**
+ * 获取商品分类信息
+ * @param int $id
+ * @return array
+ */
+ public function getInfo(int $id)
+ {
+ $field = 'category_id,category_name,image,level,pid,category_full_name,is_show,sort';
+ $info = $this->model->field($field)->where([ [ 'category_id', '=', $id ] ])->findOrEmpty()->toArray();
+ if (!empty($info)) {
+ $info[ 'child_count' ] = 0;
+ if ($info[ 'level' ] == 1) {
+ $info[ 'child_count' ] = $this->model->where([ [ 'pid', '=', $info[ 'category_id' ] ] ])->count();
+ }
+ }
+ return $info;
+ }
+ /**
+ * 获取商品分类信息
+ * @param int $id
+ * @return array
+ */
+ public function checkCategoryValid($ids)
+ {
+ return $this->model->where([ [ 'category_id', 'in', $ids ] ])->column('category_id');
+ }
+
+ /**
+ * 添加商品分类
+ * @param array $data
+ * @return mixed
+ */
+ public function add(array $data)
+ {
+ $data[ 'category_full_name' ] = $data[ 'category_name' ];
+ $data[ 'level' ] = 1;
+
+ $condition = [
+ [ 'category_name', '=', $data[ 'category_name' ] ]
+ ];
+ if ($data[ 'pid' ] > 0) {
+ $condition[] = [ 'pid', '=', $data[ 'pid' ] ];
+ } else {
+ $condition[] = [ 'level', '=', 1 ];
+ }
+
+ $categoryInfo = $this->model->where($condition)->findOrEmpty()->toArray();
+ if ($categoryInfo) {
+ throw new AdminException('分类已存在,请检查');
+ }
+ if ($data[ 'pid' ] > 0) {
+ $info = $this->model->field("category_id, category_name")->where([ [ 'category_id', '=', $data[ 'pid' ] ] ])->findOrEmpty();
+ if ($info->isEmpty()) throw new CommonException('SHOP_GOODS_CATEGORY_NOT_EXIST');
+ $data[ 'category_full_name' ] = $info->category_name . '/' . $data[ 'category_name' ];
+ $data[ 'level' ] = 2;
+ }
+
+ $data[ 'create_time' ] = time();
+ $res = $this->model->create($data);
+ return $res->category_id;
+ }
+
+ /**
+ * 商品分类编辑
+ * @param int $id
+ * @param array $data
+ * @return bool
+ */
+ public function edit(int $id, array $data)
+ {
+ $category_info = $this->getInfo($id);
+ if ($category_info && $category_info[ 'category_id' ] != $id) {
+ throw new AdminException('分类已存在,请检查');
+ }
+ if ($category_info[ 'level' ] == 1 && $category_info[ 'pid' ] != $data[ 'pid' ] && $category_info[ 'child_count' ] > 0) {
+ throw new CommonException('SHOP_GOODS_CATEGORY_EXIST_CHILD');
+ }
+
+ $data[ 'category_full_name' ] = $data[ 'category_name' ];
+ $data[ 'level' ] = 1;
+ if ($data[ 'pid' ] > 0) {
+ $info = $this->model->field("category_id, category_name")->where([ [ 'category_id', '=', $data[ 'pid' ] ] ])->findOrEmpty();
+ if ($info->isEmpty()) throw new CommonException('SHOP_GOODS_CATEGORY_NOT_EXIST');
+ $data[ 'category_full_name' ] = $info->category_name . '/' . $data[ 'category_name' ];
+ $data[ 'level' ] = 2;
+ }
+ $data[ 'update_time' ] = time();
+ try {
+ (new GoodsService())->batchUpdateCategory($id,$category_info['pid'],$data['pid']);
+ $this->model->where([ [ 'category_id', '=', $id ] ])->update($data);
+ return true;
+ }catch (AdminException $e) {
+ throw new AdminException($e->getMessage());
+ }
+
+ }
+
+ /**
+ * 删除商品分类
+ * @param int $id
+ * @return bool
+ */
+ public function del(int $id)
+ {
+ $count = ( new Goods() )->withSearch([ 'goods_category' ], [ 'goods_category' => $id ])->count();
+ if ($count) {
+ throw new AdminException('SHOP_GOODS_CATEGORY_EXIST_GOODS');
+ }
+
+ $field = 'category_id,level,pid';
+ $info = $this->model->field($field)->where([ [ 'category_id', '=', $id ] ])->findOrEmpty()->toArray();
+ if (!empty($info[ 'level' ] == 1)) {
+ // 删除子级分类
+ $this->model->where([ [ 'pid', '=', $id ] ])->delete();
+ }
+ $res = $this->model->where([ [ 'category_id', '=', $id ] ])->delete();
+ return $res;
+ }
+
+ /**
+ * 拖拽商品分类
+ * @param $id
+ * @param $data
+ */
+ public function updateCategory($data)
+ {
+ foreach ($data[ 'category_sort_array' ] as $key => $val) {
+ $info = $this->model->field("category_id, category_name")->where([ [ 'category_id', '=', $val[ 'category_id' ] ] ])->findOrEmpty();
+ if (!$info->isEmpty()) {
+ $data[ 'update_time' ] = time();
+ $this->model->where([ [ 'category_id', '=', $val[ 'category_id' ] ] ])->update([ 'sort' => $val[ 'sort' ] ]);
+ }
+ }
+ return true;
+ }
+
+ /**
+ * 设置商品分类配置
+ * @param array $params
+ * @return array
+ */
+ public function setGoodsCategoryConfig(array $params = [])
+ {
+ return ( new CoreGoodsCategoryService() )->setGoodsCategoryConfig($params);
+ }
+
+ /**
+ * 获取商品分类配置
+ * @return array
+ */
+ public function getGoodsCategoryConfig()
+ {
+ return ( new CoreGoodsCategoryService() )->getGoodsCategoryConfig();
+ }
+
+ /**
+ * 获取商品分类树结构供弹框调用
+ * @param string $field
+ * @param string $order
+ * @return array
+ */
+ public function getTreeComponents()
+ {
+ return ( new CoreGoodsCategoryService() )->getTree([
+ [ 'is_show', '=', 1 ],
+ ], 'category_id,category_name,image,level,pid');
+ }
+
+}
diff --git a/niucloud/addon/shop/app/service/admin/goods/ConfigService.php b/niucloud/addon/shop/app/service/admin/goods/ConfigService.php
new file mode 100644
index 000000000..b923d2296
--- /dev/null
+++ b/niucloud/addon/shop/app/service/admin/goods/ConfigService.php
@@ -0,0 +1,151 @@
+model = new SysConfig();
+ $this->core_goods_config_service = new CoreGoodsConfigService();
+ }
+
+ /**
+ * 获取商品搜索配置
+ * @return array
+ */
+ public function getSearchConfig()
+ {
+ return $this->core_goods_config_service->getSearchConfig();
+ }
+
+ /**
+ * 设置商品搜索配置
+ * @param $data
+ * @return SysConfig|bool|\think\Model
+ */
+ public function setSearchConfig($data)
+ {
+ return $this->core_goods_config_service->setSearchConfig($data);
+ }
+
+ /**
+ * 获取商品编码唯一值配置
+ * @return array
+ */
+ public function getUniqueConfig()
+ {
+ return $this->core_goods_config_service->getUniqueConfig();
+ }
+
+ /**
+ * 设置商品编码唯一值配置
+ * @param $data
+ * @return SysConfig|bool|\think\Model
+ */
+ public function setUniqueConfig($data)
+ {
+ return $this->core_goods_config_service->setUniqueConfig($data);
+ }
+
+ /**
+ * 验证商品编码是否重复
+ * @param $params
+ */
+ public function verifySkuNo($params)
+ {
+ $config_info = $this->core_goods_config_service->getUniqueConfig();
+ if ($config_info['is_enable'] == 0) {
+ return true;
+ }
+
+ if (empty($params['sku_no'])) {
+ throw new AdminException("缺少参数sku_no");
+ }
+
+ $sku_no_arr = explode(',', $params['sku_no']);
+ foreach ($sku_no_arr as $k=>$sku_no) {
+ if (empty($sku_no)){
+ unset($sku_no_arr[$k]);
+ }
+ }
+ if (empty($sku_no_arr)){
+ return true;
+ }
+ //判断传参中的sku_no是否有重复的
+ if (count($sku_no_arr) > 1) {
+ $counts = array_count_values($sku_no_arr);
+ $duplicates = array_filter($counts, function ($count) {
+ return $count > 1;
+ });
+ // 获取所有重复的值
+ $duplicateValues = array_keys($duplicates);
+ if (!empty($duplicateValues)) {
+ throw new AdminException("商品编码[{$duplicateValues[0]}]已存在");
+ }
+ }
+ $sql_arr = [];
+ foreach ($sku_no_arr as $sku_no) {
+ $sql_arr[] = "FIND_IN_SET('{$sku_no}', sku_no)";
+ }
+ $condition = [
+ ['', 'exp', Db::raw(join(' or ', $sql_arr))],
+ ];
+ if (!empty($params['goods_id'])) {
+ $condition[] = ['goods_id', '<>', $params['goods_id']];
+ }
+ $goods_sku_model = new GoodsSku();
+ $info = $goods_sku_model->where($condition)->find();
+ if (!empty($info)) {
+ $exist_sku_no_arr = array_intersect($sku_no_arr, explode(',', $info['sku_no']));
+ $exist_sku_no_arr = array_values($exist_sku_no_arr);
+ throw new AdminException("商品编码[{$exist_sku_no_arr[0]}]已存在");
+ }
+ return true;
+ }
+
+ /**
+ * 获取商品排序配置
+ * @return array|int[]|mixed
+ */
+ public function getSortConfig()
+ {
+ return $this->core_goods_config_service->getSortConfig();
+ }
+
+ /**
+ * 设置商品排序配置
+ * @param $data
+ * @return \addon\shop\app\service\core\goods\SysConfig|bool|\think\Model
+ */
+ public function setSortConfig($data)
+ {
+ return $this->core_goods_config_service->setSortConfig($data);
+ }
+
+}
diff --git a/niucloud/addon/shop/app/service/admin/goods/EvaluateService.php b/niucloud/addon/shop/app/service/admin/goods/EvaluateService.php
new file mode 100644
index 000000000..aa101cc7e
--- /dev/null
+++ b/niucloud/addon/shop/app/service/admin/goods/EvaluateService.php
@@ -0,0 +1,293 @@
+model = new Evaluate();
+ }
+
+ /**
+ * 获取商品评价列表
+ * @param array $where
+ * @return array
+ */
+ public function getPage(array $where = [])
+ {
+ $field = 'evaluate_id,order_id,order_goods_id,goods_id,member_id,content,images,is_anonymous,scores,is_audit,explain_first,create_time,topping';
+ $order = 'create_time desc';
+
+ $goods_where =$evaluate_where = [];
+ $evaluate_where[] = [
+ [ 'evaluate.evaluate_id', '>', 0 ]
+ ];
+ if (isset($where[ 'goods_name' ]) && $where[ 'goods_name' ] != '') {
+ $goods_where[] = [ 'goods.goods_name', 'like', '%' . $this->model->handelSpecialCharacter($where[ 'goods_name' ]) . '%' ];
+ }
+ if (isset($where[ 'status' ]) && $where[ 'status' ] != '') {
+ $evaluate_where[] = [ 'evaluate.is_audit', '=', $where[ 'status' ] ];
+ }
+
+ $search_model = $this->model
+ // ->withSearch(["goods_name"], $where)
+ ->where($evaluate_where)
+ ->field($field)
+ ->withJoin([
+ 'goods' => function(Query $query) use ($goods_where) {
+ $query->where($goods_where);
+ },
+ ])
+ ->order($order)->append([ 'audit_name', 'image_small', 'image_mid' ]);
+ $list = $this->pageQuery($search_model, function($item, $key) {
+ $item_goods = $item[ 'goods' ];
+ if (!empty($item_goods)) {
+ $item_goods->append([ 'goods_cover_thumb_small', 'goods_cover_thumb_mid' ]);
+ }
+
+ });
+ return $list;
+ }
+
+ /**
+ * 获取商品评价信息
+ * @param int $id
+ * @return array
+ */
+ public function getInfo(int $id)
+ {
+ $field = 'evaluate_id,order_id,order_goods_id,goods_id,member_id,content,images,is_anonymous,scores,is_audit,explain_first,create_time';
+
+ $info = $this->model->field($field)->where([ [ 'evaluate_id', '=', $id ] ])->findOrEmpty()->toArray();
+ return $info;
+ }
+
+ /**
+ * 添加商品评价
+ * @param array $data
+ * @return mixed
+ */
+ public function add(array $data)
+ {
+ $data[ 'is_audit' ] = EvaluateDict::AUDIT_NO;
+ return ( new CoreGoodsEvaluateService )->addEvaluate($data);
+ }
+
+ /**
+ * 删除商品评价
+ * @param int $id
+ * @return bool
+ */
+ public function del(int $evaluate_id)
+ {
+ $model = $this->model->where([ [ 'evaluate_id', '=', $evaluate_id ] ])->find();
+ if (empty($model))return false;
+ $res = $model->delete();
+
+ CoreGoodsStatService::addStat([ 'goods_id' => $model->goods_id, 'evaluate_num' => -1 ]);
+ ( new Goods() )->where([ [ 'goods_id', '=', $model->goods_id ] ])->dec('evaluate_num', 1)->update();
+ return $res;
+ }
+
+ /**
+ * 审核通过
+ * @param $evaluate_id
+ * @return bool
+ */
+ public function auditAdopt($evaluate_id)
+ {
+ $this->model->where([ [ 'evaluate_id', '=', $evaluate_id ] ])->update([ 'is_audit' => EvaluateDict::AUDIT_ADOPT ]);
+
+ $goods_id = $this->model->where('evaluate_id', '=', $evaluate_id)->value('goods_id');
+ if (empty($goods_id)) return false;
+ CoreGoodsStatService::addStat([ 'goods_id' => $goods_id, 'evaluate_num' => 1 ]);
+ ( new Goods() )->where([ [ 'goods_id', '=', $goods_id ] ])->inc('evaluate_num', 1)->update();
+ return true;
+ }
+
+ /**
+ * 审核拒绝
+ * @param $evaluate_id
+ * @return bool
+ */
+ public function auditRefuse($evaluate_id)
+ {
+ $this->model->where([ [ 'evaluate_id', '=', $evaluate_id ] ])->update([ 'is_audit' => EvaluateDict::AUDIT_REFUSE ]);
+ return true;
+ }
+
+ /**
+ * 评价回复
+ * @param $evaluate_id
+ * @param $data
+ * @return bool
+ */
+ public function reply($evaluate_id, $data)
+ {
+ $this->model->where([ [ 'evaluate_id', '=', $evaluate_id ] ])->update($data);
+ return true;
+ }
+
+ /**
+ * 置顶
+ * @param $evaluate_id
+ * @return bool
+ */
+ public function topping($evaluate_id)
+ {
+ $data = [
+ 'topping' => 1,
+ 'update_time' => time()
+ ];
+ $this->model->where([ [ 'evaluate_id', '=', $evaluate_id ] ])->update($data);
+ return true;
+ }
+
+ /**
+ * 取消置顶
+ */
+ public function cancelTopping($evaluate_id)
+ {
+ $data = [
+ 'topping' => 0,
+ 'update_time' => 0
+ ];
+ $this->model->where([ [ 'evaluate_id', '=', $evaluate_id ] ])->update($data);
+ return true;
+ }
+
+ /**
+ * 审核批量修改
+ * @return bool
+ */
+ public function auditEditBatch()
+ {
+ // 查询待审核的id
+ $evaluate_ids = $this->model->where([ [ 'is_audit', '=', EvaluateDict::AUDIT ] ])->column('evaluate_id');
+ if (!empty($evaluate_ids)) {
+ GoodsEvaluateStat::dispatch([ 'evaluate_ids' => $evaluate_ids ]);
+ }
+
+ $this->model->where([ [ 'is_audit', '=', EvaluateDict::AUDIT ] ])->update([ 'is_audit' => EvaluateDict::AUDIT_NO ]);
+ return true;
+ }
+
+ /**
+ * 批量设置评论审核状态后,更新评价统计数据
+ * @param $evaluate_ids
+ */
+ public function updateGoodsEvaluateNumBach($evaluate_ids)
+ {
+ $list = $this->model->where([ [ 'evaluate_id', 'in', $evaluate_ids ] ])->chunk(50, function($evaluate) {
+ foreach ($evaluate as $item) {
+ $goods_id = $this->model->where('goods_id', '=', $item[ 'goods_id' ])->value('goods_id');
+ if (!empty($goods_id)){
+ CoreGoodsStatService::addStat([ 'goods_id' => $item[ 'goods_id' ], 'evaluate_num' => 1 ]);
+ ( new Goods() )->where([ [ 'goods_id', '=', $item[ 'goods_id' ] ] ])->inc('evaluate_num', 1)->update();
+ }
+ }
+ });
+ return true;
+ }
+
+ /**
+ * 批量通过
+ * @param $evaluate_ids
+ * @return bool
+ */
+ public function batchAdopt($evaluate_ids)
+ {
+ $evaluate_list = $this->model->where([ [ 'evaluate_id', 'in', $evaluate_ids ], [ 'is_audit', '=', EvaluateDict::AUDIT ] ])->column('evaluate_id, goods_id');
+ $goods_ids = array_column($evaluate_list, 'goods_id');
+ $evaluate_ids = array_column($evaluate_list, 'evaluate_id');
+ Db::startTrans();
+ try {
+ if (!empty($evaluate_list)){
+ $this->model->where([ [ 'evaluate_id', 'in', $evaluate_ids ] ])->update([ 'is_audit' => EvaluateDict::AUDIT_ADOPT ]);
+ foreach ($goods_ids as $value){
+ CoreGoodsStatService::addStat([ 'goods_id' => $value, 'evaluate_num' => 1 ]);
+ ( new Goods() )->where([ [ 'goods_id', '=', $value ] ])->inc('evaluate_num', 1)->update();
+ }
+ }
+ Db::commit();
+ return true;
+ } catch (\Exception $e) {
+ Db::rollback();
+ throw new CommonException($e->getMessage());
+ }
+ }
+
+ /**
+ * 批量拒绝
+ * @param $evaluate_ids
+ * @return bool
+ */
+ public function batchRefuse($evaluate_ids)
+ {
+ $evaluate_list = $this->model->where([ ['evaluate_id', 'in', $evaluate_ids], [ 'is_audit', '=', EvaluateDict::AUDIT ]])->column('evaluate_id, is_audit');
+ if (!empty($evaluate_list)){
+ $this->model->where([ ['evaluate_id', 'in', $evaluate_ids]])->update(['is_audit' => EvaluateDict::AUDIT_REFUSE]);
+ }
+ return true;
+ }
+
+ /**
+ * 批量删除
+ * @param $evaluate_ids
+ * @return bool
+ */
+ public function batchDel($evaluate_ids)
+ {
+ $evaluate_list = $this->model->where([ [ 'evaluate_id', 'in', $evaluate_ids ] ])->column('is_audit, goods_id');
+
+ Db::startTrans();
+ try {
+ $this->model->where([ ['evaluate_id', 'in', $evaluate_ids]])->delete();
+
+ foreach ($evaluate_list as $value){
+ switch ($value[ 'is_audit' ]){
+ case EvaluateDict::AUDIT_NO:
+ case EvaluateDict::AUDIT_ADOPT:
+ CoreGoodsStatService::addStat([ 'goods_id' => $value[ 'goods_id' ], 'evaluate_num' => -1 ]);
+ ( new Goods() )->where([ [ 'goods_id', '=', $value[ 'goods_id' ] ] ])->dec('evaluate_num', 1)->update();
+ break;
+ }
+ }
+ Db::commit();
+ return true;
+ } catch (\Exception $e) {
+ Db::rollback();
+ throw new CommonException($e->getMessage());
+ }
+
+ }
+}
diff --git a/niucloud/addon/shop/app/service/admin/goods/GoodsService.php b/niucloud/addon/shop/app/service/admin/goods/GoodsService.php
new file mode 100644
index 000000000..f3a7db17c
--- /dev/null
+++ b/niucloud/addon/shop/app/service/admin/goods/GoodsService.php
@@ -0,0 +1,1861 @@
+model = new Goods();
+ }
+
+ /**
+ * 获取商品添加/编辑数据
+ * @param array $params
+ * @return array
+ */
+ public function getInit(array $params = [])
+ {
+
+ $res = [];
+
+ $addon_service = new AddonService();
+ $res['addon_shop_supplier'] = $addon_service->getInfoByKey('shop_supplier');
+
+ if (!empty($params['goods_id'])) {
+ // 查询商品信息,用于编辑
+ $field = 'goods_id,goods_name,sub_title,goods_type,goods_cover,goods_image,goods_video,goods_desc,brand_id,goods_category,label_ids,service_ids,unit,stock,virtual_sale_num,is_limit,limit_type,max_buy,min_buy,status,sort,delivery_type,is_free_shipping,fee_type,delivery_money,delivery_template_id,supplier_id,attr_ids,attr_format,member_discount,poster_id,is_gift,form_id,diy_detail_id';
+ $goods_info = $this->model->field($field)->where([['goods_id', '=', $params['goods_id']]])->findOrEmpty()->toArray();
+ if (!empty($goods_info)) {
+
+ if (!empty($goods_info['goods_category'])) {
+ $goods_category = array_values($goods_info['goods_category']);
+ $category_service = new CategoryService();
+ $goods_info['goods_category'] = $category_service->checkCategoryValid($goods_category);
+ }
+
+ // 商品品牌,处理数据类型
+ if (empty($goods_info['brand_id'])) {
+ $goods_info['brand_id'] = '';
+ } else {
+ $brand_count = (new Brand())->where([['brand_id', '=', $goods_info['brand_id']]])->count();
+ if ($brand_count == 0) $goods_info['brand_id'] = '';
+ }
+
+ // 供应商,处理数据类型
+ if (empty($goods_info['supplier_id'])) {
+ $goods_info['supplier_id'] = '';
+ }
+
+ // 标签组
+ if (empty($goods_info['label_ids'])) {
+ $goods_info['label_ids'] = [];
+ } else {
+ $goods_info['label_ids'] = array_map(function ($item) {
+ return (int)$item;
+ }, $goods_info['label_ids']);
+ }
+
+ // 商品服务
+ if (empty($goods_info['service_ids'])) {
+ $goods_info['service_ids'] = [];
+ } else {
+ $goods_info['service_ids'] = array_map(function ($item) {
+ return (int)$item;
+ }, $goods_info['service_ids']);
+ }
+
+ // 商品参数,处理数据类型
+ if (empty($goods_info['attr_ids'])) {
+ $goods_info['attr_ids'] = [];
+ } else {
+ $goods_info['attr_ids'] = array_map(function ($item) {
+ return (int)$item;
+ }, $goods_info['attr_ids']);
+ }
+
+ // 商品海报id,处理数据类型
+ if (empty($goods_info['poster_id'])) {
+ $goods_info['poster_id'] = '';
+ }
+
+ // 自定义商品详情模板id,处理数据类型
+ if (!empty($goods_info['diy_detail_id'])) {
+ $diy_model = new Diy();
+ $diy_count = $diy_model->where([
+ ['id', '=', $goods_info['diy_detail_id']]
+ ])->count();
+ if ($diy_count == 0) {
+ $goods_info['diy_detail_id'] = '';
+ }
+ } else {
+ $goods_info['diy_detail_id'] = '';
+ }
+
+ // 万能表单id,处理数据类型
+ if (!empty($goods_info['form_id'])) {
+ $diy_form_model = new DiyForm();
+ $diy_form_count = $diy_form_model->where([
+ ['form_id', '=', $goods_info['form_id']]
+ ])->count();
+ if ($diy_form_count == 0) {
+ $goods_info['form_id'] = '';
+ }
+ } else {
+ $goods_info['form_id'] = '';
+ }
+
+ // 配送方式
+ if (empty($goods_info['delivery_type'])) {
+ $goods_info['delivery_type'] = [];
+ }
+
+ $goods_info['status'] = (string)$goods_info['status'];
+
+ // 运费模板,处理数据类型
+ if (empty($goods_info['delivery_template_id'])) {
+ $goods_info['delivery_template_id'] = '';
+ }
+
+ $goods_sku_model = new GoodsSku();
+
+ $sku_field = 'sku_id,sku_name,sku_image,sku_no,goods_id,sku_spec_format,price,market_price,cost_price,stock,weight,volume,is_default';
+ $sku_order = 'sku_id asc';
+ $goods_info['sku_list'] = $goods_sku_model->withSearch(["goods_id"], ['goods_id' => $params['goods_id']])->field($sku_field)->order($sku_order)->select()->toArray();
+
+ $temp_sku_data = array_filter(array_column($goods_info['sku_list'], 'sku_spec_format'));
+ $goods_info['spec_type'] = 'single';
+ if (!empty($temp_sku_data)) {
+ // 多规格
+ $goods_info['spec_type'] = 'multi';
+
+ $goods_spec_model = new GoodsSpec();
+ $spec_field = 'spec_id,goods_id,spec_name,spec_values';
+ $spec_order = 'spec_id asc';
+ $goods_info['spec_list'] = $goods_spec_model->withSearch(["goods_id"], ['goods_id' => $params['goods_id']])->field($spec_field)->order($spec_order)->select()->toArray();
+
+ }
+
+ // 查询商品参与营销活动的数量
+ $goods_info['active_goods_count'] = $this->getActiveGoodsCount($goods_info['goods_id']);
+
+ $res['goods_info'] = $goods_info;
+ }
+
+ }
+ $res['default_sort'] = (new CoreGoodsConfigService())->getDefaultSort();
+
+ return $res;
+ }
+
+ /**
+ * 获取商品列表
+ * @param array $where
+ * @return array
+ */
+ public function getPage(array $where = [])
+ {
+ $field = 'goods_id,goods_name,goods_type,goods_cover,stock,sale_num,status,sort,create_time,member_discount,is_gift';
+ $order = 'create_time desc';
+ $sku_where = [
+ ['goodsSku.is_default', '=', 1],
+ ];
+
+ if (!empty($where['start_price']) && !empty($where['end_price'])) {
+ $money = [$where['start_price'], $where['end_price']];
+ sort($money);
+ $sku_where[] = ['goodsSku.price', 'between', $money];
+ } else if (!empty($where['start_price'])) {
+ $sku_where[] = ['goodsSku.price', '>=', $where['start_price']];
+ } else if (!empty($where['end_price'])) {
+ $sku_where[] = ['goodsSku.price', '<=', $where['end_price']];
+ }
+ if (!empty($where['order'])) {
+ $order = $where['order'] . ' ' . $where['sort'];
+ }
+ $search_model = $this->model->where([['goods.goods_id', '>', 0]])->withSearch(["goods_name", "goods_type", "brand_id", "goods_category", "label_ids", 'service_ids', "sale_num", "status"], $where)
+ ->field($field)
+ ->withJoin([
+ 'goodsSku' => ['sku_id', 'goods_id', 'price', 'member_price']
+ ])->where($sku_where)->order($order)->append(['goods_type_name', 'goods_edit_path', 'goods_cover_thumb_small']);
+ $list = $this->pageQuery($search_model);
+ $list['data'] = $this->formatGoodsJoinActive($list['data']);
+ return $list;
+ }
+
+ /**
+ * 处理商品参与的活动数据
+ * @param $goods_data
+ * @return mixed
+ */
+ private function formatGoodsJoinActive($goods_data)
+ {
+ $goods_ids = array_column($goods_data, 'goods_id');
+ $join_list = event('GetGoodsJoinInfo', [
+ 'goods_ids' => $goods_ids,
+ ]);
+ $goods_join = [];
+ foreach ($join_list as $item) {
+ if (empty($item)) {
+ continue;
+ }
+ foreach ($item as $goods_id => $value) {
+ if (!isset($goods_join[$goods_id])) {
+ {
+ $goods_join[$goods_id] = [];
+ }
+ }
+ $goods_join[ $goods_id ] = array_merge($goods_join[ $goods_id ], array_values($value));
+ }
+ }
+ if (!empty($goods_join)) {
+ $active_tips = [];
+ foreach ($goods_join as $goods_id => $join_active) {
+ foreach ($join_active as $k => $v) {
+ $join_type = $v[ 'join_type' ];
+ if (!isset($active_tips[ $goods_id ][ $join_type ][ 'name' ])) {
+ $active_tips[ $goods_id ][ $join_type ][ 'name' ] = '';
+ }
+ if (isset($v[ 'short' ])) {
+ $active_tips[ $goods_id ][ $join_type ][ 'short' ] = $v[ 'short' ];
+ unset($v[ 'short' ]);
+ $active_tips[ $goods_id ][ $join_type ][ 'list' ][] = $v;
+ $active_tips[ $goods_id ][ $join_type ][ 'name' ] .= $v[ 'name' ] . PHP_EOL;
+ } else {
+ // 防止未知数据
+ unset($active_tips[ $goods_id ][ $join_type ]);
+ }
+ }
+ }
+ foreach ($goods_data as &$item) {
+ $item[ 'active' ] = $active_tips[ $item[ 'goods_id' ] ] ?? [];
+ }
+ }
+ return $goods_data;
+ }
+
+ /**
+ * 获取商品信息
+ * @param int $id
+ * @return array
+ */
+ public function getInfo(int $id)
+ {
+ $field = 'goods_id,goods_name,sub_title,goods_type,goods_cover,goods_image,goods_video,goods_desc,brand_id,goods_category,label_ids,service_ids,unit,stock,sale_num,virtual_sale_num,is_limit,limit_type,max_buy,min_buy,status,sort,delivery_type,is_free_shipping,fee_type,delivery_money,delivery_template_id,supplier_id,create_time,update_time,member_discount,poster_id,form_id,diy_detail_id';
+ $info = $this->model->field($field)->where([ [ 'goods_id', '=', $id ] ])->findOrEmpty()->toArray();
+ return $info;
+ }
+
+ /**
+ * 添加商品
+ * @param array $data
+ * @return mixed
+ */
+ public function add(array $data)
+ {
+ try {
+ Db::startTrans();
+ $goods_sku_model = new GoodsSku();
+ $goods_spec_model = new GoodsSpec();
+ $goods_stat_model = new Stat();
+
+ // 商品封面
+ if (!empty($data[ 'goods_image' ])) $data[ 'goods_cover' ] = explode(',', $data[ 'goods_image' ])[ 0 ];
+
+ $goods_data = [
+ 'goods_name' => $data[ 'goods_name' ],
+ 'sub_title' => $data[ 'sub_title' ],
+ 'goods_type' => $data[ 'goods_type' ],
+ 'goods_cover' => $data[ 'goods_cover' ],
+ 'goods_image' => $data[ 'goods_image' ],
+ 'goods_video' => $data[ 'goods_video' ],
+ 'goods_category' => array_map(function ($item) {
+ return (string) $item;
+ }, $data[ 'goods_category' ]),
+ 'goods_desc' => $data[ 'goods_desc' ],
+ 'brand_id' => $data[ 'brand_id' ],
+ 'label_ids' => array_map(function ($item) {
+ return (string) $item;
+ }, $data[ 'label_ids' ]),
+ 'service_ids' => array_map(function ($item) {
+ return (string) $item;
+ }, $data[ 'service_ids' ]),
+ 'unit' => $data[ 'unit' ],
+ 'stock' => $data[ 'stock' ],
+ 'virtual_sale_num' => $data[ 'virtual_sale_num' ],
+ 'is_limit' => $data[ 'is_limit' ],
+ 'limit_type' => $data[ 'limit_type' ],
+ 'max_buy' => $data[ 'max_buy' ],
+ 'min_buy' => $data[ 'min_buy' ],
+ 'is_gift' => $data[ 'is_gift' ],
+ 'status' => $data[ 'status' ],
+ 'sort' => $data[ 'sort' ],
+ 'attr_ids' => $data[ 'attr_ids' ],
+ 'attr_format' => $data[ 'attr_format' ],
+ 'delivery_type' => $data[ 'delivery_type' ],
+ 'is_free_shipping' => $data[ 'is_free_shipping' ],
+ 'fee_type' => $data[ 'fee_type' ],
+ 'delivery_money' => $data[ 'delivery_money' ],
+ 'delivery_template_id' => $data[ 'delivery_template_id' ],
+ 'supplier_id' => $data[ 'supplier_id' ],
+ 'member_discount' => $data[ 'member_discount' ],
+ 'poster_id' => $data[ 'poster_id' ],
+ 'form_id' => $data[ 'form_id' ],
+ 'diy_detail_id' => $data[ 'diy_detail_id' ],
+ 'create_time' => time()
+ ];
+ $res = $this->model->create($goods_data);
+
+ $sku_data = [];
+ if ($data[ 'spec_type' ] == 'single') {
+ if (!empty($data[ 'sku_no' ])) {
+ ( new ConfigService() )->verifySkuNo([ 'sku_no' => $data[ 'sku_no' ] ]);
+ }
+ // 单规格
+ $sku_data = [
+ 'sku_name' => '',
+ 'sku_image' => $data[ 'goods_cover' ],
+ 'sku_no' => $data[ 'sku_no' ],
+ 'goods_id' => $res->goods_id,
+ 'sku_spec_format' => '', // sku规格格式
+ 'price' => $data[ 'price' ],
+ 'market_price' => $data[ 'market_price' ],
+ 'sale_price' => $data[ 'price' ],
+ 'cost_price' => $data[ 'cost_price' ],
+ 'stock' => $data[ 'stock' ],
+ 'weight' => $data[ 'weight' ],
+ 'volume' => $data[ 'volume' ],
+ 'is_default' => 1
+ ];
+ $goods_sku_model->save($sku_data);
+
+ } elseif ($data[ 'spec_type' ] == 'multi') {
+ $sku_no = implode(',', array_column($data[ 'goods_sku_data' ] ?? [], 'sku_no'));
+ if (!empty($sku_no)) {
+ ( new ConfigService() )->verifySkuNo([ 'sku_no' => $sku_no ]);
+ }
+ // 多规格数据
+ $default_spec_count = 0;
+ foreach ($data[ 'goods_sku_data' ] as $k => $v) {
+ $sku_spec_format = [];
+ foreach ($v[ 'sku_spec' ] as $ck => $cv) {
+ $sku_spec_format[] = $cv[ 'spec_value_name' ];
+ }
+ $sku_data[] = [
+ 'sku_name' => $v[ 'spec_name' ],
+ 'sku_image' => !empty($v[ 'sku_image' ]) ? $v[ 'sku_image' ] : $data[ 'goods_cover' ],
+ 'sku_no' => $v[ 'sku_no' ],
+ 'goods_id' => $res->goods_id,
+ 'sku_spec_format' => implode(',', $sku_spec_format), // sku规格格式
+ 'price' => $v[ 'price' ],
+ 'market_price' => $v[ 'market_price' ],
+ 'sale_price' => $v[ 'price' ],
+ 'cost_price' => $v[ 'cost_price' ],
+ 'stock' => $v[ 'stock' ],
+ 'weight' => $v[ 'weight' ],
+ 'volume' => $v[ 'volume' ],
+ 'is_default' => $v[ 'is_default' ]
+ ];
+ if ($v[ 'is_default' ] == 1) $default_spec_count++;
+ }
+
+ if ($default_spec_count == 0) throw new AdminException('SHOP_GOODS_NOT_HAS_DEFAULT_SPEC');
+
+ $goods_sku_model->insertAll($sku_data);
+
+ // 商品规格值
+ $spec_data = [];
+ foreach ($data[ 'goods_spec_format' ] as $k => $v) {
+ $spec_values = [];
+ foreach ($v[ 'values' ] as $ck => $cv) {
+ $spec_values[] = $cv[ 'spec_value_name' ];
+ }
+ $spec_data[] = [
+ 'goods_id' => $res->goods_id,
+ 'spec_name' => $v[ 'spec_name' ],
+ 'spec_values' => implode(',', $spec_values)
+ ];
+ }
+ $goods_spec_model->insertAll($spec_data);
+
+ }
+
+ //添加商品统计表数据
+ $goods_stat_data = [
+ 'date' => date('Y-m-d'),
+ 'date_time' => strtotime(date('Y-m-d')),
+ 'goods_id' => $res->goods_id,
+ ];
+ $goods_stat_model->create($goods_stat_data);
+
+ Db::commit();
+
+ event('AfterGoodsEdit', [
+ 'goods_id' => $res->goods_id,
+ 'goods_data' => $goods_data,
+ 'sku_data' => $sku_data
+ ]);
+
+ return $res->goods_id;
+ } catch (\Exception $e) {
+ Db::rollback();
+ throw new CommonException($e->getMessage());
+ }
+ }
+
+ /**
+ * 商品编辑
+ * @param int $goods_id
+ * @param array $data
+ * @return bool
+ */
+ public function edit(int $goods_id, array $data)
+ {
+ try {
+ Db::startTrans();
+
+ $goods_sku_model = new GoodsSku();
+ $goods_spec_model = new GoodsSpec();
+ $order_goods_model = new OrderGoods();
+ $goods_price = 0;
+ // 查询商品参与营销活动的数量
+ $active_goods_count = $this->getActiveGoodsCount($goods_id);
+ if ($data[ 'status' ] == 0) {
+ if ($active_goods_count > 0) {
+ throw new AdminException('SHOP_GOODS_PARTICIPATE_IN_ACTIVE_DISABLED_EDIT');
+ }
+ }
+
+ // 商品封面
+ if (!empty($data[ 'goods_image' ])) $data[ 'goods_cover' ] = explode(',', $data[ 'goods_image' ])[ 0 ];
+
+ $goods_data = [
+ 'goods_name' => $data[ 'goods_name' ],
+ 'sub_title' => $data[ 'sub_title' ],
+ 'goods_type' => $data[ 'goods_type' ],
+ 'goods_cover' => $data[ 'goods_cover' ],
+ 'goods_image' => $data[ 'goods_image' ],
+ 'goods_video' => $data[ 'goods_video' ],
+ 'goods_category' => array_map(function ($item) {
+ return (string) $item;
+ }, $data[ 'goods_category' ]),
+ 'goods_desc' => $data[ 'goods_desc' ],
+ 'brand_id' => $data[ 'brand_id' ],
+ 'label_ids' => array_map(function ($item) {
+ return (string) $item;
+ }, $data[ 'label_ids' ]),
+ 'service_ids' => array_map(function ($item) {
+ return (string) $item;
+ }, $data[ 'service_ids' ]),
+ 'unit' => $data[ 'unit' ],
+ 'stock' => $data[ 'stock' ],
+ 'virtual_sale_num' => $data[ 'virtual_sale_num' ],
+ 'is_limit' => $data[ 'is_limit' ],
+ 'limit_type' => $data[ 'limit_type' ],
+ 'max_buy' => $data[ 'max_buy' ],
+ 'min_buy' => $data[ 'min_buy' ],
+ 'is_gift' => $data[ 'is_gift' ],
+ 'status' => $data[ 'status' ],
+ 'sort' => $data[ 'sort' ],
+ 'attr_ids' => $data[ 'attr_ids' ],
+ 'attr_format' => $data[ 'attr_format' ],
+ 'delivery_type' => $data[ 'delivery_type' ],
+ 'is_free_shipping' => $data[ 'is_free_shipping' ],
+ 'fee_type' => $data[ 'fee_type' ],
+ 'delivery_money' => $data[ 'delivery_money' ],
+ 'delivery_template_id' => $data[ 'delivery_template_id' ],
+ 'supplier_id' => $data[ 'supplier_id' ],
+ 'member_discount' => $data[ 'member_discount' ],
+ 'poster_id' => $data[ 'poster_id' ],
+ 'form_id' => $data[ 'form_id' ],
+ 'diy_detail_id' => $data[ 'diy_detail_id' ],
+ 'update_time' => time()
+ ];
+
+ $this->model->where([ [ 'goods_id', '=', $goods_id ]])->update($goods_data);
+ $sku_data = [];
+ if ($data[ 'spec_type' ] == 'single') {
+ if (!empty($data[ 'sku_no' ])) {
+ $check = [ 'sku_no' => $data[ 'sku_no' ], 'goods_id' => $goods_id ];
+ ( new ConfigService() )->verifySkuNo($check);
+ }
+ // 单规格
+ $sku_data = [
+ 'sku_name' => '',
+ 'sku_image' => $data[ 'goods_cover' ],
+ 'sku_no' => $data[ 'sku_no' ],
+ 'goods_id' => $goods_id,
+ 'sku_spec_format' => '', // sku规格格式
+ 'market_price' => $data[ 'market_price' ],
+ 'cost_price' => $data[ 'cost_price' ],
+ 'weight' => $data[ 'weight' ],
+ 'volume' => $data[ 'volume' ],
+ 'stock' => $data[ 'stock' ],
+ 'is_default' => 1
+ ];
+
+ // 未参与营销活动,则允许修改 原价、销售价
+ if ($active_goods_count == 0) {
+ $sku_data[ 'price' ] = $data[ 'price' ];
+ $sku_data[ 'sale_price' ] = $data[ 'price' ];
+ }
+
+ $sku_count = $goods_sku_model->where([ [ 'goods_id', '=', $goods_id ] ])->count();
+ if ($sku_count > 1) {
+
+ // 规格项发生变化,删除旧规格,添加新规格重新生成
+ $goods_sku_model->where([ [ 'goods_id', '=', $goods_id ] ])->delete();
+
+ // 防止存在遗留规格项,删除旧规格
+ $goods_spec_model->where([ [ 'goods_id', '=', $goods_id ] ])->delete();
+
+ // 新增规格
+ $goods_sku_model->create($sku_data);
+
+ } else {
+
+ $goods_sku_model->where([ [ 'goods_id', '=', $goods_id ] ])->update($sku_data);
+
+ // 防止存在遗留规格项,删除旧规格
+ $goods_spec_model->where([ [ 'goods_id', '=', $goods_id ] ])->delete();
+ }
+ $goods_price = $sku_data['price'] ?? $goods_sku_model->price;
+ } elseif ($data[ 'spec_type' ] == 'multi') {
+ $sku_no = implode(',', array_column($data[ 'goods_sku_data' ] ?? [], 'sku_no'));
+ if (!empty($sku_no)) {
+ $check = [ 'sku_no' => $sku_no, 'goods_id' => $goods_id ];
+ ( new ConfigService() )->verifySkuNo($check);
+ }
+ // 多规格数据
+ $first_sku_data = reset($data[ 'goods_sku_data' ]);
+
+ // 商品正在参与营销活动,禁止修改规格
+ if ($active_goods_count > 0 && empty($first_sku_data[ 'sku_id' ])) {
+ throw new AdminException('SHOP_GOODS_PARTICIPATE_IN_ACTIVE_DISABLED_EDIT');
+ }
+
+ // 检测规格项是否发生变化
+ if (!empty($first_sku_data[ 'sku_id' ])) {
+ // 规格项没有变化,修改/新增规格数据
+
+ $sku_id_arr = [];
+ $default_spec_count = 0;
+ foreach ($data[ 'goods_sku_data' ] as $k => $v) {
+ $sku_spec_format = [];
+ foreach ($v[ 'sku_spec' ] as $ck => $cv) {
+ $sku_spec_format[] = $cv[ 'spec_value_name' ];
+ }
+ $sku_data = [
+ 'sku_name' => $v[ 'spec_name' ],
+ 'sku_image' => !empty($v[ 'sku_image' ]) ? $v[ 'sku_image' ] : $data[ 'goods_cover' ],
+ 'sku_no' => $v[ 'sku_no' ],
+ 'goods_id' => $goods_id,
+ 'sku_spec_format' => implode(',', $sku_spec_format), // sku规格格式
+ 'market_price' => $v[ 'market_price' ],
+ 'cost_price' => $v[ 'cost_price' ],
+ 'weight' => $v[ 'weight' ],
+ 'volume' => $v[ 'volume' ],
+ 'stock' => $v[ 'stock' ],
+ 'is_default' => $v[ 'is_default' ]
+ ];
+
+ // 未参与营销活动,则允许修改 原价、销售价
+ if ($active_goods_count == 0) {
+ $sku_data[ 'price' ] = $v[ 'price' ];
+ $sku_data[ 'sale_price' ] = $v[ 'price' ];
+ }
+
+ if (!empty($v[ 'sku_id' ])) {
+ // 修改规格
+ $sku_id_arr[] = $v[ 'sku_id' ];
+ $goods_sku_model->where([ [ 'sku_id', '=', $v[ 'sku_id' ] ], [ 'goods_id', '=', $goods_id ] ])->update($sku_data);
+ } else {
+ // 新增规格
+ $sku_model = $goods_sku_model->create($sku_data);
+ $sku_id_arr[] = $sku_model->sku_id;
+ }
+ if ($v[ 'is_default' ] == 1) {
+
+ $goods_price = $v[ 'price' ] ?? $goods_sku_model->price;
+ $default_spec_count++;
+ }
+ }
+
+ // 校验默认必须存在默认规格
+ if ($default_spec_count == 0) throw new AdminException('SHOP_GOODS_NOT_HAS_DEFAULT_SPEC');
+
+ $spec_id_list = $goods_spec_model->withSearch([ "goods_id" ], [ 'goods_id' => $goods_id ])->field('spec_id')->select()->toArray();
+ $spec_id_list = array_column($spec_id_list, 'spec_id');
+
+ // 商品规格值
+ foreach ($data[ 'goods_spec_format' ] as $k => $v) {
+ $spec_values = [];
+ foreach ($v[ 'values' ] as $ck => $cv) {
+ $spec_values[] = $cv[ 'spec_value_name' ];
+ }
+ $spec_data = [
+ 'goods_id' => $goods_id,
+ 'spec_name' => $v[ 'spec_name' ],
+ 'spec_values' => implode(',', $spec_values)
+ ];
+ if (!empty($v[ 'spec_id' ])) {
+ // 修改规格值
+ $goods_spec_model->where([ [ 'goods_id', '=', $goods_id ], [ 'spec_id', '=', $v[ 'spec_id' ] ] ])->update($spec_data);
+ foreach ($spec_id_list as $ck => $cv) {
+ if ($v[ 'spec_id' ] == $cv) {
+ unset($spec_id_list[ $ck ]);
+ }
+ }
+
+ } else {
+ // 添加规格值
+ $goods_spec_model->save($spec_data);
+ }
+ }
+
+ // 移除不存在的规格项
+ if (!empty($spec_id_list)) {
+ $goods_spec_model->where([ [ 'spec_id', 'in', implode(',', $spec_id_list) ] ])->delete();
+ }
+
+ // 移除不存在的商品SKU
+ $sku_id_list = $goods_sku_model->withSearch([ "goods_id" ], [ 'goods_id' => $goods_id ])->field('sku_id')->select()->toArray();
+ $sku_id_list = array_column($sku_id_list, 'sku_id');
+ foreach ($sku_id_list as $k => $v) {
+ foreach ($sku_id_arr as $ck => $cv) {
+ if ($v == $cv) {
+ unset($sku_id_list[ $k ]);
+ }
+ }
+ }
+ $sku_id_list = array_values($sku_id_list);
+
+ if (!empty($sku_id_list)) {
+
+ // 检测订单是否存在要删除的商品
+ $order_where = [
+ [ 'orderMain.status', 'in', [ OrderDict::NORMAL, OrderDict::WAIT_DELIVERY, OrderDict::WAIT_TAKE ] ], // 排除已完成、已关闭状态
+ [ 'goods_id', '=', $goods_id ],
+ [ 'sku_id', 'in', $sku_id_list ]
+ ];
+ $order_goods_count = $order_goods_model
+ ->withJoin([ 'orderMain' ])
+ ->where($order_where)->count();
+
+ if ($order_goods_count > 0) {
+ Db::rollback();
+ throw new CommonException('EXIST_ORDER_NOT_DELETE_GOODS');
+ }
+
+ $goods_sku_model->where([ [ 'sku_id', 'in', implode(',', $sku_id_list) ] ])->delete();
+ }
+
+ } else {
+
+ // 检测订单是否存在要删除的商品
+ $order_where = [
+ [ 'orderMain.status', 'in', [ 1, 2, 3 ] ], // 排除已完成、已关闭状态
+ [ 'goods_id', '=', $goods_id ]
+ ];
+ $order_goods_count = $order_goods_model
+ ->withJoin([ 'orderMain' ])
+ ->where($order_where)->count();
+
+ if ($order_goods_count > 0) {
+ Db::rollback();
+ throw new CommonException('EXIST_ORDER_NOT_EDIT_GOODS');
+ }
+
+ // 规格项发生变化,删除旧规格,添加新规格重新生成
+ $goods_sku_model->where([ [ 'goods_id', '=', $goods_id ] ])->delete();
+ $goods_spec_model->where([ [ 'goods_id', '=', $goods_id ] ])->delete();
+
+ $default_spec_count = 0;
+ foreach ($data[ 'goods_sku_data' ] as $k => $v) {
+ $sku_spec_format = [];
+ foreach ($v[ 'sku_spec' ] as $ck => $cv) {
+ $sku_spec_format[] = $cv[ 'spec_value_name' ];
+ }
+ $sku_data[] = [
+ 'sku_name' => $v[ 'spec_name' ],
+ 'sku_image' => !empty($v[ 'sku_image' ]) ? $v[ 'sku_image' ] : $data[ 'goods_cover' ],
+ 'sku_no' => $v[ 'sku_no' ],
+ 'goods_id' => $goods_id,
+ 'sku_spec_format' => implode(',', $sku_spec_format), // sku规格格式
+ 'price' => $v[ 'price' ],
+ 'sale_price' => $v[ 'price' ],
+ 'market_price' => $v[ 'market_price' ],
+ 'cost_price' => $v[ 'cost_price' ],
+ 'stock' => $v[ 'stock' ],
+ 'weight' => $v[ 'weight' ],
+ 'volume' => $v[ 'volume' ],
+ 'is_default' => $v[ 'is_default' ]
+ ];
+ if ($v[ 'is_default' ] == 1) $default_spec_count++;
+ }
+
+ // 校验默认必须存在默认规格
+ if ($default_spec_count == 0) throw new AdminException('SHOP_GOODS_NOT_HAS_DEFAULT_SPEC');
+
+ $goods_sku_model->saveAll($sku_data);
+
+ // 商品规格值
+ $spec_data = [];
+ foreach ($data[ 'goods_spec_format' ] as $k => $v) {
+ $spec_values = [];
+ foreach ($v[ 'values' ] as $ck => $cv) {
+ $spec_values[] = $cv[ 'spec_value_name' ];
+ }
+ $spec_data[] = [
+ 'goods_id' => $goods_id,
+ 'spec_name' => $v[ 'spec_name' ],
+ 'spec_values' => implode(',', $spec_values)
+ ];
+ }
+ $goods_spec_model->saveAll($spec_data);
+
+ }
+
+ }
+
+ Db::commit();
+
+ event('AfterGoodsEdit', [
+ 'goods_id' => $goods_id,
+ 'goods_data' => $goods_data,
+ 'sku_data' => $sku_data
+ ]);
+ event('TreasureDataSync',[
+ 'relate_id'=>$goods_id,
+ 'relate_type'=>'shop',
+ 'treasure_name'=>$data['goods_name'],
+ 'treasure_sub_name'=>$data['sub_title'],
+ 'treasure_image'=>$data['goods_image'],
+ 'treasure_price'=>$goods_price,
+ ]);
+ return true;
+ } catch (\Exception $e) {
+ Db::rollback();
+ throw new CommonException($e->getMessage());
+ }
+ }
+
+ /**
+ * 删除商品
+ * @param $goods_ids
+ * @return bool
+ */
+ public function del($data)
+ {
+ $is_all = $data[ 'is_all' ];
+ $goods_ids = $data[ 'goods_ids' ];
+ $where = $data[ 'where' ];
+ // 查询商品参与营销活动的数量
+ $active_goods_count = $this->getActiveGoodsCount($goods_ids, $is_all);
+ if ($active_goods_count > 0) {
+ throw new AdminException('SHOP_GOODS_PARTICIPATE_IN_ACTIVE_DISABLED_EDIT');
+ }
+ // 查询商品是否参与礼品卡活动
+ $is_connected = event('GoodsIsConnectedCard', [ 'is_all' => $is_all, 'where' => $where, 'goods_ids' => $goods_ids ]);
+ if (!empty($is_connected) && isset($is_connected[ 0 ]) && $is_connected[ 0 ]) {
+ throw new AdminException('GOODS_PARTICIPATE_IN_ACTIVE_DISABLED_DELETE');
+ }
+
+ // 删除之前下架商品
+ if (!$is_all) {
+ $query = $this->model->where([
+ [ 'goods_id', 'in', $goods_ids ]
+ ]);
+ $update = [ 'status' => 0, 'delete_time' => time() ];
+ } else {
+ $query = $this->getBatchAllQuery($data[ 'where' ], $goods_ids);
+ $update = [ 'goods.status' => 0, 'goods.delete_time' => time() ];
+ }
+ return $query->update($update);
+ }
+
+ /**
+ * 恢复商品
+ * @param $goods_ids
+ * @return bool
+ */
+ public function recycle($goods_ids)
+ {
+ $res = $this->model->restore([ [ 'goods_id', 'in', $goods_ids ]]);
+ return $res;
+ }
+
+ /**
+ * 获取商品类型
+ * @return array|mixed|string
+ */
+ public function getType()
+ {
+ return GoodsDict::getType();
+ }
+
+ /**
+ * 修改商品排序号
+ * @param array $data
+ * @return Goods|bool
+ */
+ public function editSort($data)
+ {
+ return $this->model->where([ [ 'goods_id', '=', $data[ 'goods_id' ] ]])->update([ 'sort' => $data[ 'sort' ] ]);
+ }
+
+ /**
+ * 修改商品上下架状态
+ * @param $data
+ * @return Goods
+ */
+ public function editStatus($data)
+ {
+ $is_all = $data[ 'is_all' ];
+ $explode_goods_ids = [];
+ if ($data[ 'status' ] == 0) {
+ // 查询商品参与营销活动的数量
+ $explode_goods_ids = $this->getActiveGoodsIds($data[ 'goods_ids' ], $is_all, $data[ 'where' ]);
+
+ }
+ if (!$is_all) {
+ $res = $this->model->where([
+ [ 'goods_id', 'in', $data[ 'goods_ids' ] ]
+ ])->whereNotIn('goods_id', $explode_goods_ids)->update([ 'status' => $data[ 'status' ] ]);
+ } else {
+ $explode_goods_ids = array_merge($explode_goods_ids, $data[ 'goods_ids' ]);
+ $res = $this->getBatchAllQuery($data[ 'where' ], $explode_goods_ids)->update([ 'goods.status' => $data[ 'status' ] ]);
+ }
+ return $res;
+ }
+
+ /**
+ * 修改商品上下架状态(单商品)
+ * @param $data
+ * @return bool
+ */
+ public function editSingleStatus($data)
+ {
+ if ($data[ 'status' ] == 0) {
+ // 查询商品参与营销活动的数量
+ $explode_goods_ids = $this->getActiveGoodsIds($data[ 'goods_id' ]);
+ }
+ if (!empty($explode_goods_ids)) throw new AdminException('SHOP_GOODS_PARTICIPATE_IN_ACTIVE_DISABLED_EDIT');
+
+ $this->model->where([
+ [ 'goods_id', '=', $data[ 'goods_id' ] ]
+ ])->update([ 'status' => $data[ 'status' ] ]);
+ return true;
+ }
+
+ /**
+ * 复制商品
+ * @param int $goods_id
+ * @return mixed
+ */
+ public function copy(int $goods_id)
+ {
+ try {
+ Db::startTrans();
+ $goods_sku_model = new GoodsSku();
+ $goods_spec_model = new GoodsSpec();
+
+ // 查询商品信息
+ $field = 'goods_name,sub_title,goods_type,goods_cover,goods_image,goods_video,goods_desc,brand_id,goods_category,label_ids,service_ids,unit,stock,virtual_sale_num,is_limit,limit_type,max_buy,min_buy,status,sort,delivery_type,is_free_shipping,fee_type,delivery_money,delivery_template_id,supplier_id,attr_ids,attr_format,virtual_auto_delivery,virtual_receive_type,virtual_verify_type,virtual_indate,poster_id,form_id';
+
+ $goods_data = $this->model->field($field)->where([ [ 'goods_id', '=', $goods_id ]])->findOrEmpty()->toArray();
+ if (empty($goods_data)) {
+ throw new AdminException('SHOP_GOODS_NOT_EXIST');
+ }
+
+ // 初始化数据
+ $goods_data[ 'goods_name' ] .= '_副本';
+ $goods_data[ 'sale_num' ] = 0;
+ $goods_data[ 'create_time' ] = time();
+ $goods_data[ 'sort' ] = 0;
+ $goods_data[ 'status' ] = 0;
+
+ // 添加商品
+ $res = $this->model->create($goods_data);
+
+ // 查询商品规格信息
+ $sku_field = 'sku_id,sku_name,sku_image,sku_no,goods_id,sku_spec_format,price,market_price,cost_price,stock,weight,volume,is_default';
+
+ $sku_order = 'sku_id asc';
+ $goods_sku_list = $goods_sku_model->withSearch([ "goods_id" ], [ 'goods_id' => $goods_id ])->field($sku_field)->order($sku_order)->select()->toArray();
+
+ // 添加商品规格
+ foreach ($goods_sku_list as $k => $v) {
+ unset($goods_sku_list[ $k ][ 'sku_id' ]);
+ $goods_sku_list[ $k ][ 'sale_num' ] = 0;
+ $goods_sku_list[ $k ][ 'goods_id' ] = $res->goods_id;
+ }
+ $goods_sku_model->saveAll($goods_sku_list);
+
+ // 查询规格值信息
+ $spec_field = 'spec_id,goods_id,spec_name,spec_values';
+ $spec_order = 'spec_id asc';
+ $spec_list = $goods_spec_model->withSearch([ "goods_id" ], [ 'goods_id' => $goods_id ])->field($spec_field)->order($spec_order)->select()->toArray();
+
+ // 添加规格项/值
+ if (!empty($spec_list)) {
+ foreach ($spec_list as $k => $v) {
+ unset($spec_list[ $k ][ 'spec_id' ]);
+ $spec_list[ $k ][ 'goods_id' ] = $res->goods_id;
+ }
+ $goods_spec_model->saveAll($spec_list);
+ }
+
+ Db::commit();
+ return $res->goods_id;
+ } catch (\Exception $e) {
+ Db::rollback();
+ throw new CommonException($e->getMessage());
+ }
+ }
+
+ /**
+ * 查询回收站商品分页列表
+ * @param array $where
+ * @return array
+ * @throws \think\db\exception\DbException
+ */
+ public function getRecyclePage(array $where = [])
+ {
+ $field = 'goods_id,goods_name,goods_type,goods_cover,goods_category,unit,stock,sale_num,virtual_sale_num,status,create_time,update_time';
+ $order = 'create_time desc';
+ $sku_where = [
+ [ 'goodsSku.is_default', '=', 1 ],
+ ];
+ if (!empty($where[ 'order' ])) {
+ $order = $where[ 'order' ] . ' ' . $where[ 'sort' ];
+ }
+
+ $search_model = $this->model->onlyTrashed()->withSearch([ "goods_id", "goods_name", "goods_type", "goods_category" ], $where)
+ ->field($field)->withJoin([
+ 'goodsSku' => [ 'sku_id', 'sku_name', 'goods_id', 'price', 'stock' ],
+ ])->where($sku_where)->order($order)->append([ 'goods_type_name', 'goods_edit_path', 'goods_cover_thumb_small' ]);
+ $list = $this->pageQuery($search_model);
+ return $list;
+ }
+
+ /**
+ * 获取商品选择分页列表
+ * @param array $where
+ * @return array
+ */
+ public function getSelectPage(array $where = [])
+ {
+ $field = ' goods_id, goods_name, goods_type, goods_cover,goods_image, stock,sub_title,goods_desc,is_gift';
+ $order = 'sort desc,create_time desc';
+
+ $sku_where = [
+ [ 'goodsSku.is_default', '=', 1 ],
+ ];
+ if (!empty($where[ 'start_price' ]) && !empty($where[ 'end_price' ])) {
+ $money = [ $where[ 'start_price' ], $where[ 'end_price' ] ];
+ sort($money);
+ $sku_where[] = [ 'goodsSku.price', 'between', $money ];
+ } else if (!empty($where[ 'start_price' ])) {
+ $sku_where[] = [ 'goodsSku.price', '>=', $where[ 'start_price' ] ];
+ } else if (!empty($where[ 'end_price' ])) {
+ $sku_where[] = [ 'goodsSku.price', '<=', $where[ 'end_price' ] ];
+ }
+
+ if (isset($where[ 'is_gift' ]) && $where[ 'is_gift' ] == GoodsDict::IS_GIFT) {
+ $sku_where[] = [ 'goods.is_gift', 'in', [ GoodsDict::NOT_IS_GIFT, GoodsDict::IS_GIFT ] ];
+ } else {
+ $sku_where[] = [ 'goods.is_gift', '=', GoodsDict::NOT_IS_GIFT ];
+ }
+
+ if (!empty($where[ 'keyword' ])) {
+ $sku_where[] = [ 'goods_name|sub_title', 'like', '%' . $where[ 'keyword' ] . '%' ];
+ }
+
+ // 查询已选的
+ if (!empty($where[ 'sku_ids' ])) {
+ $goods_sku_model = new GoodsSku();
+ $goods_ids = $goods_sku_model->where([
+ [ 'sku_id', 'in', $where[ 'sku_ids' ] ]
+ ])->field('goods_id')->select()->toArray();
+ if (!empty($goods_ids)) {
+ $goods_ids = array_column($goods_ids, 'goods_id');
+ }
+ }
+
+ if (!empty($goods_ids) && empty($where[ 'goods_ids' ])) {
+ $where[ 'goods_ids' ] = $goods_ids;
+ }
+ if (!empty($where[ 'goods_type' ])) {
+ $sku_where[] = [ 'goods.goods_type', '=', $where[ 'goods_type' ] ];
+ }
+
+ if ($where[ 'select_type' ] == 'all') {
+ $sku_where[] = [ 'goods.stock', '>', 0 ];
+ $sku_where[] = [ 'status', '=', 1 ];
+ }
+ if ($where[ 'select_type' ] == 'selected') {
+ $sku_where[] = [ 'goods.goods_id', 'in', $where[ 'goods_ids' ] ];
+ }
+
+ $verify_goods_ids = [];
+ $verify_sku_ids = [];
+ // 检测商品id集合是否存在,移除不存在的商品id,纠正数据准确性
+ if (!empty($where[ 'verify_goods_ids' ])) {
+ $verify_goods_ids = $this->model->where([
+ [ 'goods_id', 'in', $where[ 'verify_goods_ids' ] ],
+ [ 'status', '=', 1 ]
+ ])->field('goods_id')->select()->toArray();
+
+ if (!empty($verify_goods_ids)) {
+ $verify_goods_ids = array_column($verify_goods_ids, 'goods_id');
+ }
+ }
+
+ // 检测商品id集合是否存在,移除不存在的商品id,纠正数据准确性
+ if (!empty($where[ 'verify_sku_ids' ])) {
+ $goods_sku_model = new GoodsSku();
+ $verify_sku_ids = $goods_sku_model->where([
+ [ 'sku_id', 'in', $where[ 'verify_sku_ids' ] ]
+ ])->field('sku_id')->select()->toArray();
+
+ if (!empty($verify_sku_ids)) {
+ $verify_sku_ids = array_column($verify_sku_ids, 'sku_id');
+ }
+ }
+
+ $search_model = $this->model
+ ->withSearch([ "goods_category", "goods_type" ], $where)
+ ->field($field)
+ ->withJoin([
+ 'goodsSku' => [ 'sku_id', 'sku_name', 'goods_id', 'price', 'stock', 'sku_spec_format' ],
+ ])
+ ->with([
+ 'skuList'
+ ])
+ ->where($sku_where)->order($order)->append([ 'goods_type_name', 'goods_cover_thumb_small', 'goods_cover_thumb_mid' ]);
+ $list = $this->pageQuery($search_model);
+
+ $list[ 'verify_goods_ids' ] = $verify_goods_ids;
+ $list[ 'verify_sku_ids' ] = $verify_sku_ids;
+
+ return $list;
+ }
+
+ /**
+ * 获取商品选择分页列表
+ * @param array $where
+ * @return array
+ */
+ public function getSelectSku(array $where = [])
+ {
+ $field = ' goods_id, goods_name, goods_type, goods_cover, stock,is_gift';
+ $order = 'sort desc,create_time desc';
+
+ $select_goods_list = [];// 已选商品列表
+
+ if (isset($where[ 'is_gift' ]) && $where[ 'is_gift' ] == GoodsDict::IS_GIFT) {
+ $sku_where[] = [ 'goods.is_gift', 'in', [ GoodsDict::NOT_IS_GIFT, GoodsDict::IS_GIFT ] ];
+ } else {
+ $sku_where[] = [ 'goods.is_gift', '=', GoodsDict::NOT_IS_GIFT ];
+ }
+
+ // 检测商品id集合是否存在,移除不存在的商品id,纠正数据准确性
+ if (!empty($where[ 'verify_goods_ids' ])) {
+ $verify_goods_ids = $this->model->where([
+ [ 'goods_id', 'in', $where[ 'verify_goods_ids' ] ],
+ [ 'status', '=', 1 ]
+ ])->field('goods_id')->select()->toArray();
+
+ if (!empty($verify_goods_ids)) {
+ $verify_goods_ids = array_column($verify_goods_ids, 'goods_id');
+ }
+
+ $select_goods_list = $this->model
+ ->field($field)
+ ->withJoin([
+ 'goodsSku' => [ 'sku_id', 'sku_name', 'goods_id', 'price', 'stock', 'sku_spec_format' ],
+ ])
+ ->with([
+ 'skuList'
+ ])
+ ->where([
+ [ 'goodsSku.is_default', '=', 1 ],
+ [ 'goods.goods_id', 'in', $verify_goods_ids ]
+ ])
+ ->where($sku_where)
+ ->order($order)->append([ 'goods_type_name', 'goods_cover_thumb_small', 'goods_cover_thumb_mid' ])
+ ->select()->toArray();
+ }
+
+ // 检测商品id集合是否存在,移除不存在的商品id,纠正数据准确性
+ if (!empty($where[ 'verify_sku_ids' ])) {
+ $goods_sku_model = new GoodsSku();
+ $verify_sku_ids = $goods_sku_model->where([
+ [ 'sku_id', 'in', $where[ 'verify_sku_ids' ] ]
+ ])->field('sku_id')->select()->toArray();
+
+ if (!empty($verify_sku_ids)) {
+ $verify_sku_ids = array_column($verify_sku_ids, 'sku_id');
+ }
+
+ $goods_ids = $goods_sku_model->where([
+ [ 'sku_id', 'in', $verify_sku_ids ]
+ ])->field('goods_id')->select()->toArray();
+ if (!empty($goods_ids)) {
+ $goods_ids = array_column($goods_ids, 'goods_id');
+ $goods_ids = array_unique($goods_ids);
+ }
+
+ $select_goods_list = $this->model
+ ->field($field)
+ ->withJoin([
+ 'goodsSku' => [ 'sku_id', 'sku_name', 'goods_id', 'price', 'stock', 'sku_spec_format' ],
+ ])
+ ->with([
+ 'skuList'
+ ])
+ ->where([
+ [ 'goodsSku.is_default', '=', 1 ],
+ [ 'goods.goods_id', 'in', $goods_ids ]
+ ])
+ ->where($sku_where)
+ ->order($order)->append([ 'goods_type_name', 'goods_cover_thumb_small', 'goods_cover_thumb_mid' ])
+ ->select()->toArray();
+ }
+
+ return $select_goods_list;
+ }
+
+ /**
+ * 获取商品选择分页列表(代客下单专用)
+ * @param array $where
+ * @return array
+ */
+ public function getBuyGoodsSelect(array $where = [])
+ {
+ $field = ' goods_id, goods_name, goods_type, goods_cover,goods_image, stock,sub_title,goods_desc,is_limit,limit_type,max_buy,min_buy,member_discount';
+ $order = 'sort desc,create_time desc';
+
+ $sku_where = [
+ [ 'goodsSku.is_default', '=', 1 ],
+ [ 'goods.stock', '>', 0 ],
+ [ 'status', '=', 1 ],
+ [ 'goods.is_gift', '=', GoodsDict::NOT_IS_GIFT ]
+ ];
+
+ if (!empty($where[ 'keyword' ])) {
+ $sku_where[] = [ 'goods_name|sub_title', 'like', '%' . $where[ 'keyword' ] . '%' ];
+ }
+
+ $search_model = $this->model
+ ->withSearch([ "goods_category", "goods_type" ], $where)
+ ->field($field)
+ ->withJoin([
+ 'goodsSku' => [ 'sku_id', 'sku_name', 'goods_id', 'price', 'stock', 'sku_spec_format', 'market_price', 'sale_price', 'member_price' ],
+ ])
+ ->where($sku_where)->order($order)->append([ 'goods_type_name', 'goods_cover_thumb_small', 'goods_cover_thumb_mid' ]);
+ $list = $this->pageQuery($search_model);
+ if (!empty($where[ 'member_id' ])) {
+ $member_info = $this->getMemberInfo($where[ 'member_id' ]);
+ foreach ($list[ 'data' ] as $k => &$v) {
+ if (!empty($v[ 'goodsSku' ])) {
+ $v[ 'goodsSku' ][ 'member_price' ] = $this->getMemberPrice($member_info, $v[ 'member_discount' ], $v[ 'goodsSku' ][ 'member_price' ], $v[ 'goodsSku' ][ 'price' ]);
+ }
+ // 限购查询当前会员已购数量
+ $has_buy = ( new CoreGoodsLimitBuyService() )->getGoodsHasBuyNumber($where[ 'member_id' ], $v[ 'goods_id' ]);
+ $v[ 'has_buy' ] = $has_buy;
+ // 满减活动
+ $manjian_info = ( new ManjianService() )->getManjianInfo([ 'goods_id' => $v[ 'goods_id' ], 'sku_id' => $v[ 'goodsSku' ][ 'sku_id' ], 'member_id' => $where[ 'member_id' ] ]);
+ $v[ 'manjian_info' ] = $manjian_info;
+ }
+ }
+ return $list;
+ }
+
+ /**
+ * 获取已选商品分页列表(代客下单专用)
+ * @param array $where
+ * @return array
+ */
+ public function getBuyGoodsSelected(array $where = [])
+ {
+ $field = 'sku_id, goods_id, sku_name, sku_image, price, stock, member_price, sale_price';
+ $goods_sku_model = new GoodsSku();
+ $select_goods_list = $goods_sku_model->where([
+ [ 'sku_id', 'in', $where[ 'sku_ids' ] ]
+ ])->with([ 'goods' ])->field($field)->append([ 'goods_cover_thumb_small', 'goods_cover_thumb_mid' ])->select()->toArray();
+ if (!empty($where[ 'member_id' ])) {
+ $member_info = $this->getMemberInfo($where[ 'member_id' ]);
+ foreach ($select_goods_list as $k => &$v) {
+ if (!empty($v[ 'goods' ])) {
+ $v[ 'member_price' ] = $this->getMemberPrice($member_info, $v[ 'goods' ][ 'member_discount' ], $v[ 'member_price' ], $v[ 'price' ]);
+ }
+ // 限购查询当前会员已购数量
+ $has_buy = ( new CoreGoodsLimitBuyService() )->getGoodsHasBuyNumber( $where[ 'member_id' ], $v[ 'goods_id' ]);
+ $v[ 'has_buy' ] = $has_buy;
+ // 满减活动
+ $manjian_info = ( new ManjianService() )->getManjianInfo([ 'goods_id' => $v[ 'goods_id' ], 'sku_id' => $v[ 'sku_id' ], 'member_id' => $where[ 'member_id' ] ]);
+ $v[ 'manjian_info' ] = $manjian_info;
+ }
+ }
+ return $select_goods_list;
+ }
+
+ /**
+ * 获取商品规格信息,切换规格(代客下单专用)
+ * @param array $data
+ * @return array
+ */
+ public function getBuySkuSelect(array $data)
+ {
+
+ $field = 'sku_id, sku_name, sku_image, sku_no, goods_id, sku_spec_format, price, market_price, sale_price, stock, weight, volume, sale_num, is_default,member_price';
+
+ $goods_sku_model = new GoodsSku();
+
+ $info = $goods_sku_model->where([ [ 'sku_id', '=', $data[ 'sku_id' ] ] ])
+ ->field($field)
+ ->with([
+ // 商品主表
+ 'goods' => function ($query) {
+ $query->withField('goods_id, goods_name, goods_type, sub_title, goods_cover, unit, stock, sale_num + virtual_sale_num as sale_num, status,member_discount,is_discount')
+ ->append([ 'goods_type_name', 'goods_cover_thumb_small', 'goods_cover_thumb_mid', 'goods_cover_thumb_big' ]);
+ },
+ // 商品规格列表
+ 'skuList' => function ($query) {
+ $query->field(' sku_id, sku_name, sku_image, sku_no, goods_id, sku_spec_format, price, market_price, sale_price, stock, weight, volume, is_default,member_price');
+ },
+ // 商品规格项/规格值列表
+ 'goodsSpec' => function ($query) {
+ $query->field('spec_id, goods_id, spec_name, spec_values');
+ },
+ ])
+ ->append([ 'sku_image_thumb_small', 'sku_image_thumb_mid', 'sku_image_thumb_big' ])
+ ->findOrEmpty()->toArray();
+ if (!empty($info) && !empty($data[ 'member_id' ])) {
+ $member_info = $this->getMemberInfo($data[ 'member_id' ]);
+
+ $info[ 'member_price' ] = $this->getMemberPrice($member_info, $info[ 'goods' ][ 'member_discount' ], $info[ 'member_price' ], $info[ 'price' ]);
+
+ $this->getMemberPriceByList($member_info, $info[ 'goods' ][ 'member_discount' ], $info[ 'skuList' ]);
+ // 限购查询当前会员已购数量
+ $has_buy = ( new CoreGoodsLimitBuyService() )->getGoodsHasBuyNumber( $data[ 'member_id' ], $info[ 'goods_id' ]);
+ $info[ 'has_buy' ] = $has_buy;
+ // 满减活动
+ $manjian_info = ( new ManjianService() )->getManjianInfo([ 'goods_id' => $info[ 'goods_id' ], 'sku_id' => $info[ 'sku_id' ], 'member_id' => $data[ 'member_id' ] ]);
+ $info[ 'manjian_info' ] = $manjian_info;
+ }
+
+ return $info;
+ }
+
+ /**
+ * 查询商品SKU规格列表
+ * @param $params
+ * @return array
+ */
+ public function getSkuList($params)
+ {
+ $goods_sku_model = new GoodsSku();
+
+ $field = 'sku_id, sku_name, sku_image,sku_no, goods_id, sku_spec_format, price, market_price, sale_price, cost_price, stock, weight, volume,member_price';
+ $order = 'sku_id asc';
+ $list = $goods_sku_model->where([ [ 'sku_id', '>', 0 ] ])->withSearch([ "goods_id" ], [ 'goods_id' => $params[ 'goods_id' ] ])->with([ 'goods' ])->field($field)->order($order)->select()->toArray();
+ return $list;
+ }
+
+ /**
+ * 商品数统计
+ * @return int[]
+ * @throws \think\db\exception\DbException
+ */
+ public function getGoodsCount()
+ {
+ $data = [
+ "sale_goods_num" => 0, //销售
+ "warehouse_goods_num" => 0, //仓库
+ ];
+
+ $data[ 'sale_goods_num' ] = $this->model->where([ [ 'status', '=', 1 ] ])->count();
+ $data[ 'warehouse_goods_num' ] = $this->model->where([ [ 'status', '=', 0 ] ])->count();
+ return $data;
+ }
+
+ /**
+ * 编辑商品规格列表库存
+ * @param $params
+ * @return array|bool
+ */
+ public function editGoodsListStock($params)
+ {
+ try {
+ Db::startTrans();
+
+ $goods_info = $this->model->where([
+ [ 'goods_id', '=', $params[ 'goods_id' ] ],
+ ])->field('goods_type')->findOrEmpty()->toArray();
+
+ if (empty($goods_info)) {
+ throw new CommonException('SHOP_GOODS_NOT_EXIST');
+ }
+
+ $sku_list = $params[ 'sku_list' ];
+ if (!empty($sku_list)) {
+ $goods_stock = 0; // 总库存
+ $goods_sku_model = new GoodsSku();
+ foreach ($sku_list as $k => $v) {
+ $goods_stock += (int) $v[ 'stock' ];
+
+ $update_data = [
+ 'stock' => $v[ 'stock' ],
+ ];
+
+ $goods_sku_model->where([
+ [ 'goods_id', '=', $params[ 'goods_id' ] ],
+ [ 'sku_id', '=', $v[ 'sku_id' ] ]
+ ])->update($update_data);
+ }
+ $this->model->where([
+ [ 'goods_id', '=', $params[ 'goods_id' ] ]
+ ])->update([
+ 'stock' => $goods_stock,
+ ]);
+ }
+ Db::commit();
+ return true;
+ } catch (\Exception $e) {
+ Db::rollback();
+ throw new CommonException($e->getMessage());
+ }
+ }
+
+ /**
+ * 编辑商品规格列表价格
+ * @param $params
+ * @return array|bool
+ */
+ public function editGoodsListPrice($params)
+ {
+ try {
+ Db::startTrans();
+
+ $goods_info = $this->model->where([
+ [ 'goods_id', '=', $params[ 'goods_id' ] ],
+ ])->field('goods_id,goods_type')->findOrEmpty()->toArray();
+
+ if (empty($goods_info)) {
+ throw new CommonException('SHOP_GOODS_NOT_EXIST');
+ }
+
+ // 查询商品参与营销活动的数量
+ $active_goods_count = $this->getActiveGoodsCount($goods_info[ 'goods_id' ]);
+
+ $sku_list = $params[ 'sku_list' ];
+ if (!empty($sku_list)) {
+ $goods_sku_model = new GoodsSku();
+ foreach ($sku_list as $k => $v) {
+ $update_data = [
+ 'cost_price' => $v[ 'cost_price' ],
+ 'market_price' => $v[ 'market_price' ],
+ ];
+
+ if ($active_goods_count == 0) {
+ $update_data[ 'price' ] = $v[ 'price' ];
+ $update_data[ 'sale_price' ] = $v[ 'price' ];
+ }
+
+ $goods_sku_model->where([
+ [ 'goods_id', '=', $params[ 'goods_id' ] ],
+ [ 'sku_id', '=', $v[ 'sku_id' ] ]
+ ])->update($update_data);
+ }
+ }
+ Db::commit();
+ return true;
+ } catch (\Exception $e) {
+ Db::rollback();
+ throw new CommonException($e->getMessage());
+ }
+ }
+
+ /**
+ * 编辑商品规格列表会员价格
+ * @param $params
+ * @return array|bool
+ */
+ public function editGoodsListMemberPrice($params)
+ {
+ try {
+ Db::startTrans();
+
+ $goods_info = $this->model->where([
+ [ 'goods_id', '=', $params[ 'goods_id' ] ],
+ ])->field('goods_type')->findOrEmpty()->toArray();
+
+ if (empty($goods_info)) {
+ throw new CommonException('SHOP_GOODS_NOT_EXIST');
+ }
+
+ // 修改商品的会员等级折扣
+ $this->model->where([
+ [ 'goods_id', '=', $params[ 'goods_id' ] ],
+ ])->update([
+ 'member_discount' => $params[ 'member_discount' ]
+ ]);
+
+ $sku_list = $params[ 'sku_list' ];
+ if (!empty($sku_list)) {
+ $goods_sku_model = new GoodsSku();
+ foreach ($sku_list as $k => $v) {
+ $update_data = [
+ 'member_price' => json_encode($v[ 'member_price' ]),
+ ];
+
+ $goods_sku_model->where([
+ [ 'goods_id', '=', $params[ 'goods_id' ] ],
+ [ 'sku_id', '=', $v[ 'sku_id' ] ]
+ ])->update($update_data);
+ }
+ }
+ Db::commit();
+ return true;
+ } catch (\Exception $e) {
+ Db::rollback();
+ throw new CommonException($e->getMessage() . ',Line:' . $e->getLine() . ',File:' . $e->getFile());
+ }
+ }
+
+ /**
+ * 查询商品参与营销活动的数量
+ * @param $goods_id
+ * @return mixed
+ */
+ public function getActiveGoodsCount($goods_id, $is_all = 0, $where = [])
+ {
+ // 判断 $goods_id 类型
+ if (!is_array($goods_id)) {
+ $goods_id = [ $goods_id ];
+ }
+
+ $join_list = event('GetGoodsJoinInfo', [
+ 'goods_ids' => $goods_id,
+ 'is_get_count' => 1,
+ 'is_all' => $is_all,
+ 'where' => $where,
+ ]);
+ return array_sum($join_list);
+ }
+
+ /**
+ * 查询商品参与营销活动的数量
+ * @param $goods_id
+ * @return mixed
+ */
+ public function getActiveGoodsIds($goods_id, $is_all = 0, $where = [])
+ {
+ // 判断 $goods_id 类型
+ if (!is_array($goods_id)) {
+ $goods_id = [ $goods_id ];
+ }
+
+ $join_list = event('GetGoodsJoinInfo', [
+ 'goods_ids' => $goods_id,
+ 'is_get_count' => 0,
+ 'is_all' => $is_all,
+ 'where' => $where,
+ ]);
+ $goods_ids = [];
+ foreach ($join_list as $item) {
+ $goods_ids = array_merge($goods_ids, array_keys($item));
+ }
+ return $goods_ids;
+ }
+
+ public function getMemberInfo($member_id)
+ {
+ $member_model = new Member();
+ $member_field = 'member_level';
+ $member_info = $member_model->where([
+ [ 'member_id', '=', $member_id ]
+ ])->field($member_field)
+ ->with([
+ // 会员等级
+ 'memberLevelData' => function ($query) {
+ $query->field('level_id, level_name, status, level_benefits, level_gifts');
+ },
+ ])
+ ->findOrEmpty()->toArray();
+ return $member_info;
+ }
+
+ /**
+ * 查询商品的会员价
+ * @param $member_info
+ * @param string $member_discount 会员等级折扣,不参与:空,会员折扣:discount,指定会员价:fixed_price
+ * @param string $member_price 会员价,json格式,指定会员价,数据结构为:{"level_12":"92.00","level_13":"72.00","level_14":"66.00","level_15":"45.00"}
+ * @param $price
+ * @return int|string
+ */
+ public function getMemberPrice($member_info, $member_discount, $member_price, $price)
+ {
+ if (empty($member_discount)) {
+ return $price;
+ }
+
+ // 未找到会员,排除
+ if (empty($member_info)) {
+ return $price;
+ }
+
+ // 没有会员等级,排除
+ if (!empty($member_info) && empty($member_info[ 'member_level' ])) {
+ return $price;
+ }
+
+ if ($member_discount == 'discount') {
+ // 按照会员等级折扣计算
+
+ // 默认按会员享受折扣计算
+ if (!empty($member_info[ 'memberLevelData' ][ 'level_benefits' ])
+ && !empty($member_info[ 'memberLevelData' ][ 'level_benefits' ][ 'discount' ])
+ && !empty($member_info[ 'memberLevelData' ][ 'level_benefits' ][ 'discount' ][ 'is_use' ])) {
+
+ $price = number_format($price * $member_info[ 'memberLevelData' ][ 'level_benefits' ][ 'discount' ][ 'discount' ] / 10, 2, '.', '');
+ }
+
+ } elseif ($member_discount == 'fixed_price') {
+ // 指定会员价
+ if (!empty($member_price)) {
+ $member_price = json_decode($member_price, true);
+ if (!empty($member_price[ 'level_' . $member_info[ 'member_level' ] ])) {
+ $member_level_price = $member_price[ 'level_' . $member_info[ 'member_level' ] ];
+ $price = number_format($member_level_price, 2, '.', '');
+ }
+ }
+ }
+
+ return $price;
+
+ }
+
+ /**
+ * 查询商品的会员价
+ * @param $member_info
+ * @param string $member_discount 会员等级折扣,不参与:空,会员折扣:discount,指定会员价:fixed_price
+ * @param $sku_list
+ * @return int
+ */
+ public function getMemberPriceByList($member_info, $member_discount, &$sku_list)
+ {
+
+ // 是否按照原价返回
+ $is_default = false;
+
+ if (empty($member_discount)) {
+ $is_default = true;
+ }
+
+ // 未找到会员,排除
+ if (empty($member_info)) {
+ $is_default = true;
+ }
+
+ // 没有会员等级,排除
+ if (!empty($member_info) && empty($member_info[ 'member_level' ])) {
+ $is_default = true;
+ }
+
+ foreach ($sku_list as $k => &$v) {
+
+ if ($is_default) {
+ $v[ 'member_price' ] = $v[ 'price' ];
+ } else {
+ if ($member_discount == 'discount') {
+ // 按照会员等级折扣计算
+
+ // 默认按会员享受折扣计算
+ if (!empty($member_info[ 'memberLevelData' ][ 'level_benefits' ])
+ && !empty($member_info[ 'memberLevelData' ][ 'level_benefits' ][ 'discount' ])
+ && !empty($member_info[ 'memberLevelData' ][ 'level_benefits' ][ 'discount' ][ 'is_use' ])) {
+ $v[ 'member_price' ] = number_format($v[ 'price' ] * $member_info[ 'memberLevelData' ][ 'level_benefits' ][ 'discount' ][ 'discount' ] / 10, 2, '.', '');
+ } else {
+ $v[ 'member_price' ] = $v[ 'price' ];
+ }
+
+ } elseif ($member_discount == 'fixed_price') {
+ // 指定会员价
+ if (!empty($v[ 'member_price' ])) {
+ $member_price = json_decode($v[ 'member_price' ], true); // 会员价,json格式,指定会员价
+ if (!empty($member_price[ 'level_' . $member_info[ 'member_level' ] ])) {
+ $member_level_price = $member_price[ 'level_' . $member_info[ 'member_level' ] ];
+ $v[ 'member_price' ] = number_format($member_level_price, 2, '.', '');
+ } else {
+ $v[ 'member_price' ] = $v[ 'price' ];
+ }
+ }
+ }
+ }
+ }
+
+ return $sku_list;
+ }
+
+ /**
+ * 批量设置商品
+ * @param $data
+ * @return mixed
+ */
+ public function batchSet($data)
+ {
+ $is_all = $data[ 'is_all' ];
+ $goods_ids = $data[ 'goods_ids' ];
+ if (empty($data[ 'set_type' ])) throw new AdminException('NOT_GET_SET_TYPE');
+ if (!$is_all && empty($goods_ids)) throw new AdminException('NOT_GET_SHOP_INFO');
+ $save_data = $filed_data = $sku_save_data = [];
+ switch ($data[ 'set_type' ]) {
+ case GoodsDict::LABEL :
+ $filed_data[ 'label' ][ 'label_ids' ] = array_map(function ($item) {
+ return (string) $item;
+ }, $data[ 'set_value' ][ 'label_ids' ]);
+ break;
+ case GoodsDict::SERVICE :
+ $filed_data[ 'service' ][ 'service_ids' ] = array_map(function ($item) {
+ return (string) $item;
+ }, $data[ 'set_value' ][ 'service_ids' ]);
+ break;
+ case GoodsDict::VIRTUAL_SALE_NUM :
+ $filed_data[ 'virtual_sale_num' ][ 'virtual_sale_num' ] = $data[ 'set_value' ][ 'virtual_sale_num' ];
+ break;
+ case GoodsDict::CATEGORY :
+ if (!isset($data[ 'set_value' ][ 'goods_category' ]) || empty($data[ 'set_value' ][ 'goods_category' ])) break;
+ $filed_data[ 'category' ][ 'goods_category' ] = array_map(function ($item) {
+ return (string) $item;
+ }, $data[ 'set_value' ][ 'goods_category' ]);
+ break;
+ case GoodsDict::BRAND :
+ $filed_data[ 'brand' ][ 'brand_id' ] = $data[ 'set_value' ][ 'brand_id' ];
+ break;
+ case GoodsDict::POSTER :
+ $filed_data[ 'poster' ][ 'poster_id' ] = $data[ 'set_value' ][ 'poster_id' ];
+ break;
+ case GoodsDict::DIY_FORM :
+ $filed_data[ 'diy_form' ][ 'form_id' ] = $data[ 'set_value' ][ 'form_id' ];
+ break;
+ case GoodsDict::GIFT :
+ if (!isset($data[ 'set_value' ][ 'is_gift' ]) || !in_array($data[ 'set_value' ][ 'is_gift' ], [ GoodsDict::IS_GIFT, GoodsDict::NOT_IS_GIFT ])) break;
+ $filed_data[ 'gift' ][ 'is_gift' ] = $data[ 'set_value' ][ 'is_gift' ];
+ break;
+ case GoodsDict::DELIVERY :
+ if (!isset($data[ 'set_value' ][ 'delivery_type' ]) || empty($data[ 'set_value' ][ 'delivery_type' ])) break;
+ $filed_data[ 'delivery' ][ 'delivery_type' ] = array_map(function ($item) {
+ return (string) $item;
+ }, $data[ 'set_value' ][ 'delivery_type' ] ?? []);
+ $filed_data[ 'delivery' ][ 'is_free_shipping' ] = $data[ 'set_value' ][ 'is_free_shipping' ] ?? 1;
+ $filed_data[ 'delivery' ][ 'fee_type' ] = $data[ 'set_value' ][ 'fee_type' ] ?? 'template';
+ $filed_data[ 'delivery' ][ 'delivery_money' ] = $data[ 'set_value' ][ 'delivery_money' ] ?? 0;
+ $filed_data[ 'delivery' ][ 'delivery_template_id' ] = $data[ 'set_value' ][ 'delivery_template_id' ] ?? 0;
+ break;
+ case GoodsDict::MEMBER_DISCOUNT :
+ $filed_data[ 'member_discount' ][ 'member_discount' ] = $data[ 'set_value' ][ 'member_discount' ];
+ break;
+ case GoodsDict::DIY_DETAIL :
+ $filed_data[ 'diy_detail' ][ 'diy_detail_id' ] = $data[ 'set_value' ][ 'diy_detail_id' ];
+ break;
+ case GoodsDict::STOCK :
+ if (!isset($data[ 'set_value' ][ 'stock_type' ]) || empty($data[ 'set_value' ][ 'stock_type' ]) || !isset($data[ 'set_value' ][ 'stock' ]) || $data[ 'set_value' ][ 'stock' ] <= 0) break;
+ $update_stock = (int) $data[ 'set_value' ][ 'stock' ];
+
+ if ($data[ 'set_value' ][ 'stock_type' ] == 'inc') {
+ if ($is_all) {
+ $query = $this->getBatchAllQuery($data[ 'where' ], $goods_ids);
+ } else {
+ $query = GoodsSku::alias('goodsSku')
+ ->join(( new Goods() )->getTable() . ' goods', 'goods.goods_id = goodsSku.goods_id')
+ ->whereIn('goods.goods_id', $goods_ids);
+ }
+ $query->update([
+ 'goodsSku.stock' => Db::raw("goodsSku.stock + {$update_stock}"),
+ ]);
+ } else {
+ if ($is_all) {
+ $query = $this->getBatchAllQuery($data[ 'where' ], $goods_ids);
+ } else {
+ $query = GoodsSku::alias('goodsSku')
+ ->join(( new Goods() )->getTable() . ' goods', 'goods.goods_id = goodsSku.goods_id') // 使用INNER JOIN更安全
+ ->whereIn('goods.goods_id', $goods_ids);
+ }
+ $query->update([
+ 'goodsSku.stock' => Db::raw("CASE WHEN goodsSku.stock >= $update_stock THEN goodsSku.stock - $update_stock ELSE 0 END"),
+ ]);
+ }
+
+ if ($is_all) {
+ $query = $this->getBatchAllQuery($data[ 'where' ], $goods_ids);
+ $query->update([
+ 'goods.stock' => Db::raw("(SELECT COALESCE(SUM(stock), 0) FROM " . ( new GoodsSku() )->getTable() . " WHERE goods_id = goods.goods_id )")
+ ]);
+ } else {
+ $query = Goods::alias('goods');
+ $query = $query->whereIn('goods.goods_id', $goods_ids);
+ $query->update([
+ 'stock' => Db::raw("(SELECT COALESCE(SUM(stock), 0) FROM " . ( new GoodsSku() )->getTable() . " WHERE goods_id = goods.goods_id )")
+ ]);
+ }
+
+ return true;
+ }
+
+ if (!empty($filed_data)) {
+ $field = array_keys($filed_data)[ 0 ];
+ if ($is_all) {
+ $update = $filed_data[ $field ];
+ $update_data = [];
+ foreach ($update as $column => $value) {
+ $update_data[ 'goods.' . $column ] = is_array($value) ? json_encode($value) : $value;
+ }
+ $query = $this->getBatchAllQuery($data[ 'where' ], $goods_ids);
+ if ($data[ 'set_type' ] == GoodsDict::DELIVERY) {
+ $query = $query->where([ [ 'goods_type', '=', GoodsDict::REAL ] ]);
+ }
+ $res = $query->update($update_data);
+ if ($data[ 'set_type' ] == GoodsDict::MEMBER_DISCOUNT) {
+ $goods_ids = $query->column('goods.goods_id');
+ }
+ } else {
+ if ($data[ 'set_type' ] == GoodsDict::DELIVERY) {
+ $goods_ids = $this->model->where([ [ 'goods_id', 'in', $goods_ids ], [ 'goods_type', '=', GoodsDict::REAL ] ])->column('goods_id');
+ }
+ foreach ($goods_ids as $k => $v) {
+ $save_data[ $k ] = $filed_data[ $field ];
+ $save_data[ $k ][ 'goods_id' ] = $v;
+ }
+ $this->model->saveAll($save_data);
+ }
+ if ($data[ 'set_type' ] == GoodsDict::MEMBER_DISCOUNT && !empty($goods_ids)) {
+ ( new GoodsSku() )->where([ [ 'goods_id', 'in', $goods_ids ] ])->update([ 'member_price' => '' ]);
+ }
+ }
+
+ return true;
+ }
+
+ public function getBatchAllQuery($where, $example_goods_ids = [])
+ {
+ $sku_where = [
+ [ 'goodsSku.is_default', '=', 1 ],
+ ];
+
+ if (!empty($where[ 'start_price' ]) && !empty($where[ 'end_price' ])) {
+ $money = [ $where[ 'start_price' ], $where[ 'end_price' ] ];
+ sort($money);
+ $sku_where[] = [ 'goodsSku.price', 'between', $money ];
+ } else if (!empty($where[ 'start_price' ])) {
+ $sku_where[] = [ 'goodsSku.price', '>=', $where[ 'start_price' ] ];
+ } else if (!empty($where[ 'end_price' ])) {
+ $sku_where[] = [ 'goodsSku.price', '<=', $where[ 'end_price' ] ];
+ }
+
+ return Goods::alias('goods')->where([ [ 'goods.goods_id', '>', 0 ] ])->withSearch([ "goods_name", "goods_type", "brand_id", "goods_category", "label_ids", 'service_ids', "sale_num", "status" ], $where)
+ ->withJoin([ 'goodsSku' ])->where($sku_where)->whereNotIn('goods.goods_id', $example_goods_ids);
+ }
+
+ /**
+ * 获取商品排行榜统计类型
+ * @return array
+ */
+ public function getBatchSetDict()
+ {
+ $list = GoodsDict::getBatchSetDict();
+ return $list;
+ }
+
+ /**
+ * 分类调整时使用(分类登记变化) 数据较多时需优化 Job
+ * @return void
+ */
+ public function batchUpdateCategory($category_id, $old_pid, $new_pid)
+ {
+ $goods_category = [];
+
+ $category_goods_list = ( new Goods() )->where([
+ ])->withSearch([ 'goods_category' ], [
+ 'goods_category' => $category_id
+ ])->select()->toArray();
+ if ($old_pid != 0 && $new_pid == 0) {
+
+ foreach ($category_goods_list as $item) {
+
+ $goods_category = array_map(function ($value) {
+ return (string) $value;
+ }, $goods_category);
+ ( new Goods() )->where([
+ [ 'goods_id', '=', $item[ 'goods_id' ] ]
+ ])->update([
+ 'goods_category' => array_values($goods_category)
+ ]);
+
+ }
+ }
+
+ foreach ($category_goods_list as $item) {
+ //将无二级分类的顶级分类调整为二级分类
+ $item_category = $item[ 'goods_category' ];
+ if ($old_pid == 0 && $new_pid != 0) {
+ $item_category[] = $new_pid;
+ } else
+ if ($old_pid != 0 && $new_pid == 0) { //将二级分类调整为顶级分类
+ foreach ($item_category as $k => $value) {
+ if ($value == $old_pid) {
+ unset($item_category[ $k ]);
+ }
+ }
+ }
+ $item_category = array_map(function ($value) {
+ return (string) $value;
+ }, $item_category);
+ ( new Goods() )->where([
+ [ 'goods_id', '=', $item[ 'goods_id' ] ]
+ ])->update([
+ 'goods_category' => array_values($item_category)
+ ]);
+ }
+ }
+
+}
diff --git a/niucloud/addon/shop/app/service/admin/goods/LabelGroupService.php b/niucloud/addon/shop/app/service/admin/goods/LabelGroupService.php
new file mode 100644
index 000000000..8f19deffe
--- /dev/null
+++ b/niucloud/addon/shop/app/service/admin/goods/LabelGroupService.php
@@ -0,0 +1,143 @@
+model = new LabelGroup();
+ }
+
+ /**
+ * 获取商品标签分组列表
+ * @param array $where
+ * @return array
+ */
+ public function getPage(array $where = [])
+ {
+ $field = 'group_id, group_name, sort, create_time, update_time';
+ $order = 'group_id desc';
+ if (!empty($where[ 'order' ])) {
+ $order = $where[ 'order' ] . ' ' . $where[ 'sort' ];
+ }
+
+ $search_model = $this->model->where([ [ 'group_id', '>', 0 ] ])->withSearch([ "group_name" ], $where)->field($field)->order($order);
+ $list = $this->pageQuery($search_model);
+ return $list;
+ }
+
+ /**
+ * 获取商品标签分组列表
+ * @param array $where
+ * @param string $field
+ * @return array
+ */
+ public function getList(array $where = [], $field = 'group_id, group_name, sort, create_time, update_time')
+ {
+ $order = 'sort desc,group_id desc';
+ return $this->model->where([ [ 'group_id', '>', 0 ] ])->withSearch([ "group_name" ], $where)->field($field)->order($order)->select()->toArray();
+ }
+
+ /**
+ * 获取商品标签分组信息
+ * @param int $id
+ * @return array
+ */
+ public function getInfo(int $id)
+ {
+ $field = 'group_id, group_name, sort, create_time, update_time';
+
+ $info = $this->model->field($field)->where([ [ 'group_id', '=', $id ] ])->findOrEmpty()->toArray();
+ return $info;
+ }
+
+ /**
+ * 添加商品标签分组
+ * @param array $data
+ * @return mixed
+ */
+ public function add(array $data)
+ {
+ $data[ 'create_time' ] = time();
+ $brandInfo = $this->model->where([ [ 'group_name', '=', $data[ 'group_name' ] ] ])->findOrEmpty()->toArray();
+ if ($brandInfo) {
+ throw new AdminException('标签分组已存在,请检查');
+ }
+ $res = $this->model->create($data);
+ return $res->group_id;
+ }
+
+ /**
+ * 商品标签分组编辑
+ * @param int $id
+ * @param array $data
+ * @return bool
+ */
+ public function edit(int $id, array $data)
+ {
+ $data[ 'update_time' ] = time();
+ $labelInfo = $this->model->where([ [ 'group_name', '=', $data[ 'group_name' ] ] ])->findOrEmpty()->toArray();
+ if ($labelInfo && $labelInfo[ 'group_id' ] != $id) {
+ throw new AdminException('标签分组已存在,请检查');
+ }
+
+ $this->model->where([ [ 'group_id', '=', $id ] ])->update($data);
+ return true;
+ }
+
+ /**
+ * 删除商品标签分组
+ * @param int $id
+ * @return bool
+ */
+ public function del(int $id)
+ {
+ // 检测商品标签分组是否被使用
+ $label_model = new Label();
+ $label_count = $label_model->where([
+ [ 'group_id', '=', $id ]
+ ])->count();
+ if ($label_count) {
+ throw new AdminException('该标签分组正在使用中,无法删除');
+ }
+
+ $model = $this->model->where([ [ 'group_id', '=', $id ] ])->find();
+ $res = $model->delete();
+ return $res;
+ }
+
+ /**
+ * 修改排序
+ * @param $data
+ * @return mixed
+ */
+ public function modifySort($data)
+ {
+ return $this->model->where([
+ [ 'group_id', '=', $data[ 'group_id' ] ],
+ ])->update([ 'sort' => $data[ 'sort' ] ]);
+ }
+
+}
diff --git a/niucloud/addon/shop/app/service/admin/goods/LabelService.php b/niucloud/addon/shop/app/service/admin/goods/LabelService.php
new file mode 100644
index 000000000..e5a8f58af
--- /dev/null
+++ b/niucloud/addon/shop/app/service/admin/goods/LabelService.php
@@ -0,0 +1,186 @@
+model = new Label();
+ }
+
+ /**
+ * 获取商品标签列表
+ * @param array $where
+ * @return array
+ */
+ public function getPage(array $where = [])
+ {
+ $field = 'label_id, label_name, group_id, style_type, color_json, icon, status, memo, sort, create_time, update_time';
+ $order = 'label_id desc';
+ if (!empty($where[ 'order' ])) {
+ $order = $where[ 'order' ] . ' ' . $where[ 'sort' ];
+ }
+
+ $search_model = $this->model->where([ [ 'label_id', '>', 0 ]])->withSearch([ "label_name", 'group_id' ], $where)->field($field)
+ ->with([
+ 'group' => function($query) {
+ $query->field('group_id, group_name');
+ },
+ ])
+ ->order($order);
+ $list = $this->pageQuery($search_model);
+ return $list;
+ }
+
+ /**
+ * 获取商品标签列表
+ * @param array $where
+ * @param string $field
+ * @return array
+ */
+ public function getList(array $where = [], $field = 'label_id, label_name, group_id, style_type, color_json, icon, status, memo, sort, create_time, update_time')
+ {
+ $order = 'sort desc,label_id desc';
+ return $this->model->where([ ['status','=',LabelDict::ENABLE]])->withSearch([ "label_name" ], $where)->field($field)
+ ->with([
+ 'group' => function($query) {
+ $query->field('group_id, group_name');
+ },
+ ])->order($order)->select()->toArray();
+ }
+
+ /**
+ * 获取商品标签信息
+ * @param int $id
+ * @return array
+ */
+ public function getInfo(int $id)
+ {
+ $field = 'label_id, label_name, group_id, style_type, color_json, icon, status, memo, sort, create_time, update_time';
+
+ $info = $this->model->field($field)->where([ [ 'label_id', '=', $id ] ])
+ ->with([
+ 'group' => function($query) {
+ $query->field('group_id, group_name');
+ },
+ ])->findOrEmpty()->toArray();
+ return $info;
+ }
+
+ /**
+ * 添加商品标签
+ * @param array $data
+ * @return mixed
+ */
+ public function add(array $data)
+ {
+ $data[ 'create_time' ] = time();
+ $brandInfo = $this->model->where([ [ 'label_name', '=', $data[ 'label_name' ] ] ])->findOrEmpty()->toArray();
+ if ($brandInfo) {
+ throw new AdminException('SHOP_GOODS_LABEL_NAME_REPEAT');
+ }
+ $res = $this->model->create($data);
+ return $res->label_id;
+ }
+
+ /**
+ * 商品标签编辑
+ * @param int $id
+ * @param array $data
+ * @return bool
+ */
+ public function edit(int $id, array $data)
+ {
+ $data[ 'update_time' ] = time();
+ $labelInfo = $this->model->where([ [ 'label_name', '=', $data[ 'label_name' ] ] ])->findOrEmpty()->toArray();
+ if ($labelInfo && $labelInfo[ 'label_id' ] != $id) {
+ throw new AdminException('SHOP_GOODS_LABEL_NAME_REPEAT');
+ }
+
+ $this->model->where([ [ 'label_id', '=', $id ] ])->update($data);
+ return true;
+ }
+
+ /**
+ * 删除商品标签
+ * @param int $id
+ * @return bool
+ */
+ public function del(int $id)
+ {
+ // 检测商品标签分组是否被使用
+ $goods_model = new Goods();
+ $count = $goods_model->where([ [ 'goods_id', '>', 0 ] ])->withSearch([ 'label_ids' ], [ 'label_ids' => $id ])->count();
+ if ($count) {
+ throw new AdminException('SHOP_GOODS_LABEL_IN_USE');
+ }
+ $model = $this->model->where([ [ 'label_id', '=', $id ] ])->find();
+ $res = $model->delete();
+ return $res;
+ }
+
+ /**
+ * 修改排序
+ * @param $data
+ * @return Label
+ */
+ public function modifySort($data)
+ {
+ return $this->model->where([
+ [ 'label_id', '=', $data[ 'label_id' ] ]
+ ])->update([ 'sort' => $data[ 'sort' ] ]);
+ }
+
+ /**
+ * 修改状态
+ * @param $data
+ * @return Label
+ */
+ public function modifyStatus($data)
+ {
+ return $this->model->where([
+ [ 'label_id', '=', $data[ 'label_id' ] ]
+ ])->update([ 'status' => $data[ 'status' ] ]);
+ }
+
+ /**
+ * 复制商品标签
+ * @param int $id
+ * @return Label|\think\Model
+ * @throws \think\db\exception\DataNotFoundException
+ * @throws \think\db\exception\DbException
+ * @throws \think\db\exception\ModelNotFoundException
+ */
+ public function copy(int $id)
+ {
+ $field = 'label_name, group_id, style_type, color_json, icon, memo, sort';
+ $label_info = $this->model->field($field)->where('label_id',$id)->find()->toArray();
+ $label_info['label_name'] =$label_info['label_name'].'_副本';
+ $label_info['status'] =0;
+ return $this->model->create($label_info);
+ }
+
+}
diff --git a/niucloud/addon/shop/app/service/admin/goods/OfferGoodsService.php b/niucloud/addon/shop/app/service/admin/goods/OfferGoodsService.php
new file mode 100644
index 000000000..f5c910b66
--- /dev/null
+++ b/niucloud/addon/shop/app/service/admin/goods/OfferGoodsService.php
@@ -0,0 +1,180 @@
+model = new Goods();
+ }
+
+ /**
+ * 获取输出商品初始化数据
+ * @return array
+ */
+ public function getWhereInit()
+ {
+ return [
+ 'label_list' => (new LabelService())->getList(),
+ 'brand_list' => (new BrandService())->getList(),
+ 'category_list' => (new CategoryService())->getTree(),
+ 'type_list' => (new GoodsService())->getType(),
+ ];
+ }
+
+ /**
+ * 输出商品列表
+ * @param $param
+ * @return array
+ * @throws \think\db\exception\DbException
+ */
+ public function getOfferGoodsList($param)
+ {
+ $field = 'goods_id,goods_name,sub_title,goods_image,unit,goods_video,goods_desc,goods_id as source_id,goods_cover,stock';
+ $order = 'create_time desc';
+ $where = [
+ 'status' => 1,
+ 'goods_name' => $param['goods_name'] ?? '',
+ 'goods_type' => $param['goods_type'] ?? '',
+ 'brand_id' => $param['brand_id'] ?? '',
+ 'goods_category' => $param['goods_category'] ?? '',
+ 'label_ids' => $param['label_ids'] ?? '',
+ ];
+ $search_model = $this->model
+ ->withSearch(["goods_name", 'goods_type', 'brand_id', 'goods_category', 'label_ids', "status"], $where)
+ ->field($field)
+ ->with([
+ 'sku_list' => function (Query $query) {
+ $query->field(['goods_id', 'sku_id', 'is_default', 'sku_name', 'sku_image', 'price', 'is_default', 'sku_spec_format', 'sku_id as source_sku_id', 'stock'])->order('is_default desc');
+ },
+ 'goods_spec' => function (Query $query) {
+ $query->field(['goods_id', 'spec_name', 'spec_values']);
+ },
+ ])
+ ->hidden(['goods_id', 'sku_list' => ['goods_id', 'sku_id']])
+ ->append(['goods_cover_thumb_small'])
+ ->order($order);
+ $list = $this->pageQuery($search_model, function (&$item, $key) {
+ $item = $item->toArray();
+ $temp_sku_data = array_filter(array_column($item['sku_list'], 'sku_spec_format'));
+ $item['spec_type'] = 'single';
+ if (!empty($temp_sku_data)) {
+ // 多规格
+ $item['spec_type'] = 'multi';
+ }
+ return $item;
+ });
+ return $list;
+ }
+
+
+ /**
+ * 商品详情
+ * @param $param
+ * @return array
+ */
+ public function getOfferGoodsInfo($param)
+ {
+
+ $field = 'goods_id,goods_name,sub_title,goods_image,goods_video,goods_desc,goods_id as source_id';
+ $order = 'create_time desc';
+ $where = [
+ 'status' => 1,
+ 'goods_id' => $param['goods_id'] ?? '',
+ ];
+
+ $info = $this->model
+ ->withSearch(["goods_id", "status"], $where)
+ ->field($field)
+ ->with([
+ 'sku_list' => function (Query $query) {
+ $query->field(['goods_id', 'sku_id', 'sku_name', 'sku_image', 'price', 'is_default', 'sku_spec_format', 'sku_id as source_sku_id']);
+ },
+ 'goods_spec' => function (Query $query) {
+ $query->field(['goods_id', 'spec_name', 'spec_values']);
+ },
+ ])
+ ->hidden(['goods_id', 'sku_list' => ['goods_id', 'sku_id']])
+ ->append(['goods_cover_thumb_small'])
+ ->order($order)
+ ->findOrEmpty()
+ ->toArray();
+
+ if (!empty($info)) {
+ $temp_sku_data = array_filter(array_column($info['sku_list'], 'sku_spec_format'));
+ $info['spec_type'] = 'single';
+ if (!empty($temp_sku_data)) {
+ // 多规格
+ $info['spec_type'] = 'multi';
+ }
+ }
+ return $info;
+ }
+
+
+ /**
+ * 下单前商品效验
+ * @return array
+ */
+ public function checkGoods($param)
+ {
+
+ $goods_id = $param['goods_id'];
+ $sku_id = $param['sku_id'];
+ $goods_num = $param['num'];
+ $goods_info = $this->model
+ ->where([['goods_id', '=', $goods_id], ['status', '=', 1]])
+ ->with([
+ 'goodsSku' => function (Query $query) {
+ $query->field(['goods_id', 'sku_id', 'stock']);
+ },
+ ])
+ ->hasWhere('goodsSku', function (Query $query) use ($sku_id) {
+ $query->where('sku_id', '=', $sku_id);
+ })
+ ->findOrEmpty()
+ ->toArray();
+
+ if (empty($goods_info)) {
+ return [
+ 'code' => -1,
+ 'message' => '商品不存在或已下架'
+ ];
+ }
+ if ($goods_info['goodsSku']['stock'] < $goods_num) {
+ return [
+ 'code' => -1,
+ 'message' => '商品库存不足'
+ ];
+ }
+ return [
+ 'code' => 1,
+ 'message' => '成功'
+ ];
+ }
+
+
+}
diff --git a/niucloud/addon/shop/app/service/admin/goods/RankService.php b/niucloud/addon/shop/app/service/admin/goods/RankService.php
new file mode 100644
index 000000000..1a69d7088
--- /dev/null
+++ b/niucloud/addon/shop/app/service/admin/goods/RankService.php
@@ -0,0 +1,325 @@
+model = new Rank();
+ }
+
+ /**
+ * 获取商品排行榜列表
+ * @param array $where
+ * @return array
+ */
+ public function getPage(array $where = [])
+ {
+ $field = 'rank_id,name,rank_type,goods_source,rule_type,sort,create_time,goods_json,category_ids,brand_ids,label_ids,status';
+ $order = 'create_time desc';
+ if (!empty($where[ 'order' ])) {
+ $order = $where[ 'order' ] . ' ' . $where[ 'sort' ];
+ }
+
+ $search_model = $this->model
+ ->where([ [ 'rank_id', '>', 0 ] ])
+ ->withSearch([ "name", 'rank_type' ], $where)
+ ->field($field)
+ ->order($order)->append([ 'rank_type_name', 'goods_source_name', 'rule_type_name' ]);
+ $list = $this->pageQuery($search_model);
+ if (!empty($list[ 'data' ])) {
+ $list[ 'data' ] = $this->getShowGodsNum($list[ 'data' ]);
+ }
+ return $list;
+ }
+
+ /**
+ * 获取商品排行榜列表
+ * @param array $where
+ * @param string $field
+ * @return array
+ */
+ public function getList(array $where = [], $field = 'rank_id,name,rank_type,goods_source,rule_type,sort,create_time')
+ {
+ $order = 'create_time desc';
+ return $this->model->where([ [ 'rank_id', '>', 0 ] ])->withSearch([ "name" ], $where)->field($field)->order($order)->select()->toArray();
+ }
+
+ /**
+ * 添加商品榜单
+ * @param array $data
+ * @return mixed
+ */
+ public function add(array $data)
+ {
+ $data[ 'create_time' ] = time();
+ $rankInfo = $this->model->where([ [ 'name', '=', $data[ 'name' ] ] ])->findOrEmpty()->toArray();
+ if ($rankInfo) {
+ throw new AdminException('商品榜单已存在,请检查');
+ }
+ $data = $this->checkRankData($data); // 将其他类型的字段值重置
+ $res = $this->model->create($data);
+ return $res->rank_id;
+ }
+
+ protected function checkRankData($data)
+ {
+ // 重置字段,防止修改后字段值错误
+ if ($data[ 'goods_source' ] == RankDict::GOODS) {
+ $data[ 'category_ids' ] = [];
+ $data[ 'brand_ids' ] = [];
+ $data[ 'label_ids' ] = [];
+ }
+ if ($data[ 'goods_source' ] == RankDict::CATEGORY) {
+ $data[ 'goods_json' ] = [];
+ $data[ 'brand_ids' ] = [];
+ $data[ 'label_ids' ] = [];
+ }
+ if ($data[ 'goods_source' ] == RankDict::BRAND) {
+ $data[ 'category_ids' ] = [];
+ $data[ 'goods_json' ] = [];
+ $data[ 'label_ids' ] = [];
+ }
+ if ($data[ 'goods_source' ] == RankDict::LABEL) {
+ $data[ 'category_ids' ] = [];
+ $data[ 'brand_ids' ] = [];
+ $data[ 'goods_json' ] = [];
+ }
+ return $data;
+ }
+
+ /**
+ * 修改商品榜单
+ * @param int $id
+ * @param array $data
+ * @return mixed
+ */
+ public function edit(int $id, array $data)
+ {
+ $info = $this->model->where([ [ 'rank_id', '=', $id ] ])->find();
+ if (empty($info)) {
+ throw new AdminException('商品榜单不存在,请检查');
+ }
+ $data[ 'update_time' ] = time();
+ $rankInfo = $this->model->where([ [ 'name', '=', $data[ 'name' ] ], [ 'rank_id', '<>', $id ] ])->findOrEmpty()->toArray();
+ if (!empty($rankInfo)) {
+ throw new AdminException('商品榜单已存在,请检查');
+ }
+ $data = $this->checkRankData($data); // 将其他类型的字段值重置
+
+ $info->save($data);
+ return true;
+ }
+
+ /**
+ * 商品排行榜详情
+ * @param int $id
+ * @return
+ */
+ public function getInfo(int $id)
+ {
+ $info = $this->model->where([ [ 'rank_id', '=', $id ] ])->findOrEmpty()->toArray();
+ if (empty($info)) {
+ throw new AdminException('商品榜单不存在,请检查');
+ }
+ $goods_list = [];
+ if (!empty($info[ 'goods_source' ]) && $info[ 'goods_source' ] == RankDict::GOODS) {
+ $goods_id = array_column($info[ 'goods_json' ], 'goods_id');
+ $goods_id_sort_array = array_column($info[ 'goods_json' ], 'sort', 'goods_id');
+ $goods_list = ( new Goods )->where([ [ 'goods_id', 'in', $goods_id ] ])
+ ->field('goods_id,goods_name,goods_type')
+ ->with([ 'goodsSku' => function($query) {
+ $query->field('sku_id,sku_name,sku_image,goods_id,price,stock');
+ } ])
+ ->append([ 'goods_type_name' ])->select()->toArray();
+ foreach ($goods_list as &$item) {
+ $item[ 'sort' ] = 0;
+ if (isset($goods_id_sort_array[ $item[ 'goods_id' ] ])) {
+ $item[ 'sort' ] = $goods_id_sort_array[ $item[ 'goods_id' ] ];
+ }
+ }
+ }
+ $info[ 'goods_list' ] = $goods_list;
+ return $info;
+ }
+
+ /**
+ * 商品排行榜选项列表
+ */
+ public function getOptionData()
+ {
+ $list[ 'rank_type' ] = RankDict::getRankType();
+ $list[ 'goods_source' ] = RankDict::getGoodsSource();
+ $list[ 'rule_type' ] = RankDict::getRuleType();
+ return $list;
+ }
+
+ /**
+ * 删除商品排行榜
+ * @param int $id
+ * @return bool
+ */
+ public function del(int $id)
+ {
+ $info = $this->model->where([ [ 'rank_id', '=', $id ] ])->find();
+ if (empty($info)) {
+ throw new AdminException('商品榜单不存在,请检查');
+ }
+ $res = $info->delete();
+ return $res;
+ }
+
+ /**
+ * 设置商品排行榜配置
+ * @param array $params
+ * @return bool
+ */
+ public function setGoodsRankConfig(array $params = [])
+ {
+ return ( new CoreGoodsRankConfigService() )->setGoodsRankConfig($params);
+ }
+
+ /**
+ * 获取商品排行榜配置
+ * @return array
+ */
+ public function getGoodsRankConfig()
+ {
+ return ( new CoreGoodsRankConfigService() )->getGoodsRankConfig();
+ }
+
+ /**
+ * 修改榜单排序号
+ * @return bool
+ */
+ public function editSort($data)
+ {
+ if (empty($data[ 'rank_id' ])) {
+ throw new AdminException('SHOP_RANK_NOT_EXIST');
+ }
+ $this->model->where([ [ 'rank_id', '=', $data[ 'rank_id' ] ] ])->update([ 'sort' => $data[ 'sort' ] ]);
+ return true;
+ }
+
+ /**
+ * 批量删除
+ * @return bool
+ */
+ public function batchDelete($data)
+ {
+ if (empty($data[ 'rank_id' ])) {
+ throw new AdminException('SHOP_RANK_NOT_EXIST');
+ }
+ $this->model->where([ [ 'rank_id', 'in', $data[ 'rank_id' ] ] ])->delete();
+ return true;
+ }
+
+ /**
+ * 获取排行榜分页列表
+ * @param array $where
+ * @return array
+ */
+ public function getSelectPage(array $where = [])
+ {
+
+ $verify_rank_ids = [];
+ if (!empty($where[ 'verify_rank_ids' ])) {
+ $verify_rank_ids = $this->model->where([
+ [ 'rank_id', 'in', $where[ 'verify_rank_ids' ] ]
+ ])->withSearch([ "name", "rank_type" ], $where)->field('rank_id')->select()->toArray();
+ if (!empty($verify_rank_ids)) {
+ $verify_rank_ids = array_column($verify_rank_ids, 'rank_id');
+ }
+ }
+
+ $field = 'rank_id,name,rank_type,goods_source,rule_type,create_time,goods_json,category_ids,brand_ids,label_ids';
+ $order = 'sort desc,create_time desc';
+ $search_model = $this->model
+ ->where([
+ [ 'rank_id', '>', 0 ],
+// [ 'status', '=', RankDict::ON ] // 不限制状态
+ ])
+ ->withSearch([ "name", 'rank_type' ], $where)
+ ->field($field)
+ ->order($order)->append([ 'rank_type_name', 'goods_source_name', 'rule_type_name' ]);
+ $list = $this->pageQuery($search_model);
+ if (!empty($list[ 'data' ])) {
+ $list[ 'data' ] = $this->getShowGodsNum($list[ 'data' ]);
+ }
+ $list[ 'verify_rank_ids' ] = $verify_rank_ids;
+ return $list;
+ }
+
+ /**
+ * 获取榜单展示数量
+ * @param array $data
+ * @return array
+ */
+ public function getShowGodsNum($data)
+ {
+ $goods_model = new Goods();
+ foreach ($data as &$value) {
+ switch ($value[ 'goods_source' ]) {
+ case RankDict::ALL:
+ $value[ 'show_goods_num' ] = $goods_model->where([ [ 'is_gift', '=', GoodsDict::NOT_IS_GIFT ], [ 'status', '=', 1 ], [ 'delete_time', '=', 0 ] ])->count();
+ break;
+ case RankDict::GOODS:
+ $goods_json = $value[ 'goods_json' ];
+ $goods_ids = array_column($goods_json, 'goods_id');
+ $value[ 'show_goods_num' ] = $goods_model->where([ [ 'is_gift', '=', GoodsDict::NOT_IS_GIFT ], [ 'goods_id', 'in', $goods_ids ], [ 'status', '=', 1 ], [ 'delete_time', '=', 0 ] ])->count();
+ break;
+ case RankDict::CATEGORY:
+ $category_ids = $value[ 'category_ids' ];
+ $value[ 'show_goods_num' ] = $goods_model->withSearch([ 'goods_category' ], [ 'goods_category' => $category_ids ])->where([ [ 'is_gift', '=', GoodsDict::NOT_IS_GIFT ], [ 'status', '=', 1 ], [ 'delete_time', '=', 0 ] ])->count();
+ break;
+ case RankDict::BRAND:
+ $brand_ids = $value[ 'brand_ids' ];
+ $value[ 'show_goods_num' ] = $goods_model->where([ [ 'is_gift', '=', GoodsDict::NOT_IS_GIFT ], [ 'brand_id', 'in', $brand_ids ], [ 'status', '=', 1 ], [ 'delete_time', '=', 0 ] ])->count();
+ break;
+ case RankDict::LABEL:
+ $label_ids = $value[ 'label_ids' ];
+ $value[ 'show_goods_num' ] = $goods_model->withSearch([ 'label_ids' ], [ 'label_ids' => $label_ids ])->where([ [ 'is_gift', '=', GoodsDict::NOT_IS_GIFT ], [ 'status', '=', 1 ], [ 'delete_time', '=', 0 ] ])->count();
+ break;
+ }
+ }
+ return $data;
+ }
+
+ /**
+ * 修改状态
+ * @param $data
+ * @return Rank
+ */
+ public function modifyStatus($data)
+ {
+ return $this->model->where([
+ [ 'rank_id', '=', $data[ 'rank_id' ] ],
+ ])->update([ 'status' => $data[ 'status' ] ]);
+ }
+
+}
diff --git a/niucloud/addon/shop/app/service/admin/goods/ServiceService.php b/niucloud/addon/shop/app/service/admin/goods/ServiceService.php
new file mode 100644
index 000000000..5032cfb81
--- /dev/null
+++ b/niucloud/addon/shop/app/service/admin/goods/ServiceService.php
@@ -0,0 +1,107 @@
+model = new Service();
+ }
+
+ /**
+ * 获取商品服务列表
+ * @param array $where
+ * @return array
+ */
+ public function getPage(array $where = [])
+ {
+ $field = 'service_id,service_name,image,desc,create_time,update_time';
+ $order = 'create_time desc';
+
+ $search_model = $this->model->where([ [ 'service_id', '>', 0 ] ])->withSearch([ "service_name" ], $where)->field($field)->order($order);
+ $list = $this->pageQuery($search_model);
+ return $list;
+ }
+
+ /**
+ * 获取商品服务列表
+ * @param array $where
+ * @param string $field
+ * @return array
+ */
+ public function getList(array $where = [], $field = 'service_id,service_name,image,desc,create_time,update_time')
+ {
+ $order = "create_time desc";
+ return $this->model->where([ [ 'service_id', '>', 0 ] ])->withSearch([ "service_name" ], $where)->field($field)->order($order)->select()->toArray();
+ }
+
+ /**
+ * 获取商品服务信息
+ * @param int $id
+ * @return array
+ */
+ public function getInfo(int $id)
+ {
+ $field = 'service_id,service_name,image,desc,create_time,update_time';
+
+ $info = $this->model->field($field)->where([ [ 'service_id', '=', $id ] ])->findOrEmpty()->toArray();
+ return $info;
+ }
+
+ /**
+ * 添加商品服务
+ * @param array $data
+ * @return mixed
+ */
+ public function add(array $data)
+ {
+ $data[ 'create_time' ] = time();
+ $res = $this->model->create($data);
+ return $res->service_id;
+ }
+
+ /**
+ * 商品服务编辑
+ * @param int $id
+ * @param array $data
+ * @return bool
+ */
+ public function edit(int $id, array $data)
+ {
+ $data[ 'update_time' ] = time();
+ $this->model->where([ [ 'service_id', '=', $id ] ])->update($data);
+ return true;
+ }
+
+ /**
+ * 删除商品服务
+ * @param int $id
+ * @return bool
+ */
+ public function del(int $id)
+ {
+ $model = $this->model->where([ [ 'service_id', '=', $id ] ])->find();
+ $res = $model->delete();
+ return $res;
+ }
+}
diff --git a/niucloud/addon/shop/app/service/admin/goods/StatisticsService.php b/niucloud/addon/shop/app/service/admin/goods/StatisticsService.php
new file mode 100644
index 000000000..a5e4b39b8
--- /dev/null
+++ b/niucloud/addon/shop/app/service/admin/goods/StatisticsService.php
@@ -0,0 +1,325 @@
+model = new Stat();
+ }
+
+ /**
+ * 获取商品统计基本信息
+ * @param array $data
+ * @return array
+ */
+ public function getBasic(array $data)
+ {
+ if (empty($data[ 'date' ])) {
+ $data[ 'date' ] = date('Y/m/d', strtotime('-1 month')) . '-' . date('Y/m/d');
+ }
+
+ $date_arr = explode('-', $data[ 'date' ]);
+ $date = [ strtotime($date_arr[ 0 ]), strtotime($date_arr[ 1 ]) ];
+ $goods_ids = (new Goods())->where([[ 'goods_id', '>', 0 ]])->column('goods_id');
+
+ $field = 'goods_id,sum(cart_num) as cart_num,sum(sale_num) as sale_num,sum(pay_num) as pay_num,sum(pay_money) as pay_money,sum(refund_num) as refund_num,sum(refund_money) as refund_money,sum(collect_num) as collect_num,sum(evaluate_num) as evaluate_num,sum(access_num) as access_num,sum(goods_visit_member_count) as goods_visit_member_count';
+ $list = $this->model->where([ [ 'date_time', 'between', $date ], ['goods_id','in',$goods_ids] ])
+ ->field($field)
+ ->group('goods_id')
+ ->select()
+ ->toArray();
+
+ $data = [
+ 'access_good_num' => 0,//被访问商品数
+ 'sale_good_num' => 0,//动销商品数
+ 'cart_num' => 0,//加入购物车数量
+ 'sale_num' => 0,//商品销量(下单数)
+ 'pay_num' => 0,//支付件数
+ 'pay_money' => 0,//支付总金额
+ 'refund_num' => 0,//退款件数
+ 'refund_money' => 0,//退款总额
+ 'access_num' => 0,//访问次数(浏览量)
+ 'collect_num' => 0,//收藏数量
+ 'evaluate_num' => 0,//评论数量
+ 'goods_visit_member_count' => 0,//商品访客数
+// 'pay_percent'=>0,//支付转化率
+ ];
+ foreach ($list as $value) {
+ if ($value[ 'access_num' ] >= 1) {
+ $data[ 'access_good_num' ] += 1;
+ }
+ if ($value[ 'sale_num' ] >= 1) {
+ $data[ 'sale_good_num' ] += 1;
+ }
+ $data[ 'cart_num' ] += $value[ 'cart_num' ];
+ $data[ 'sale_num' ] += $value[ 'sale_num' ];
+ $data[ 'pay_num' ] += $value[ 'pay_num' ];
+ $data[ 'pay_money' ] = bcadd($data[ 'pay_money' ], $value[ 'pay_money' ], 2);
+ $data[ 'refund_num' ] += $value[ 'refund_num' ];
+ $data[ 'refund_money' ] = bcadd($data[ 'refund_money' ], $value[ 'refund_money' ], 2);
+ $data[ 'access_num' ] += $value[ 'access_num' ];
+ $data[ 'collect_num' ] += $value[ 'collect_num' ];
+ $data[ 'evaluate_num' ] += $value[ 'evaluate_num' ];
+ $data[ 'goods_visit_member_count' ] += $value[ 'goods_visit_member_count' ];
+ }
+ return $data;
+ }
+
+ /**
+ * 获取商品统计图表信息
+ * @param array $data
+ * @return array
+ */
+ public function getTrend(array $data)
+ {
+ $goods_ids = (new Goods())->where([[ 'goods_id', '>', 0 ]])->column('goods_id');
+ $where[] = [
+ ['goods_id','in',$goods_ids]
+ ];
+ $date_type = 'day';
+ if (empty($data[ 'date' ])) {
+ $data[ 'date' ] = date('Y/m/d', strtotime('-1 month')) . '-' . date('Y/m/d');
+ }
+ $date_arr = explode('-', $data[ 'date' ]);
+ $allDates = $this->getDatesBetween($date_arr[ 0 ], $date_arr[ 1 ]);
+ $select_data = [];
+ if (count($allDates) > 32) {
+ $date_type = 'month';
+ foreach ($allDates as $v) {
+ $select_data[ date('Y-m', strtotime($v)) ][] = $v;
+ }
+ $allDates = $this->getMonthsBetween($date_arr[ 0 ], $date_arr[ 1 ]);
+ }
+
+ $date = [ strtotime($date_arr[ 0 ]), strtotime($date_arr[ 1 ]) ];
+ $where[] = [ 'date_time', 'between', $date ];
+ $field = 'goods_id,date,date_time,sum(cart_num) as cart_num,sum(sale_num) as sale_num,sum(pay_num) as pay_num,sum(pay_money) as pay_money,sum(refund_num) as refund_num,sum(refund_money) as refund_money,sum(collect_num) as collect_num,sum(evaluate_num) as evaluate_num,sum(access_num) as access_num,sum(goods_visit_member_count) as goods_visit_member_count';
+ $list = $this->model
+ ->where($where)
+ ->field($field)
+ ->group('date_time')
+ ->order('date_time asc')
+ ->select()
+ ->toArray();
+ $data = $stat_count = $date_arr_data = [];
+ if (!empty($allDates)) {
+ foreach ($allDates as $key => $value) {
+ $stat_count[ 'access_count' ][ $value ] = 0;//浏览量
+ $stat_count[ 'goods_visit_member_count' ][ $value ] = 0;//访客数
+ $stat_count[ 'pay_money' ][ $value ] = 0;//支付金额
+ $stat_count[ 'refund_money' ][ $value ] = 0;//退款金额
+ $stat_count[ 'cart_num' ][ $value ] = 0;//加入购物车数
+ $stat_count[ 'sale_num' ][ $value ] = 0;//下单件数
+ $stat_count[ 'pay_num' ][ $value ] = 0;//支付件数
+ $stat_count[ 'refund_num' ][ $value ] = 0;//退款件数
+ }
+
+ if ($date_type == 'day') {
+ foreach ($list as $k => $v) {
+ $stat_count[ 'access_count' ][ $v[ 'date' ] ] += $v[ 'access_num' ];
+ $stat_count[ 'goods_visit_member_count' ][ $v[ 'date' ] ] += $v[ 'goods_visit_member_count' ];
+ $stat_count[ 'pay_money' ][ $v[ 'date' ] ] = bcadd($stat_count[ 'pay_money' ][ $v[ 'date' ] ], $v[ 'pay_money' ], 2);
+ $stat_count[ 'refund_money' ][ $v[ 'date' ] ] += bcadd($stat_count[ 'refund_money' ][ $v[ 'date' ] ], $v[ 'refund_money' ], 2);
+ $stat_count[ 'cart_num' ][ $v[ 'date' ] ] += $v[ 'cart_num' ];
+ $stat_count[ 'sale_num' ][ $v[ 'date' ] ] += $v[ 'sale_num' ];
+ $stat_count[ 'pay_num' ][ $v[ 'date' ] ] += $v[ 'pay_num' ];
+ $stat_count[ 'refund_num' ][ $v[ 'date' ] ] += $v[ 'refund_num' ];
+ }
+ } elseif ($date_type == 'month') {
+ foreach ($select_data as $key => $value) {
+ foreach ($list as $k => $v) {
+ if (in_array($v[ 'date' ], $value)) {
+ $stat_count[ 'access_count' ][ $key ] += $v[ 'access_num' ];
+ $stat_count[ 'goods_visit_member_count' ][ $key ] += $v[ 'goods_visit_member_count' ];
+ $stat_count[ 'pay_money' ][ $key ] = bcadd($stat_count[ 'pay_money' ][ $key ], $v[ 'pay_money' ], 2);
+ $stat_count[ 'refund_money' ][ $key ] = bcadd($stat_count[ 'refund_money' ][ $key ], $v[ 'refund_money' ], 2);
+ $stat_count[ 'cart_num' ][ $key ] += $v[ 'cart_num' ];
+ $stat_count[ 'sale_num' ][ $key ] += $v[ 'sale_num' ];
+ $stat_count[ 'pay_num' ][ $key ] += $v[ 'pay_num' ];
+ $stat_count[ 'refund_num' ][ $key ] += $v[ 'refund_num' ];
+ }
+ }
+ }
+ }
+ foreach ($stat_count as $key => $value) {
+ $data[ $key ][ 'name' ] = $key;
+ $data[ $key ][ 'data' ] = array_values($value);
+ }
+ }
+ $arr = [
+ 'data' => array_values($data),
+ 'xAxis' => $allDates,
+ ];
+ return $arr;
+ }
+
+ /**
+ * 获取商品排行榜信息
+ * @param array $data
+ * @return array
+ */
+ public function getRank(array $data)
+ {
+ if (empty($data[ 'date' ])) {
+ $data[ 'date' ] = date('Y/m/d', strtotime('-1 month')) . '-' . date('Y/m/d');
+ }
+ $date_arr = explode('-', $data[ 'date' ]);
+ $date = [ strtotime($date_arr[ 0 ]), strtotime($date_arr[ 1 ]) ];
+
+ $where[] = [
+ [ 'date_time', 'between', $date ],
+ [ 'goods.delete_time', '=', 0 ],
+ ];
+ if (!empty($data[ 'category_ids' ])) {
+ $category_where = array_map(function($item) { return '%"' . $item . '"%'; }, $data[ 'category_ids' ]);
+ $where[] = [ 'goods_category', 'like', $category_where, 'or' ];
+ }
+ if (!empty($data[ 'goods_name' ])) {
+ $where[] = [ "goods_name", "like", "%" . $data[ 'goods_name' ] . "%"];
+ }
+ $field = 'stat.goods_id,sum(stat.cart_num) as cart_num,sum(stat.sale_num) as sale_num,sum(stat.pay_num) as pay_num,sum(stat.pay_money) as pay_money,sum(stat.refund_num) as refund_num,sum(stat.refund_money) as refund_money,sum(stat.collect_num) as collect_num,sum(stat.evaluate_num) as evaluate_num,sum(stat.access_num) as access_num,sum(goods_visit_member_count) as goods_visit_member_count,goods_name,goods_cover,is_gift';
+ //排序 access_num=访问次数(浏览量) cart_num=>加入购物车数量 sale_num=商品销量(下单数)pay_num=支付件数 collect_num=收藏数量 pay_money=支付总金额
+ $order = $data[ 'type' ] . ' desc,goods.sort desc,goods.create_time desc';
+ $query = $this->model
+ ->alias('stat')
+ ->where($where)
+ ->withSearch(['goods_name'],$where)
+ ->field($field)
+ ->join('shop_goods goods', 'stat.goods_id=goods.goods_id', 'left')
+ ->append([ 'goods_cover_thumb_small' ])
+ ->group('stat.goods_id')
+ ->order($order);
+ $list = $this->pageQuery($query);
+ return $list;
+ }
+
+ /**
+ * 获取商品排行榜统计类型
+ * @return array
+ */
+ public function getType()
+ {
+ $list = StatisticsDict::getType();
+ return $list;
+ }
+
+ public function getDatesBetween($startDate, $endDate)
+ {
+ $dates = [];
+ $start = strtotime($startDate);
+ $end = strtotime($endDate);
+
+ // 确保开始日期小于或等于结束日期
+ if ($start > $end) {
+ return $dates; // 返回空数组
+ }
+
+ // 循环获取日期
+ while ($start <= $end) {
+ $dates[] = date('Y-m-d', $start); // 格式化为日期字符串
+ $start = strtotime("+1 day", $start); // 增加一天
+ }
+
+ return $dates; // 返回日期数组
+ }
+
+ public function getMonthsBetween($startDate, $endDate)
+ {
+ $months = [];
+ $start = new DateTime($startDate);
+ $end = new DateTime($endDate);
+
+ // 确保开始日期小于等于结束日期
+ if ($start > $end) {
+ return $months; // 返回空数组
+ }
+
+ // 循环获取月份
+ while ($start <= $end) {
+ $months[] = $start->format('Y-m'); // 格式化为年月字符串
+ $start->modify('first day of next month'); // 移动到下一个月的第一天
+ }
+
+ return $months; // 返回月份数组
+ }
+
+ /**
+ * 同步商品统计信息
+ * @param array $date
+ * @return bool
+ */
+ public function syncStatGoods($date = [])
+ {
+ $pageSize = 100;
+ $page = 1;
+
+ if (empty($date)) {
+ $date[] = date('Y-m-d');
+ }
+
+ while (true) {
+ $goods_list = (new Goods())
+ ->field('goods_id')
+ ->limit(($page - 1) * $pageSize, $pageSize)
+ ->select()
+ ->toArray();
+
+ if (empty($goods_list)) {
+ break; // 没有更多商品时退出循环
+ }
+
+ $goods_ids = array_column($goods_list, 'goods_id');
+
+ $data = [];
+ foreach ($date as $value) {
+ $stat_goods_ids = $this->model
+ ->where([
+ ['date', '=', $value],
+ ['goods_id', 'in', $goods_ids]
+ ])
+ ->column('goods_id');
+
+ foreach ($goods_list as $v) {
+ if (!in_array($v['goods_id'], $stat_goods_ids)) {
+ $data[] = [
+ 'date' => $value,
+ 'date_time' => strtotime($value),
+ 'goods_id' => $v['goods_id'],
+ ];
+ }
+ }
+ }
+ if (!empty($data)) {
+ $this->model->saveAll($data);
+ }
+
+ $page++;
+ }
+ return true;
+ }
+
+}
diff --git a/niucloud/addon/shop/app/service/admin/goods/VirtualGoodsService.php b/niucloud/addon/shop/app/service/admin/goods/VirtualGoodsService.php
new file mode 100644
index 000000000..bab1a93f2
--- /dev/null
+++ b/niucloud/addon/shop/app/service/admin/goods/VirtualGoodsService.php
@@ -0,0 +1,708 @@
+model = new Goods();
+ }
+
+ /**
+ * 获取商品添加/编辑数据
+ * @param array $params
+ * @return array
+ */
+ public function getInit(array $params = [])
+ {
+
+ $res = [];
+
+ $addon_service = new AddonService();
+ $res[ 'addon_shop_supplier' ] = $addon_service->getInfoByKey('shop_supplier');
+
+ if (!empty($params[ 'goods_id' ])) {
+ // 查询商品信息,用于编辑
+ $field = 'goods_id,goods_name,sub_title,goods_type,goods_cover,goods_image,goods_video,goods_desc,brand_id,goods_category,label_ids,service_ids,unit,stock,virtual_sale_num,is_limit,limit_type,max_buy,min_buy,status,sort,supplier_id,attr_ids,attr_format,virtual_auto_delivery,virtual_receive_type,virtual_verify_type,virtual_indate,member_discount,poster_id,is_gift,form_id';
+ $goods_info = $this->model->field($field)->where([ [ 'goods_id', '=', $params[ 'goods_id' ] ] ])->findOrEmpty()->toArray();
+ if (!empty($goods_info)) {
+
+ if (!empty($goods_info[ 'goods_category' ])) {
+ $category_service = new CategoryService();
+ foreach ($goods_info[ 'goods_category' ] as $k => $v) {
+ $category = $category_service->getInfo($v);
+ if (empty($category)) {
+ unset($goods_info[ 'goods_category' ][ $k ]);
+ }
+ }
+ }
+
+ // 商品品牌,处理数据类型
+ if (empty($goods_info[ 'brand_id' ])) {
+ $goods_info[ 'brand_id' ] = '';
+ } else {
+ $brand_count = ( new Brand() )->where([ [ 'brand_id', '=', $goods_info[ 'brand_id' ] ] ])->count();
+ if ($brand_count == 0) $goods_info[ 'brand_id' ] = '';
+ }
+
+ // 供应商,处理数据类型
+ if (empty($goods_info[ 'supplier_id' ])) {
+ $goods_info[ 'supplier_id' ] = '';
+ }
+
+ // 标签组
+ if (empty($goods_info[ 'label_ids' ])) {
+ $goods_info[ 'label_ids' ] = [];
+ } else {
+ $goods_info[ 'label_ids' ] = array_map(function ($item) {
+ return (int) $item;
+ }, $goods_info[ 'label_ids' ]);
+ }
+
+ // 商品服务
+ if (empty($goods_info[ 'service_ids' ])) {
+ $goods_info[ 'service_ids' ] = [];
+ } else {
+ $goods_info[ 'service_ids' ] = array_map(function ($item) {
+ return (int) $item;
+ }, $goods_info[ 'service_ids' ]);
+ }
+
+ // 商品参数,处理数据类型
+ if (empty($goods_info[ 'attr_ids' ])) {
+ $goods_info[ 'attr_ids' ] = [];
+ } else {
+ $goods_info[ 'attr_ids' ] = array_map(function ($item) {
+ return (int) $item;
+ }, $goods_info[ 'attr_ids' ]);
+ }
+
+ // 商品海报id,处理数据类型
+ if (empty($goods_info[ 'poster_id' ])) {
+ $goods_info[ 'poster_id' ] = '';
+ }
+
+ // 自定义商品详情模板id,处理数据类型
+ if (!empty($goods_info[ 'diy_detail_id' ])) {
+ $diy_model = new Diy();
+ $diy_count = $diy_model->where([
+ [ 'id', '=', $goods_info[ 'diy_detail_id' ] ]
+ ])->count();
+ if ($diy_count == 0) {
+ $goods_info[ 'diy_detail_id' ] = '';
+ }
+ } else {
+ $goods_info[ 'diy_detail_id' ] = '';
+ }
+
+ // 万能表单id,处理数据类型
+ if (!empty($goods_info[ 'form_id' ])) {
+ $diy_form_model = new DiyForm();
+ $diy_form_count = $diy_form_model->where([
+ [ 'form_id', '=', $goods_info[ 'form_id' ] ]
+ ])->count();
+ if ($diy_form_count == 0) {
+ $goods_info[ 'form_id' ] = '';
+ }
+ } else {
+ $goods_info[ 'form_id' ] = '';
+ }
+
+ $goods_info[ 'status' ] = (string) $goods_info[ 'status' ];
+
+ $goods_sku_model = new GoodsSku();
+
+ $sku_field = 'sku_id,sku_name,sku_image,sku_no,goods_id,sku_spec_format,price,market_price,cost_price,stock,is_default';
+ $sku_order = 'sku_id asc';
+ $goods_info[ 'sku_list' ] = $goods_sku_model->withSearch([ "goods_id" ], [ 'goods_id' => $params[ 'goods_id' ] ])->field($sku_field)->order($sku_order)->select()->toArray();
+
+ $goods_info[ 'spec_type' ] = 'single';
+ if (count($goods_info[ 'sku_list' ]) > 1) {
+ // 多规格
+ $goods_info[ 'spec_type' ] = 'multi';
+
+ $goods_spec_model = new GoodsSpec();
+ $spec_field = 'spec_id,goods_id,spec_name,spec_values';
+ $spec_order = 'spec_id asc';
+ $goods_info[ 'spec_list' ] = $goods_spec_model->withSearch([ "goods_id" ], [ 'goods_id' => $params[ 'goods_id' ] ])->field($spec_field)->order($spec_order)->select()->toArray();
+
+ }
+
+ // 存在订单的虚拟商品(收货方式为 到店核销),则无法编辑收发货设置
+ if ($goods_info[ 'virtual_receive_type' ] == 'verify') {
+ $order_goods_model = new OrderGoods();
+
+ // 检测订单是否存在
+ $order_where = [
+ [ 'orderMain.status', 'in', [ 1, 2, 3 ] ], // 排除已完成、已关闭状态
+ [ 'goods_id', '=', $goods_info[ 'goods_id' ] ],
+ ];
+ $goods_info[ 'order_goods_count' ] = $order_goods_model
+ ->withJoin([ 'orderMain' ])
+ ->where($order_where)->count();
+ } else {
+ $goods_info[ 'order_goods_count' ] = 0;
+ }
+
+ // 查询商品参与营销活动的数量
+ $goods_info[ 'active_goods_count' ] = $this->getActiveGoodsCount($goods_info[ 'goods_id' ]);
+
+ $res[ 'goods_info' ] = $goods_info;
+
+ }
+
+ }
+ $res[ 'default_sort' ] = ( new CoreGoodsConfigService() )->getDefaultSort();
+
+ return $res;
+ }
+
+ /**
+ * 添加商品
+ * @param array $data
+ * @return mixed
+ */
+ public function add(array $data)
+ {
+ try {
+ Db::startTrans();
+ $goods_sku_model = new GoodsSku();
+ $goods_spec_model = new GoodsSpec();
+ $goods_stat_model = new Stat();
+
+ // 商品封面
+ if (!empty($data[ 'goods_image' ])) $data[ 'goods_cover' ] = explode(',', $data[ 'goods_image' ])[ 0 ];
+
+ $goods_data = [
+ 'goods_name' => $data[ 'goods_name' ],
+ 'sub_title' => $data[ 'sub_title' ],
+ 'goods_type' => $data[ 'goods_type' ],
+ 'goods_cover' => $data[ 'goods_cover' ],
+ 'goods_image' => $data[ 'goods_image' ],
+ 'goods_video' => $data[ 'goods_video' ],
+ 'goods_category' => array_map(function ($item) {
+ return (string) $item;
+ }, $data[ 'goods_category' ]),
+ 'goods_desc' => $data[ 'goods_desc' ],
+ 'brand_id' => $data[ 'brand_id' ],
+ 'label_ids' => array_map(function ($item) {
+ return (string) $item;
+ }, $data[ 'label_ids' ]),
+ 'service_ids' => array_map(function ($item) {
+ return (string) $item;
+ }, $data[ 'service_ids' ]),
+ 'unit' => $data[ 'unit' ],
+ 'stock' => $data[ 'stock' ],
+ 'virtual_sale_num' => $data[ 'virtual_sale_num' ],
+ 'is_limit' => $data[ 'is_limit' ],
+ 'limit_type' => $data[ 'limit_type' ],
+ 'max_buy' => $data[ 'max_buy' ],
+ 'min_buy' => $data[ 'min_buy' ],
+ 'is_gift' => $data[ 'is_gift' ],
+ 'status' => $data[ 'status' ],
+ 'sort' => $data[ 'sort' ],
+ 'attr_ids' => $data[ 'attr_ids' ],
+ 'attr_format' => $data[ 'attr_format' ],
+ 'supplier_id' => $data[ 'supplier_id' ],
+ 'virtual_auto_delivery' => $data[ 'virtual_auto_delivery' ] ?? 0,
+ 'virtual_receive_type' => $data[ 'virtual_receive_type' ] ?? 'artificial',
+ 'virtual_verify_type' => $data[ 'virtual_verify_type' ] ?? 0,
+ 'virtual_indate' => $data[ 'virtual_indate' ] ?? 0,
+ 'member_discount' => $data[ 'member_discount' ],
+ 'poster_id' => $data[ 'poster_id' ],
+ 'form_id' => $data[ 'form_id' ],
+ 'diy_detail_id' => $data[ 'diy_detail_id' ],
+ 'create_time' => time()
+ ];
+ $res = $this->model->create($goods_data);
+
+ $sku_data = [];
+ if ($data[ 'spec_type' ] == 'single') {
+ if (!empty($data[ 'sku_no' ])) {
+ ( new ConfigService() )->verifySkuNo([ 'sku_no' => $data[ 'sku_no' ] ]);
+ }
+ // 单规格
+ $sku_data = [
+ 'sku_name' => '',
+ 'sku_image' => $data[ 'goods_cover' ],
+ 'sku_no' => $data[ 'sku_no' ],
+ 'goods_id' => $res->goods_id,
+ 'sku_spec_format' => '', // sku规格格式
+ 'price' => $data[ 'price' ],
+ 'market_price' => $data[ 'market_price' ],
+ 'sale_price' => $data[ 'price' ],
+ 'cost_price' => $data[ 'cost_price' ],
+ 'stock' => $data[ 'stock' ],
+ 'is_default' => 1
+ ];
+ $goods_sku_model->save($sku_data);
+
+ } elseif ($data[ 'spec_type' ] == 'multi') {
+ $sku_no = implode(',', array_column($data[ 'goods_sku_data' ] ?? [], 'sku_no'));
+ if (!empty($sku_no)) {
+ ( new ConfigService() )->verifySkuNo([ 'sku_no' => $sku_no ]);
+ }
+ // 多规格数据
+ $default_spec_count = 0;
+ foreach ($data[ 'goods_sku_data' ] as $k => $v) {
+ $sku_spec_format = [];
+ foreach ($v[ 'sku_spec' ] as $ck => $cv) {
+ $sku_spec_format[] = $cv[ 'spec_value_name' ];
+ }
+ $sku_data[] = [
+ 'sku_name' => $v[ 'spec_name' ],
+ 'sku_image' => !empty($v[ 'sku_image' ]) ? $v[ 'sku_image' ] : $data[ 'goods_cover' ],
+ 'sku_no' => $v[ 'sku_no' ],
+ 'goods_id' => $res->goods_id,
+ 'sku_spec_format' => implode(',', $sku_spec_format), // sku规格格式
+ 'price' => $v[ 'price' ],
+ 'market_price' => $v[ 'market_price' ],
+ 'sale_price' => $v[ 'price' ],
+ 'cost_price' => $v[ 'cost_price' ],
+ 'stock' => $v[ 'stock' ],
+ 'is_default' => $v[ 'is_default' ]
+ ];
+ if ($v[ 'is_default' ] == 1) $default_spec_count++;
+ }
+
+ if ($default_spec_count == 0) throw new AdminException('SHOP_GOODS_NOT_HAS_DEFAULT_SPEC');
+
+ $goods_sku_model->saveAll($sku_data);
+
+ // 商品规格值
+ $spec_data = [];
+ foreach ($data[ 'goods_spec_format' ] as $k => $v) {
+ $spec_values = [];
+ foreach ($v[ 'values' ] as $ck => $cv) {
+ $spec_values[] = $cv[ 'spec_value_name' ];
+ }
+ $spec_data[] = [
+ 'goods_id' => $res->goods_id,
+ 'spec_name' => $v[ 'spec_name' ],
+ 'spec_values' => implode(',', $spec_values)
+ ];
+ }
+ $goods_spec_model->saveAll($spec_data);
+
+ }
+
+ //添加商品统计表数据
+ $goods_stat_data = [
+ 'date' => date('Y-m-d'),
+ 'date_time' => strtotime(date('Y-m-d')),
+ 'goods_id' => $res->goods_id,
+ ];
+ $goods_stat_model->create($goods_stat_data);
+
+ Db::commit();
+
+ event('AfterGoodsEdit', [
+ 'goods_id' => $res->goods_id,
+ 'goods_data' => $goods_data,
+ 'sku_data' => $sku_data
+ ]);
+ return $res->goods_id;
+ } catch (\Exception $e) {
+ Db::rollback();
+ throw new CommonException($e->getMessage());
+ }
+ }
+
+ /**
+ * 商品编辑
+ * @param int $goods_id
+ * @param array $data
+ * @return bool
+ */
+ public function edit(int $goods_id, array $data)
+ {
+ try {
+ Db::startTrans();
+
+ $goods_sku_model = new GoodsSku();
+ $goods_spec_model = new GoodsSpec();
+ $order_goods_model = new OrderGoods();
+
+ // 查询商品参与营销活动的数量
+ $active_goods_count = $this->getActiveGoodsCount($goods_id);
+ if ($data[ 'status' ] == 0) {
+ if ($active_goods_count > 0) {
+ throw new AdminException('SHOP_GOODS_PARTICIPATE_IN_ACTIVE_DISABLED_EDIT');
+ }
+ }
+
+ // 商品封面
+ if (!empty($data[ 'goods_image' ])) $data[ 'goods_cover' ] = explode(',', $data[ 'goods_image' ])[ 0 ];
+
+ $goods_data = [
+ 'goods_name' => $data[ 'goods_name' ],
+ 'sub_title' => $data[ 'sub_title' ],
+ 'goods_type' => $data[ 'goods_type' ],
+ 'goods_cover' => $data[ 'goods_cover' ],
+ 'goods_image' => $data[ 'goods_image' ],
+ 'goods_video' => $data[ 'goods_video' ],
+ 'goods_category' => array_map(function ($item) {
+ return (string) $item;
+ }, $data[ 'goods_category' ]),
+ 'goods_desc' => $data[ 'goods_desc' ],
+ 'brand_id' => $data[ 'brand_id' ],
+ 'label_ids' => array_map(function ($item) {
+ return (string) $item;
+ }, $data[ 'label_ids' ]),
+ 'service_ids' => array_map(function ($item) {
+ return (string) $item;
+ }, $data[ 'service_ids' ]),
+ 'unit' => $data[ 'unit' ],
+ 'stock' => $data[ 'stock' ],
+ 'virtual_sale_num' => $data[ 'virtual_sale_num' ],
+ 'is_limit' => $data[ 'is_limit' ],
+ 'limit_type' => $data[ 'limit_type' ],
+ 'max_buy' => $data[ 'max_buy' ],
+ 'min_buy' => $data[ 'min_buy' ],
+ 'is_gift' => $data[ 'is_gift' ],
+ 'status' => $data[ 'status' ],
+ 'sort' => $data[ 'sort' ],
+ 'attr_ids' => $data[ 'attr_ids' ],
+ 'attr_format' => $data[ 'attr_format' ],
+ 'supplier_id' => $data[ 'supplier_id' ],
+ 'virtual_auto_delivery' => $data[ 'virtual_auto_delivery' ] ?? 0,
+ 'virtual_receive_type' => $data[ 'virtual_receive_type' ] ?? 'artificial',
+ 'virtual_verify_type' => $data[ 'virtual_verify_type' ] ?? 0,
+ 'virtual_indate' => $data[ 'virtual_indate' ] ?? 0,
+ 'member_discount' => $data[ 'member_discount' ],
+ 'poster_id' => $data[ 'poster_id' ],
+ 'form_id' => $data[ 'form_id' ],
+ 'diy_detail_id' => $data[ 'diy_detail_id' ],
+ 'update_time' => time()
+ ];
+
+ $this->model->where([ [ 'goods_id', '=', $goods_id ] ])->update($goods_data);
+
+ $sku_data = [];
+ if ($data[ 'spec_type' ] == 'single') {
+ if (!empty($data[ 'sku_no' ])) {
+ $check = [ 'sku_no' => $data[ 'sku_no' ], 'goods_id' => $goods_id ];
+ ( new ConfigService() )->verifySkuNo($check);
+ }
+ // 单规格
+ $sku_data = [
+ 'sku_name' => '',
+ 'sku_image' => $data[ 'goods_cover' ],
+ 'sku_no' => $data[ 'sku_no' ],
+ 'goods_id' => $goods_id,
+ 'sku_spec_format' => '', // sku规格格式
+ 'market_price' => $data[ 'market_price' ],
+ 'cost_price' => $data[ 'cost_price' ],
+ 'is_default' => 1
+ ];
+
+ // 未参与营销活动,则允许修改 原价、销售价、库存
+ if ($active_goods_count == 0) {
+ $sku_data[ 'price' ] = $data[ 'price' ];
+ $sku_data[ 'sale_price' ] = $data[ 'price' ];
+ $sku_data[ 'stock' ] = $data[ 'stock' ];
+ }
+
+ $sku_count = $goods_sku_model->where([ [ 'goods_id', '=', $goods_id ] ])->count();
+ if ($sku_count > 1) {
+
+ // 规格项发生变化,删除旧规格,添加新规格重新生成
+ $goods_sku_model->where([ [ 'goods_id', '=', $goods_id ] ])->delete();
+
+ // 防止存在遗留规格项,删除旧规格
+ $goods_spec_model->where([ [ 'goods_id', '=', $goods_id ] ])->delete();
+
+ // 新增规格
+ $goods_sku_model->create($sku_data);
+
+ } else {
+
+ $goods_sku_model->where([ [ 'goods_id', '=', $goods_id ] ])->update($sku_data);
+
+ // 防止存在遗留规格项,删除旧规格
+ $goods_spec_model->where([ [ 'goods_id', '=', $goods_id ] ])->delete();
+ }
+
+ } elseif ($data[ 'spec_type' ] == 'multi') {
+ $sku_no = implode(',', array_column($data[ 'goods_sku_data' ] ?? [], 'sku_no'));
+ if (!empty($sku_no)) {
+ $check = [ 'sku_no' => $sku_no, 'goods_id' => $goods_id ];
+ ( new ConfigService() )->verifySkuNo($check);
+ }
+ // 多规格数据
+ $first_sku_data = reset($data[ 'goods_sku_data' ]);
+
+ // 商品正在参与营销活动,禁止修改规格
+ if ($active_goods_count > 0 && empty($first_sku_data[ 'sku_id' ])) {
+ throw new AdminException('SHOP_GOODS_PARTICIPATE_IN_ACTIVE_DISABLED_EDIT');
+ }
+
+ // 检测规格项是否发生变化
+ if (!empty($first_sku_data[ 'sku_id' ])) {
+ // 规格项没有变化,修改/新增规格数据
+
+ $sku_id_arr = [];
+ $default_spec_count = 0;
+ foreach ($data[ 'goods_sku_data' ] as $k => $v) {
+ $sku_spec_format = [];
+ foreach ($v[ 'sku_spec' ] as $ck => $cv) {
+ $sku_spec_format[] = $cv[ 'spec_value_name' ];
+ }
+ $sku_data = [
+ 'sku_name' => $v[ 'spec_name' ],
+ 'sku_image' => !empty($v[ 'sku_image' ]) ? $v[ 'sku_image' ] : $data[ 'goods_cover' ],
+ 'sku_no' => $v[ 'sku_no' ],
+ 'goods_id' => $goods_id,
+ 'sku_spec_format' => implode(',', $sku_spec_format), // sku规格格式
+ 'market_price' => $v[ 'market_price' ],
+ 'cost_price' => $v[ 'cost_price' ],
+ 'is_default' => $v[ 'is_default' ]
+ ];
+
+ // 未参与营销活动,则允许修改 原价、销售价
+ if ($active_goods_count == 0) {
+ $sku_data[ 'price' ] = $v[ 'price' ];
+ $sku_data[ 'sale_price' ] = $v[ 'price' ];
+ $sku_data[ 'stock' ] = $v[ 'stock' ];
+ }
+
+ if (!empty($v[ 'sku_id' ])) {
+ // 修改规格
+ $sku_id_arr[] = $v[ 'sku_id' ];
+ $goods_sku_model->where([ [ 'sku_id', '=', $v[ 'sku_id' ] ], [ 'goods_id', '=', $goods_id ] ])->update($sku_data);
+ } else {
+ // 新增规格
+ $sku_model = $goods_sku_model->create($sku_data);
+ $sku_id_arr[] = $sku_model->sku_id;
+ }
+ if ($v[ 'is_default' ] == 1) $default_spec_count++;
+
+ }
+
+ // 校验默认必须存在默认规格
+ if ($default_spec_count == 0) throw new AdminException('SHOP_GOODS_NOT_HAS_DEFAULT_SPEC');
+
+ $spec_id_list = $goods_spec_model->withSearch([ "goods_id" ], [ 'goods_id' => $goods_id ])->field('spec_id')->select()->toArray();
+ $spec_id_list = array_column($spec_id_list, 'spec_id');
+
+ // 商品规格值
+ foreach ($data[ 'goods_spec_format' ] as $k => $v) {
+ $spec_values = [];
+ foreach ($v[ 'values' ] as $ck => $cv) {
+ $spec_values[] = $cv[ 'spec_value_name' ];
+ }
+ $spec_data = [
+ 'goods_id' => $goods_id,
+ 'spec_name' => $v[ 'spec_name' ],
+ 'spec_values' => implode(',', $spec_values)
+ ];
+ if (!empty($v[ 'spec_id' ])) {
+ // 修改规格值
+ $goods_spec_model->where([ [ 'goods_id', '=', $goods_id ], [ 'spec_id', '=', $v[ 'spec_id' ] ] ])->update($spec_data);
+ foreach ($spec_id_list as $ck => $cv) {
+ if ($v[ 'spec_id' ] == $cv) {
+ unset($spec_id_list[ $ck ]);
+ }
+ }
+
+ } else {
+ // 添加规格值
+ $goods_spec_model->save($spec_data);
+ }
+ }
+
+ // 移除不存在的规格项
+ if (!empty($spec_id_list)) {
+ $goods_spec_model->where([ [ 'spec_id', 'in', implode(',', $spec_id_list) ] ])->delete();
+ }
+
+ // 移除不存在的商品SKU
+ $sku_id_list = $goods_sku_model->withSearch([ "goods_id" ], [ 'goods_id' => $goods_id ])->field('sku_id')->select()->toArray();
+ $sku_id_list = array_column($sku_id_list, 'sku_id');
+ foreach ($sku_id_list as $k => $v) {
+ foreach ($sku_id_arr as $ck => $cv) {
+ if ($v == $cv) {
+ unset($sku_id_list[ $k ]);
+ }
+ }
+ }
+ $sku_id_list = array_values($sku_id_list);
+
+ if (!empty($sku_id_list)) {
+
+ // 检测订单是否存在要删除的商品
+ $order_where = [
+ [ 'orderMain.status', 'in', [ 1, 2, 3 ] ], // 排除已完成、已关闭状态
+ [ 'goods_id', '=', $goods_id ],
+ [ 'sku_id', 'in', $sku_id_list ]
+ ];
+ $order_goods_count = $order_goods_model
+ ->withJoin([ 'orderMain' ])
+ ->where($order_where)->count();
+
+ if ($order_goods_count > 0) {
+ Db::rollback();
+ throw new CommonException('EXIST_ORDER_NOT_DELETE_GOODS');
+ }
+
+ $goods_sku_model->where([ [ 'sku_id', 'in', implode(',', $sku_id_list) ] ])->delete();
+ }
+
+ } else {
+
+ // 检测订单是否存在要删除的商品
+ $order_where = [
+ [ 'orderMain.status', 'in', [ 1, 2, 3 ] ], // 排除已完成、已关闭状态
+ [ 'goods_id', '=', $goods_id ]
+ ];
+ $order_goods_count = $order_goods_model
+ ->withJoin([ 'orderMain' ])
+ ->where($order_where)->count();
+
+ if ($order_goods_count > 0) {
+ Db::rollback();
+ throw new CommonException('EXIST_ORDER_NOT_EDIT_GOODS');
+ }
+
+ // 规格项发生变化,删除旧规格,添加新规格重新生成
+ $goods_sku_model->where([ [ 'goods_id', '=', $goods_id ] ])->delete();
+ $goods_spec_model->where([ [ 'goods_id', '=', $goods_id ] ])->delete();
+
+ $default_spec_count = 0;
+ foreach ($data[ 'goods_sku_data' ] as $k => $v) {
+ $sku_spec_format = [];
+ foreach ($v[ 'sku_spec' ] as $ck => $cv) {
+ $sku_spec_format[] = $cv[ 'spec_value_name' ];
+ }
+ $sku_data[] = [
+ 'sku_name' => $v[ 'spec_name' ],
+ 'sku_image' => !empty($v[ 'sku_image' ]) ? $v[ 'sku_image' ] : $data[ 'goods_cover' ],
+ 'sku_no' => $v[ 'sku_no' ],
+ 'goods_id' => $goods_id,
+ 'sku_spec_format' => implode(',', $sku_spec_format), // sku规格格式
+ 'price' => $v[ 'price' ],
+ 'market_price' => $v[ 'market_price' ],
+ 'sale_price' => $v[ 'price' ],
+ 'cost_price' => $v[ 'cost_price' ],
+ 'stock' => $v[ 'stock' ],
+ 'is_default' => $v[ 'is_default' ]
+ ];
+ if ($v[ 'is_default' ] == 1) $default_spec_count++;
+ }
+
+ // 校验默认必须存在默认规格
+ if ($default_spec_count == 0) throw new AdminException('SHOP_GOODS_NOT_HAS_DEFAULT_SPEC');
+
+ $goods_sku_model->saveAll($sku_data);
+
+ // 商品规格值
+ $spec_data = [];
+ foreach ($data[ 'goods_spec_format' ] as $k => $v) {
+ $spec_values = [];
+ foreach ($v[ 'values' ] as $ck => $cv) {
+ $spec_values[] = $cv[ 'spec_value_name' ];
+ }
+ $spec_data[] = [
+ 'goods_id' => $goods_id,
+ 'spec_name' => $v[ 'spec_name' ],
+ 'spec_values' => implode(',', $spec_values)
+ ];
+ }
+ $goods_spec_model->saveAll($spec_data);
+
+ }
+
+ }
+
+ Db::commit();
+
+ event('AfterGoodsEdit', [
+ 'goods_id' => $goods_id,
+ 'goods_data' => $goods_data,
+ 'sku_data' => $sku_data
+ ]);
+ return true;
+ } catch (\Exception $e) {
+ Db::rollback();
+ throw new CommonException($e->getMessage());
+ }
+ }
+
+ /**
+ * 查询商品参与营销活动的数量
+ * @param $goods_id
+ * @return mixed
+ */
+ public function getActiveGoodsCount($goods_id)
+ {
+ $active_goods_model = new ActiveGoods();
+ $discount_goods_model = new DiscountGoods();
+ $field = 'active_goods_id,active_id';
+
+ $condition = [];
+
+ // 判断 $goods_id 类型
+ if (is_array($goods_id)) {
+ $condition[] = [ 'goods_id', 'in', $goods_id ];
+ } else {
+ $condition[] = [ 'goods_id', '=', $goods_id ];
+ }
+
+ // 活动商品条件
+ $active_goods_count = $active_goods_model->where(array_merge($condition, [
+ [ 'active_goods_status', '=', 'active' ],
+ [ 'active_goods_type', 'in', [ ActiveDict::GOODS_SINGLE, ActiveDict::GOODS_INDEPENDENT ] ]
+ ]))->field($field)->with([
+ 'active' => function ($query) {
+ $query->withField('active_id,active_name, active_desc, start_time, end_time');
+ }
+ ])->count();
+
+ // 折扣商品条件
+ $discount_goods_count = $discount_goods_model->where(array_merge($condition, [
+ [ 'status', '=', 'active' ]
+ ]))->field('discount_goods_id')->with([
+ 'discount' => function ($query) {
+ $query->withField('discount_id');
+ }
+ ])->count();
+
+ return $active_goods_count + $discount_goods_count;
+ }
+
+}
diff --git a/niucloud/addon/shop/app/service/admin/marketing/CouponService.php b/niucloud/addon/shop/app/service/admin/marketing/CouponService.php
new file mode 100644
index 000000000..627abf5d1
--- /dev/null
+++ b/niucloud/addon/shop/app/service/admin/marketing/CouponService.php
@@ -0,0 +1,630 @@
+model = new Coupon();
+ }
+
+ public function getInit()
+ {
+ // 查询商品分类
+ $goods_category_tree = [];
+ $goods_category_service = new CategoryService();
+ $goods_category = $goods_category_service->getTree();
+ foreach ($goods_category as $k => $v) {
+ $children = [];
+ if (!empty($v['child_list'])) {
+ foreach ($v['child_list'] as $ck => $cv) {
+ $children[] = [
+ 'value' => $cv['category_id'],
+ 'label' => $cv['category_name'],
+ ];
+ }
+ }
+ $goods_category_tree[] = [
+ 'value' => $v['category_id'],
+ 'label' => $v['category_name'],
+ 'children' => $children
+ ];
+ }
+ $res['goods_category_tree'] = $goods_category_tree;
+ return $res;
+ }
+
+ /**
+ * 获取优惠券列表
+ * @param array $where
+ * @return array
+ * @throws \think\db\exception\DbException
+ */
+ public function getPage(array $where = [])
+ {
+ $field = 'id,title,price,type,receive_type,start_time,end_time,remain_count,receive_count,give_count,status,limit_count,min_condition_money,receive_status,valid_type,length,valid_end_time';
+ $order = 'id desc';
+ $search_model = $this->model->where([['id', '>', 0]])->withSearch(["title", "status"], $where)->append(['is_show_send', 'type_name', 'receive_type_name', 'status_name'])->field($field)->order($order);
+ $list = $this->pageQuery($search_model);
+ $coupon_member_model = new CouponMember();
+ foreach ($list['data'] as $k => &$v) {
+ if ($v['remain_count'] != '-1') {
+ $v['sum_count'] = $v['remain_count'] + $v['receive_count'];
+ } else {
+ $v['sum_count'] = '-1';
+ }
+ //查询已使用数量
+ $v['receive_use_count'] = $coupon_member_model->where([['coupon_id', '=', $v['id']], ['use_time', '>', 1]])->count();
+ }
+ return $list;
+ }
+
+ /**
+ * 获取优惠券选择分页列表
+ * @param array $where
+ * @return array
+ * @throws \think\db\exception\DbException
+ */
+ public function getSelectPage(array $where = [])
+ {
+ $verify_coupon_ids = [];
+ // 检测优惠券id集合是否存在,移除不存在的优惠券id,纠正数据准确性
+ if (!empty($where['verify_coupon_ids'])) {
+ $verify_coupon_ids = $this->model->where([
+ ['id', 'in', $where['verify_coupon_ids']]
+ ])->withSearch(["title"], $where)->field('id')->select()->toArray();
+
+ if (!empty($verify_coupon_ids)) {
+ $verify_coupon_ids = array_column($verify_coupon_ids, 'id');
+ }
+ }
+
+ $field = 'id,title,price,type,receive_type,start_time,end_time,remain_count,receive_count,status,limit_count,min_condition_money,receive_status,valid_type,length,valid_end_time';
+ $order = 'id desc';
+ $search_model = $this->model->where([['status', '=', CouponDict::NORMAL]])->withSearch(["title"], $where)->append(['type_name', 'receive_type_name', 'status_name'])->field($field)->order($order);
+ $list = $this->pageQuery($search_model);
+ $list['verify_coupon_ids'] = $verify_coupon_ids;
+ return $list;
+ }
+
+ /**
+ * 查询选中的优惠券
+ * @param string $coupon_ids
+ * @return array
+ * @throws \think\db\exception\DataNotFoundException
+ * @throws \think\db\exception\DbException
+ * @throws \think\db\exception\ModelNotFoundException
+ */
+ public function getSelectedList(string $coupon_ids = '')
+ {
+ if (empty($coupon_ids)) return [];
+ $field = 'id,title,price,type,receive_type,start_time,end_time,remain_count,receive_count,status,limit_count,min_condition_money,receive_status,valid_type,length,valid_end_time';
+ $order = 'id desc';
+ return $this->model->where([['id', 'in', $coupon_ids]])->append(['type_name', 'receive_type_name', 'status_name'])->field($field)->order($order)->select()->toArray();
+ }
+
+ /**
+ * 获取优惠券详情
+ * @param int $id
+ * @return array
+ */
+ public function getInfo(int $id)
+ {
+ $info = $this->model->where([['id', '=', $id]])->findOrEmpty()->toArray();
+ if ($info['remain_count'] == '-1') {
+ $info['limit'] = 2;
+ } else {
+ $info['limit'] = 1;
+ }
+ if ($info['min_condition_money'] == '0.00') {
+ $info['threshold'] = 2;
+ } else {
+ $info['threshold'] = 1;
+ }
+ if ($info['limit_count'] == 0) {
+ $info['limit_count'] = '';
+ }
+
+ if ($info['type'] == 2) {
+ $goods_coupon_model = new CouponGoods();
+ $goods_coupon_list = $goods_coupon_model->where([['coupon_id', '=', $id]])->field('category_id')->select()->toArray();
+ $info['goods_category_ids'] = array_column($goods_coupon_list, 'category_id');
+ } else {
+ $info['goods_category_ids'] = [];
+ }
+ if ($info['type'] == 3) {
+ $goods_coupon_model = new CouponGoods();
+ //获取商品ids
+ $goods_coupon_ids = $goods_coupon_model->where([['coupon_id', '=', $id]])->column('goods_id');
+ //获取选中商品信息
+ $goods_list = (new Goods())->field('goods_id,goods_cover,goods_name,status')
+ ->where([ ['goods.goods_id', 'in', $goods_coupon_ids], ['goods.status', '=', 1], ['goodsSku.is_default', '=', 1]])
+ ->withJoin(['goodsSku' => function ($query) {
+ $query->field('sku_id,sku_name,sku_image,goodsSku.stock,goodsSku.price');
+ }])
+ ->hidden(['goodsSku'])
+ ->append(['goods_cover_thumb_small'])->select()->toArray();
+ $info['goods_ids'] = $goods_coupon_ids;
+ $info['goods_list'] = $goods_list;
+ } else {
+ $info['goods_ids'] = [];
+ }
+ if ($info['remain_count'] != '-1') {
+ $info['sum_count'] = $info['remain_count'] + $info['receive_count'];
+ } else {
+ $info['remain_count'] = 1000;
+ $info['sum_count'] = '不限量';
+ }
+
+ //查询已使用数量
+ $coupon_member_model = new CouponMember();
+ $info['receive_invalid_count'] = $coupon_member_model->where([['coupon_id', '=', $info['id']], ['status', '=', CouponMemberDict::INVALID]])->count();
+ $info['receive_use_count'] = $coupon_member_model->where([['coupon_id', '=', $info['id']], ['use_time', '>', 1]])->count();
+
+ //查询已过期数量
+ $info['receive_expire_count'] = $coupon_member_model->where([['coupon_id', '=', $info['id']], ['use_time', '=', 0], ['expire_time', '<', time()]])->count();
+
+ return $info;
+ }
+
+ /**
+ * 添加优惠券
+ * @param array $data
+ * @return mixed
+ */
+ public function add(array $data)
+ {
+ if ($data['threshold'] == 2) {
+ $data['min_condition_money'] = 0;
+ }
+ if ($data['receive_type'] == 2) {
+ unset($data['receive_time']);
+ unset($data['valid_time']);
+ unset($data['limit_count']);
+ unset($data['remain_count']);
+ } else {
+ if ($data['receive_type_time'] == 1) {
+ if (!empty($data['receive_time'])) {
+ $data['start_time'] = strtotime($data['receive_time'][0]);
+ $data['end_time'] = strtotime($data['receive_time'][1]);
+ $now_time = strtotime(date('Y-m-d', time()));
+ if ($data['start_time'] > $now_time) {
+ $data['status'] = 0; // 活动未开始
+ }
+ } else {
+ $data['start_time'] = '';
+ $data['end_time'] = '';
+ }
+ } else {
+ $data['start_time'] = '';
+ $data['end_time'] = '';
+ }
+ if (!empty($data['valid_time'])) {
+ $data['valid_start_time'] = time();
+ $data['valid_end_time'] = strtotime($data['valid_time']);
+ if ($data['valid_end_time'] <= $data['valid_start_time']) throw new AdminException('SHOP_COUPON_VALID_END_TIME_NOT_ALLOW_LT_START_TIME');
+ }
+ if ($data['limit'] == 2) {
+ $data['remain_count'] = '-1';
+ }
+ }
+
+ if (!empty($data['goods_ids']) || !empty($data['goods_category_ids'])) {
+
+ $coupon_goods_model = new CouponGoods();
+ if (!empty($data['goods_ids'])) {
+ Db::startTrans();
+ try {
+ $res = $this->model->create($data);
+ $coupon_goods = [];
+ foreach ($data['goods_ids'] as $value) {
+ $coupon_goods[] = [
+ 'coupon_id' => $res->id,
+ 'goods_id' => $value,
+ ];
+ }
+ $coupon_goods_model->saveAll($coupon_goods);
+ Db::commit();
+ return $res->id;
+ } catch (\Exception $e) {
+ Db::rollback();
+ throw new CommonException($e->getMessage());
+ }
+ }
+ if (!empty($data['goods_category_ids'])) {
+ Db::startTrans();
+ try {
+ $res = $this->model->create($data);
+ $coupon_goods = [];
+ foreach ($data['goods_category_ids'] as $category) {
+ $coupon_goods[] = [
+ 'coupon_id' => $res->id,
+ 'category_id' => $category[count($category) - 1],
+ ];
+ }
+
+ $coupon_goods_model->saveAll($coupon_goods);
+ Db::commit();
+ return $res->id;
+ } catch (\Exception $e) {
+ Db::rollback();
+ throw new CommonException($e->getMessage());
+ }
+ }
+ } else {
+ $res = $this->model->create($data);
+ return $res->id;
+ }
+ }
+
+ /**
+ * 编辑优惠券
+ * @param int $id
+ * @param array $data
+ * @return bool
+ */
+ public function edit(int $id, array $data)
+ {
+ $coupon_ids = $this->checkCouponInUse();
+ if (in_array($id, $coupon_ids)) {
+ throw new AdminException('SHOP_COUPON_IN_USE_NOT_ALLOW_EDIT');
+ }
+ if ($data['threshold'] == 2) {
+ $data['min_condition_money'] = 0;
+ }
+ unset($data['threshold']);
+ if ($data['receive_type'] == 2) {
+ unset($data['receive_time']);
+ unset($data['valid_time']);
+ unset($data['limit_count']);
+ unset($data['remain_count']);
+
+ } else {
+ if ($data['receive_type_time'] == 1) {
+ if (!empty($data['receive_time'])) {
+ $data['start_time'] = strtotime($data['receive_time'][0]);
+ $data['end_time'] = strtotime($data['receive_time'][1]);
+ $now_time = strtotime(date('Y-m-d', time()));
+ if ($data['start_time'] > $now_time) {
+ $data['status'] = 0; // 活动未开始
+ }
+ } else {
+ $data['start_time'] = '';
+ $data['end_time'] = '';
+ $data['status'] = 1;
+ }
+ } else {
+ $data['start_time'] = '';
+ $data['end_time'] = '';
+ $data['status'] = 1;
+ }
+
+ if ($data['valid_type'] == 2) {
+ if (!empty($data['valid_time'])) {
+ $data['valid_start_time'] = time();
+ $data['valid_end_time'] = strtotime($data['valid_time']);
+ if ($data['valid_end_time'] <= $data['valid_start_time']) throw new AdminException('SHOP_COUPON_VALID_END_TIME_NOT_ALLOW_LT_START_TIME');
+ }
+ } else {
+ $data['valid_start_time'] = '';
+ $data['valid_end_time'] = '';
+ }
+ if ($data['limit'] == 2) {
+ $data['remain_count'] = '-1';
+ }
+
+ }
+ unset($data['limit']);
+ unset($data['receive_time']);
+ unset($data['valid_time']);
+ unset($data['receive_type_time']);
+ unset($data['type']);
+
+ $coupon_goods_model = new CouponGoods();
+ if (!empty($data['goods_ids'])) {
+ Db::startTrans();
+ try {
+
+ $coupon_goods = [];
+ $coupon_goods_model->where([['coupon_id', '=', $id]])->delete();
+ foreach ($data['goods_ids'] as $value) {
+ $coupon_goods[] = [
+ 'coupon_id' => $id,
+ 'goods_id' => $value,
+ ];
+ }
+ $coupon_goods_model->saveAll($coupon_goods);
+ unset($data['goods_ids']);
+ unset($data['goods_category_ids']);
+ Db::commit();
+ } catch (\Exception $e) {
+ Db::rollback();
+ throw new CommonException($e->getMessage());
+ }
+ } else if (!empty($data['goods_category_ids'])) {
+ Db::startTrans();
+ try {
+ $coupon_goods = [];
+ $coupon_goods_model->where([['coupon_id', '=', $id]])->delete();
+ foreach ($data['goods_category_ids'] as $category) {
+ $coupon_goods[] = [
+ 'coupon_id' => $id,
+ 'category_id' => $category[count($category) - 1],
+ ];
+ }
+ $coupon_goods_model->saveAll($coupon_goods);
+ unset($data['goods_ids']);
+ unset($data['goods_category_ids']);
+ Db::commit();
+ } catch (\Exception $e) {
+ Db::rollback();
+ throw new CommonException($e->getMessage());
+ }
+ } else {
+ unset($data['goods_ids']);
+ unset($data['goods_category_ids']);
+ Db::startTrans();
+ try {
+ $coupon_goods_model->where([['coupon_id', '=', $id]])->delete();
+ Db::commit();
+ } catch (\Exception $e) {
+ Db::rollback();
+ throw new CommonException($e->getMessage());
+ }
+ }
+ $res = $this->model->where([
+ ['id', '=', $id]
+ ])->update($data);
+ (new CoreCouponMemberService())->refeshMemberCouponExpireTime($id);
+ return $res;
+ }
+
+ /**
+ * 删除优惠券
+ * @param $ids
+ * @return bool
+ * @throws \think\db\exception\DataNotFoundException
+ * @throws \think\db\exception\DbException
+ * @throws \think\db\exception\ModelNotFoundException
+ */
+ public function del($ids)
+ {
+ if (empty($ids)) {
+ return true;
+ }
+ $coupon_list = $this->model->where([
+ ['id', 'in', implode(',', $ids)],
+ ])->field('id,status,title')->select()->toArray();
+ $coupon_names = array_column($coupon_list, 'title', 'id');
+
+ $use_coupon_list = (new CouponMember())->where([
+ ['coupon_id', 'in', implode(',', $ids)],
+ ['status', '=', CouponMemberDict::WAIT_USE]
+ ])->field('coupon_id')->select()->toArray();
+
+ $not_del_coupon_list = array_unique(array_column($use_coupon_list, 'coupon_id'));
+ if (count($not_del_coupon_list) > 0) {
+ $err_str = '';
+ foreach ($not_del_coupon_list as $coupon_id) {
+ $err_str .= $coupon_names[$coupon_id] . '、';
+ }
+ $err_str = rtrim($err_str, '、');
+ $err_str .= " \n" . get_lang('SHOP_COUPON_IN_USE_NOT_ALLOW_DEL');
+ throw new AdminException($err_str);
+ }
+ return $this->model->where([ ['id', 'in', implode(',', $ids)]])->delete();
+ }
+
+ /**
+ * 领取记录
+ * @param int $id
+ * @return void
+ */
+ public function getMemberCoupon($data)
+ {
+ $coupon_member_model = new CouponMember();
+ $member_where = [];
+ if (isset($data['keywords']) && $data['keywords'] != '') {
+ $member_where = [['member.member_no|member.username|member.nickname|member.mobile', 'like', '%' . $this->model->handelSpecialCharacter($data['keywords']) . '%']];
+ }
+ $memberList = $coupon_member_model->where([['coupon_id', '=', $data['id']]])->withJoin([
+ 'member' => ['member_id', 'member_no', 'username', 'mobile', 'nickname'],
+ ])->where($member_where)->order('id desc')->append(['status_name', 'receive_type_name']);
+ $list = $this->pageQuery($memberList);
+ return $list;
+ }
+
+ /**
+ * 领取状态修改
+ * @param $id
+ * @param $status
+ * @return true
+ */
+ public function setStatus($id, $status)
+ {
+ $coupon_ids = $this->checkCouponInUse();
+ if (in_array($id, $coupon_ids)) {
+ throw new AdminException('SHOP_COUPON_IN_USE_NOT_ALLOW_EDIT');
+ }
+ $data = array(
+ 'receive_status' => $status
+ );
+ $this->model->where([['id', '=', $id]])->update($data);
+ return true;
+ }
+
+ /**
+ * 优惠券失效
+ * @param $id
+ * @param $status
+ * @return true
+ */
+ public function couponInvalid($ids)
+ {
+ $data = array(
+ 'status' => CouponDict::INVALID
+ );
+ $res = $this->model->where([['id', 'in', implode(',', $ids)]])->update($data);
+ $coupon_member_model = new CouponMember();
+ if ($res) $coupon_member_model->where([ ['coupon_id', 'in', implode(',', $ids)], ['status', '=', CouponMemberDict::WAIT_USE]])->update(['status' => CouponMemberDict::INVALID]);
+ return true;
+ }
+
+
+ /**
+ * 优惠券使用检测
+ * @return array
+ */
+ public function checkCouponInUse()
+ {
+ $coupon_ids = [];
+ $sign_config = (new CoreConfigService())->getConfig( 'SIGN_CONFIG');
+ if (!empty($sign_config) && !empty($sign_config['value'])) {
+ $sign_info = $sign_config['value'];
+ if (!empty($sign_info['day_award']) && !empty($sign_info['day_award']['shop_coupon'])) {
+ $coupon_ids = $sign_info['day_award']['shop_coupon']['coupon_id'];
+ }
+ if (!empty($sign_info['continue_award'])) {
+ foreach ($sign_info['continue_award'] as $item) {
+ if (!empty($item['shop_coupon'])) {
+ $coupon_ids = array_merge($coupon_ids, $item['shop_coupon']['coupon_id']);
+ }
+ }
+ }
+ $coupon_ids = array_values(array_unique($coupon_ids));
+ }
+ return $coupon_ids;
+ }
+
+ public function getSendReordsPageList($coupon_id, $data)
+ {
+ $where[] = ['coupon_id', '=', $coupon_id];
+ if (!empty($data['range_type'])) {
+ $where[] = ['range_type', '=', $data['range_type']];
+ }
+ $model = (new CouponSendRecord())->where($where)->with([
+ 'coupon' => function ($query) {
+ $query->field('title,id');
+ }
+ ])->withSearch(['create_time'], $data)->field("success_num,status,id,coupon_id,range_type,range_param,end_time,admin_username,create_time")->append(['status_name', 'range_param_value', 'range_type_name'])->order('create_time desc');
+ $list = $this->pageQuery($model);
+ return $list;
+ }
+
+ /**
+ * 添加发券记录
+ * @param $coupon_id
+ * @param $data
+ * @return true
+ * @throws \think\db\exception\DbException
+ */
+ public function sendCoupon($coupon_id, $data)
+ {
+ $coupon = (new Coupon())->where([['id', '=', $coupon_id]])->findOrEmpty();
+ if ($coupon->isEmpty()) {
+ throw new CommonException('COUPON_NOT_EXIST');
+ }
+ if ($coupon->status != CouponDict::NORMAL) {
+ throw new CommonException('COUPON_INVALID');
+ }
+ $range_param = $data['range_param'] ?? [];
+ list($member_num, $range_param) = $this->getSendMemberNum($data['range_type'], $range_param);
+ $data = [
+ 'coupon_id' => $coupon_id,
+ 'send_num' => $data['send_num'],
+ 'range_type' => $data['range_type'],
+ 'range_param' => $range_param,
+ 'member_num' => $member_num,
+ 'status' => CouponDict::SEND_STATUS_WAIT,
+ 'admin_uid' => $this->uid,
+ 'admin_username' => $this->username,
+ 'create_time' => time(),
+ ];
+ $record_id = (new CouponSendRecord())->insertGetId($data);
+ CouponSend::dispatch(['record_id' => $record_id]);
+ return true;
+ }
+
+ /**
+ * 获取发送用户数量
+ * @param $range_type
+ * @param $range_param
+ * @return array
+ * @throws \think\db\exception\DbException
+ */
+ public function getSendMemberNum($range_type, $range_param)
+ {
+ switch ($range_type) {
+ case CouponDict::SEND_RANGE_ALL:
+ $member_num = (new Member())->where([
+ ])->count();
+ break;
+ case CouponDict::SEND_RANGE_MEMBER:
+ $member_num = count($range_param['member_ids']);
+ break;
+ case CouponDict::SEND_RANGE_MEMBER_LEVEL:
+ $member_level = $range_param['member_level'];
+ $member_num = (new Member())->where([
+ ['member_level', 'in', implode(',', $member_level)]
+ ])->count();
+ $level_names = (new MemberLevel())->where([
+ ['level_id', 'in', implode(',', $member_level)]
+ ])->column('level_name');
+ $range_param['level_name'] = implode('、', $level_names);
+ break;
+ case CouponDict::SEND_RANGE_MEMBER_LABEL:
+ $member_label = $range_param['member_label'];
+ $member_num = (new Member())->where([
+ ['member_id', '>', 0]
+ ])->withSearch(['member_label'], ['member_label' => $member_label])->count();
+ $label_names = (new MemberLabel())->where([
+ ['label_id', 'in', implode(',', $member_label)]
+ ])->column('label_name') ?? [];
+ $range_param['label_name'] = implode('、', $label_names);;
+ break;
+ default:
+ $member_num = 0;
+ break;
+ }
+ return [$member_num, $range_param];
+
+ }
+
+}
diff --git a/niucloud/addon/shop/app/service/admin/marketing/DiscountService.php b/niucloud/addon/shop/app/service/admin/marketing/DiscountService.php
new file mode 100644
index 000000000..a457c336f
--- /dev/null
+++ b/niucloud/addon/shop/app/service/admin/marketing/DiscountService.php
@@ -0,0 +1,789 @@
+model = new Discount();
+ }
+
+ /**
+ * 获取限时折扣列表
+ * @param array $where
+ * @return array
+ */
+ public function getPage(array $where = [])
+ {
+ $field = 'discount_id,name,remark,start_time,end_time,status,create_time,order_money,order_num,member_num,success_num';
+ $order = 'discount_id desc';
+ $search_model = $this->model->where([ [ 'discount_id', '>', 0 ] ])->withSearch([ "name", "status", "active_id" ], $where)->append([ 'status_name' ])->field($field)->order($order);
+ $list = $this->pageQuery($search_model);
+ return $list;
+ }
+
+ /**
+ * 获取限时折扣详情
+ * @param int $discount_id
+ * @return array
+ */
+ public function getInfo(int $discount_id)
+ {
+ $info = $this->model->field('discount_id,name,remark,start_time,end_time,status,create_time,order_money,order_num,member_num,success_num')
+ ->where([ [ 'discount_id', '=', $discount_id ]])
+ ->append([ 'status_name' ])
+ ->findOrEmpty()->toArray();
+ return $info;
+ }
+
+ /**
+ * 获取限时折扣详情
+ * @param int $discount_id
+ * @return array
+ */
+ public function getDetail(int $discount_id)
+ {
+ $info = $this->model->where([ [ 'discount_id', '=', $discount_id ] ])->append([ 'status_name' ])->findOrEmpty()->toArray();
+ $active_goods = ( new DiscountGoods() )
+ ->field('discount_goods_id,discount_id,goods_id,sku_id,type,rate,reduce_money,discount_price,is_enabled')
+ ->where([ [ 'discount_id', '=', $discount_id ] ])
+ ->withJoin([ 'goods' => function($query){
+ $query->field('goods.goods_id,goods_name,goods_cover,goods_type');
+ },'goodsSku' => function($query){
+ $query->field('goodsSku.sku_id,price,sku_name,sku_image');
+ }])
+ ->append([ 'goods_cover_thumb_small'])
+ ->hidden(['goods', 'goodsSku'])
+ ->select()
+ ->toArray();
+
+ $goods_sku_data = $goods_info =[];
+ foreach($active_goods as $value){
+ $goods_sku_data[$value['goods_id']][] = $value;
+ }
+ foreach ($goods_sku_data as $value){
+ if (count($value) > 1){
+
+ $filtered = array_filter($value, fn($item) => $item['is_enabled'] == 1);
+ $rates = array_map(fn($item) => floatval($item['rate']), $filtered);
+ $reduce_money = array_map(fn($item) => floatval($item['reduce_money']), $filtered);
+ $discount_price = array_map(fn($item) => floatval($item['discount_price']), $filtered);
+
+ $goods_info[$value[0]['goods_id']] = [
+ 'goods_cover_thumb_small' => $value[0]['goods_cover_thumb_small'] ?? '',
+ 'goods_id' => $value[0]['goods_id'] ?? '',
+ 'sku_id' => $value[0]['sku_id'] ?? '',
+ 'type' => $value[0]['type'] ?? '',
+ 'goods_type' => $value[0]['goods_type'] ?? '',
+ 'goods_type_name' => GoodsDict::getType($value[0]['goods_type'])[ 'name' ] ?? '',
+ 'goods_name' => $value[0]['goods_name'] ?? '',
+ 'price' => $value[0]['price'] ?? '',
+ 'min_rate' => !empty($rates) ? $this->formatNumber(min($rates)) : null,
+ 'max_rate' => !empty($rates) ? $this->formatNumber(max($rates)) : null,
+ 'min_reduce_money' => !empty($reduce_money) ? min($reduce_money) : null,
+ 'max_reduce_money' => !empty($reduce_money) ? max($reduce_money) : null,
+ 'min_discount_price' => !empty($discount_price) ? min($discount_price) : null,
+ 'max_discount_price' => !empty($discount_price) ? max($discount_price) : null,
+ 'spec_type' => 'multi',
+ 'goods_sku_list' => $value,
+ ];
+ }else{
+ $goods_info[$value[0]['goods_id']] = [
+ 'goods_cover_thumb_small' => $value[0]['goods_cover_thumb_small'] ?? '',
+ 'goods_id' => $value[0]['goods_id'] ?? '',
+ 'sku_id' => $value[0]['sku_id'] ?? '',
+ 'type' => $value[0]['type'] ?? '',
+ 'goods_type' => $value[0]['goods_type'] ?? '',
+ 'goods_type_name' => GoodsDict::getType($value[0]['goods_type'])[ 'name' ] ?? '',
+ 'goods_name' => $value[0]['goods_name'] ?? '',
+ 'price' => $value[0]['price'] ?? '',
+ 'rate' => $this->formatNumber($value[0]['rate']) ?? '',
+ 'reduce_money' => $value[0]['reduce_money'] ?? '',
+ 'discount_price' => $value[0]['discount_price'] ?? '',
+ 'spec_type' => 'single',
+ 'goods_sku_list' => $value,
+ ];
+ }
+ }
+ $info['goods_info'] = array_values($goods_info);
+ return $info;
+ }
+
+ /**
+ * 添加限时折扣
+ * @param array $data
+ * @return mixed
+ */
+ public function add(array $data)
+ {
+ $goods_list = $data['goods_list'];
+ $goods_ids = array_column($goods_list, 'goods_id');
+ $data[ 'start_time' ] = strtotime($data[ 'start_time' ]);
+ $data[ 'end_time' ] = strtotime($data[ 'end_time' ]);
+ $data[ 'create_time' ] = time();
+ $data[ 'update_time' ] = time();
+
+ $this->checkGoods($goods_list);
+
+ $check_condition = [
+ [ 'discount_goods.goods_id', 'in', $goods_ids ],
+ ];
+
+ $goods_where = [
+ [ 'discount.status', 'in', [ DiscountDict::NOT_ACTIVE, DiscountDict::ACTIVE ] ]
+ ];
+ $goods_where_or = [
+ [ 'discount.start_time|discount.end_time', 'between', [ $data[ 'start_time' ], $data[ 'end_time' ] ] ],
+ [ [ 'discount.start_time', '<=', $data[ 'start_time' ] ], [ 'discount.end_time', '>=', $data[ 'end_time' ] ] ],
+ [ [ 'discount.start_time', '>=', $data[ 'start_time' ] ], [ 'discount.end_time', '<=', $data[ 'end_time' ] ] ],
+ ];
+
+ $discount_goods_model = new DiscountGoods();
+ $count = $discount_goods_model->where($check_condition)
+ ->withJoin([
+ 'discount' => function(Query $query) use ($goods_where, $goods_where_or) {
+ $query->where($goods_where)->where(function($query) use ($goods_where_or) {
+ $query->whereOr($goods_where_or);
+ });
+ },
+ ], 'inner')
+ ->count();
+
+ if ($count > 0) throw new AdminException('ACTIVE_GOODS_NOT_REPEAR');
+
+ Db::startTrans();
+ try {
+ $status = DiscountDict::NOT_ACTIVE;
+
+ $time = time();
+ if (!empty($data[ 'start_time' ]) && $data[ 'start_time' ] <= $time) {
+ $status = DiscountDict::ACTIVE;
+ } elseif (!empty($data[ 'end_time' ]) && $data[ 'end_time' ] <= $time) {
+ $status = DiscountDict::END;
+ }
+ $data[ 'status' ] = $status;
+ $discount_id = $this->model->create($data)->discount_id;
+
+ $discount_goods = [];
+ foreach ($goods_list as $k => $v) {
+ foreach($v['sku_list'] as $item){
+ $discount_goods[] = [
+ 'discount_id' => $discount_id,
+ 'goods_id' => $item[ 'goods_id' ],
+ 'sku_id' => $item[ 'sku_id' ],
+ 'status' => $status,
+ 'type' => $item[ 'discount_type' ],
+ 'rate' => $item[ 'discount_rate' ],
+ 'reduce_money' => $item[ 'reduce_money' ],
+ 'discount_price' => $item[ 'discount_price' ] ?? $item[ 'reduce_money' ],
+ 'is_enabled' => $item[ 'is_enabled' ] ?? 1,
+ ];
+ }
+ }
+
+ (new DiscountGoods())->saveAll($discount_goods);
+
+ if (!empty($data[ 'start_time' ]) && $data[ 'start_time' ] <= $time) {
+ $this->discountStartAfter($discount_id);
+ } elseif (!empty($data[ 'end_time' ]) && $data[ 'end_time' ] <= $time) {
+ $this->discountEndAfter($discount_id);
+ }
+
+ Db::commit();
+ return $discount_id;
+ } catch (\Exception $e) {
+ Db::rollback();
+ throw new CommonException($e->getMessage());
+ }
+ }
+
+ /**
+ * 编辑限时折扣
+ * @param int $discount_id
+ * @param array $data
+ * @return bool
+ */
+ public function edit(int $discount_id, array $data)
+ {
+ $goods_list = $data['goods_list'];
+ $goods_ids = array_column($goods_list, 'goods_id');
+ $data[ 'start_time' ] = strtotime($data[ 'start_time' ]);
+ $data[ 'end_time' ] = strtotime($data[ 'end_time' ]);
+ $data[ 'create_time' ] = time();
+ $data[ 'update_time' ] = time();
+
+ $this->checkGoods($goods_list);
+
+ $check_condition = [
+ [ 'discount_goods.goods_id', 'in', $goods_ids ],
+ [ 'discount_goods.discount_id', '<>', $discount_id ],
+ ];
+
+ $goods_where = [
+ [ 'discount.status', 'in', [ DiscountDict::NOT_ACTIVE, DiscountDict::ACTIVE ] ]
+ ];
+ $goods_where_or = [
+ [ 'discount.start_time|discount.end_time', 'between', [ $data[ 'start_time' ], $data[ 'end_time' ] ] ],
+ [ [ 'discount.start_time', '<=', $data[ 'start_time' ] ], [ 'discount.end_time', '>=', $data[ 'end_time' ] ] ],
+ [ [ 'discount.start_time', '>=', $data[ 'start_time' ] ], [ 'discount.end_time', '<=', $data[ 'end_time' ] ] ],
+ ];
+
+ $discount_goods_model = new DiscountGoods();
+ $count = $discount_goods_model->where($check_condition)
+ ->withJoin([
+ 'discount' => function(Query $query) use ($goods_where, $goods_where_or) {
+ $query->where($goods_where)->where(function($query) use ($goods_where_or) {
+ $query->whereOr($goods_where_or);
+ });
+ },
+ ], 'inner')
+ ->count();
+ if ($count > 0) throw new AdminException('ACTIVE_GOODS_NOT_REPEAR');
+
+ $this->model->where([ [ 'discount_id', '=', $discount_id ] ])->update([ 'status' => DiscountDict::NOT_ACTIVE ]);
+ $this->discountEndAfter($discount_id);
+
+ $status = DiscountDict::NOT_ACTIVE;
+ $time = time();
+ if (!empty($data[ 'start_time' ]) && $data[ 'start_time' ] <= $time) {
+ $status = DiscountDict::ACTIVE;
+ } elseif (!empty($data[ 'end_time' ]) && $data[ 'end_time' ] <= $time) {
+ $status = DiscountDict::END;
+ }
+
+ $active_goods_data = $discount_goods_model->where([ [ 'discount_id', '=', $discount_id]])->select()->toArray();
+ $active_goods_ids = array_unique(array_column($active_goods_data,'goods_id'));
+ $discount_goods = [];
+ foreach ($goods_list as $k=>$v){
+ foreach($v['sku_list'] as $item){
+ $discount_goods[] = [
+ 'discount_id' => $discount_id,
+ 'goods_id' => $item[ 'goods_id' ],
+ 'sku_id' => $item[ 'sku_id' ],
+ 'status' => $status,
+ 'type' => $item[ 'discount_type' ],
+ 'rate' => $item[ 'discount_rate' ],
+ 'reduce_money' => $item[ 'reduce_money' ],
+ 'discount_price' => $item[ 'discount_price' ] ?? $item[ 'reduce_money' ],
+ 'is_enabled' => $item[ 'is_enabled' ] ?? 1,
+ ];
+ }
+ }
+ $delete_goods_ids = array_diff($active_goods_ids, $goods_ids);
+ unset($data['goods_list']);
+ Db::startTrans();
+ try {
+ $data[ 'discount_id' ] = $discount_id;
+ $data[ 'status' ] = $status;
+
+ $this->model->where([ [ 'discount_id', '=', $discount_id]])->update($data);
+
+ foreach ($discount_goods as $v){
+ $discount_goods_info = $discount_goods_model->where([ [ 'discount_id', '=', $v['discount_id']], [ 'goods_id', '=', $v['goods_id']], [ 'sku_id', '=', $v['sku_id']]])->findOrEmpty();
+ if($discount_goods_info->isEmpty()){
+ $discount_goods_model->create($v);
+ }else{
+ $discount_goods_model->where([ [ 'discount_id', '=', $v['discount_id']], [ 'goods_id', '=', $v['goods_id']], [ 'sku_id', '=', $v['sku_id']]])->update($v);
+ }
+ }
+
+ $discount_goods_model->where([ [ 'goods_id', 'in', $delete_goods_ids], [ 'discount_id', '=', $discount_id]])->delete();
+
+ if (!empty($data[ 'start_time' ]) && $data[ 'start_time' ] <= $time) {
+ $this->discountStartAfter($discount_id);
+ } elseif (!empty($data[ 'end_time' ]) && $data[ 'end_time' ] <= $time) {
+ $this->discountEndAfter($discount_id);
+ }
+
+ Db::commit();
+ return $discount_id;
+ } catch (\Exception $e) {
+ Db::rollback();
+ throw new CommonException($e->getMessage());
+ }
+ }
+
+ /**
+ * 限时折扣商品校验
+ * @param $data
+ * @return array
+ */
+ public function checkGoodsData($data)
+ {
+ $error = [
+ 'code' => 1,
+ 'data' => []
+ ];
+ $goods_ids = $data[ 'goods_ids' ];
+ $discount_goods_model = new DiscountGoods();
+ $select_goods_id = $discount_goods_model
+ ->where([ [ 'discount_goods.discount_goods_id', '>', 0 ] ])
+ ->withJoin([
+ 'discount' => function(Query $query) use ($data) {
+ $query->where([ [ 'discount.status', 'in', [ DiscountDict::NOT_ACTIVE, DiscountDict::ACTIVE ] ] ])->where(function($query) use ($data) {
+ $query->whereOr([ [ 'discount.start_time|discount.end_time', 'between', [ strtotime($data[ 'start_time' ]), strtotime($data[ 'end_time' ]) ] ],
+ [ [ 'discount.start_time', '<=', strtotime($data[ 'start_time' ]) ], [ 'discount.end_time', '>=', strtotime($data[ 'end_time' ]) ] ],
+ [ [ 'discount.start_time', '>=', strtotime($data[ 'start_time' ]) ], [ 'discount.end_time', '<=', strtotime($data[ 'end_time' ]) ] ] ]);
+ });
+ },
+ ], 'inner')
+ ->column('goods_id');
+
+ if (!empty($select_goods_id)) {
+ if (!empty($data[ 'discount_id' ])) {
+ $select_goods_ids = $discount_goods_model->where([
+ [ 'discount_id', '=', $data[ 'discount_id' ] ]
+ ])->column('goods_id');
+ $goods_ids = array_diff($goods_ids, $select_goods_ids);
+ }
+ $goods_id_intersect = array_intersect($goods_ids, $select_goods_id);
+ if (!empty($goods_id_intersect)) {
+ foreach ($goods_id_intersect as $goods_id) {
+ $discount_info = $discount_goods_model->where([
+ [ 'goods_id', '=', $goods_id ],
+ [ 'status', 'in', [ DiscountDict::NOT_ACTIVE, DiscountDict::ACTIVE ] ],
+ ])->with([ 'discount' => function($query) use ($data) {
+ $query->field('discount_id,name');
+ } ])->findOrEmpty()->toArray();
+ if (!empty($discount_info)) {
+ $error[ 'code' ] = -1;
+ $error[ 'data' ][] = [
+ 'goods_id' => $goods_id,
+ 'error_msg' => '该商品已参加【' . $discount_info[ 'discount' ][ 'name' ] . '】活动'
+ ];
+ }
+ }
+ }
+ }
+ return $error;
+ }
+
+ /**
+ * 商品结构校验
+ * @param $goods_list
+ * @return void
+ */
+ public function checkGoods($goods_list)
+ {
+ if (empty($goods_list)) throw new AdminException('DISCOUNT_GOODS_NOT_EMPTY');
+ foreach ($goods_list as $k => $v) {
+ if (empty($v[ 'sku_list' ])) throw new AdminException('DISCOUNT_GOODS_SKU_NOT_EMPTY');
+ foreach ($v[ 'sku_list' ] as $key => $value) {
+ if (!isset($value[ 'is_enabled' ])) throw new AdminException('DISCOUNT_IS_ENABLED_NOT_EMPTY');
+
+ if ($value[ 'is_enabled' ]) {
+ if (empty($value[ 'discount_type' ])) throw new AdminException('DISCOUNT_GOODS_DISCOUNT_TYPE_NOT_EMPTY');
+ if (!in_array($value[ 'discount_type' ], [ 'discount', 'reduce', 'specify' ])) throw new AdminException('DISCOUNT_GOODS_DISCOUNT_TYPE_ERROR');
+ if (empty($value[ 'discount_price' ]) && $value[ 'discount_price' ] != 0) throw new AdminException('DISCOUNT_GOODS_DISCOUNT_PRICE_NOT_EMPTY');
+ if (empty($value[ 'discount_rate' ]) && $value[ 'discount_price' ] != 0) throw new AdminException('DISCOUNT_GOODS_DISCOUNT_RATE_NOT_EMPTY');
+ if (empty($value[ 'reduce_money' ]) && $value[ 'discount_price' ] != 0) throw new AdminException('DISCOUNT_GOODS_REDUCE_MONEY_NOT_EMPTY');
+ }
+ }
+ }
+ }
+
+ /**
+ * 删除限时折扣
+ * @param int $discount_id
+ * @return bool
+ */
+ public function del(int $discount_id)
+ {
+ $info = $this->model->where([ ['discount_id', '=', $discount_id] ])->findOrEmpty();
+ if ($info->isEmpty()) throw new AdminException('ACTIVE_NOT_FOUND');
+ if ($info->status == DiscountDict::ACTIVE) throw new AdminException('ACTIVE_NOT_DELETE');
+ $this->model->where([ [ 'discount_id', '=', $discount_id ] ])->delete();
+ (new DiscountGoods())->where([ [ 'discount_id', '=', $discount_id ] ])->delete();
+ return true;
+ }
+
+ /**
+ * 批量删除限时折扣
+ * @param array $ids
+ * @return bool
+ */
+ public function batchDel($ids)
+ {
+ $discount_list = $this->model->where([ [ 'discount_id', 'in', $ids ] ])->select()->toArray();
+ foreach ($discount_list as $value){
+ if ($value[ 'status' ] == DiscountDict::ACTIVE) throw new AdminException('ACTIVE_NOT_DELETE');
+ }
+
+ Db::startTrans();
+ try {
+ $this->model->where([ [ 'discount_id', 'in', $ids ] ])->delete();
+ (new DiscountGoods())->where([ [ 'discount_id', 'in', $ids ] ])->delete();
+
+ Db::commit();
+ return true;
+ } catch (\Exception $e) {
+ Db::rollback();
+ throw new CommonException($e->getMessage());
+ }
+ }
+
+ /**
+ * 批量关闭限时折扣
+ * @param array $ids
+ * @return bool
+ */
+ public function batchClose($ids)
+ {
+ $discount_goods_model = new DiscountGoods();
+ $shop_goods_model = new Goods();
+ $shop_goods_sku_model = new GoodsSku();
+
+ $discount_list = $this->model->where([ [ 'discount_id', 'in', $ids ] ])->select()->toArray();
+ if (empty($discount_list)) throw new AdminException('ACTIVE_NOT_FOUND');
+
+ $discount_goods_ids = $discount_goods_model->where([ [ 'discount_id', 'in', $ids ] ])->column('goods_id');
+
+ Db::startTrans();
+ try {
+ $this->model->where([ ['discount_id', 'in', $ids], ['status', '=', DiscountDict::ACTIVE] ])->update([ 'status' => DiscountDict::CLOSE ]);
+ $discount_goods_model->where([ ['discount_id', 'in', $ids]])->update([ 'status' => DiscountDict::CLOSE ]);
+ $shop_goods_model->where([ [ 'goods_id', 'in', $discount_goods_ids ] ])->update([ 'is_discount' => 0 ]);
+ $shop_goods_sku_model->where([ [ 'goods_id', 'in', $discount_goods_ids ] ])->update([ 'sale_price' => Db::raw('price') ]);
+ Db::commit();
+ return true;
+ } catch (\Exception $e) {
+ Db::rollback();
+ throw new CommonException($e->getMessage());
+ }
+
+
+
+ }
+
+ /**
+ * 设置商品限时折扣
+ * @param $discount_ids
+ * @return void
+ */
+ public function setGoodsDiscount($discount_ids)
+ {
+ $list = $this->model->where([ [ 'discount_id', 'in', $discount_ids ],['status','=',DiscountDict::ACTIVE] ])->select()->toArray();
+ if (empty($list)) return true;
+ $discount_goods_model = new DiscountGoods();
+ $shop_goods_model = new Goods();
+ $shop_goods_sku_model = new GoodsSku();
+ $discount_goods_list = $discount_goods_model->where([ [ 'discount_id', 'in', $discount_ids ] ])->field('goods_id, discount_id,sku_id,is_enabled,discount_price')->select()->toArray();
+ $discount_goods_ids = array_unique(array_column($discount_goods_list, 'goods_id' ));
+ $shop_goods_model->where([ [ 'goods_id', 'in', $discount_goods_ids ] ])->update([ 'is_discount' => 1]);
+ foreach ($discount_goods_list as $k => $v) {
+ if ($v[ 'is_enabled' ]) {
+ $shop_goods_sku_model->where([ [ 'sku_id', '=', $v[ 'sku_id' ] ] ])->update([
+ 'sale_price' => $v[ 'discount_price' ]
+ ]);
+ }
+ }
+ return true;
+ }
+
+ /**
+ * 设置商品取消限时折扣
+ * @param $discount_id
+ * @return bool
+ */
+ public function cancelGoodsDiscount($discount_ids)
+ {
+ $list = $this->model->where([ [ 'discount_id', 'in', $discount_ids ],['status','=',DiscountDict::ACTIVE] ])->select()->toArray();
+ if (empty($list)) return true;
+
+ $discount_goods_model = new DiscountGoods();
+ $shop_goods_model = new Goods();
+ $shop_goods_sku_model = new GoodsSku();
+
+ $discount_goods_list = $discount_goods_model->where([ [ 'discount_id', 'in', $discount_ids ] ])->field('goods_id, discount_id')->select()->toArray();
+ $discount_goods_ids = array_column($discount_goods_list, 'goods_id');
+ $shop_goods_model->where([ [ 'goods_id', 'in', $discount_goods_ids ] ])->update([ 'is_discount' => 0 ]);
+ $shop_goods_sku_model->where([ [ 'goods_id', 'in', $discount_goods_ids ] ])->update([ 'sale_price' => Db::raw('price') ]);
+
+ return true;
+ }
+
+
+ /**
+ * 活动关闭
+ * @return void
+ */
+ public function discountClose($discount_id)
+ {
+ $this->model->where([ ['discount_id', '=', $discount_id], ['status', '=', DiscountDict::ACTIVE] ])->update([ 'status' => DiscountDict::CLOSE ]);
+ (new DiscountGoods())->where([ ['discount_id', '=', $discount_id]])->update([ 'status' => DiscountDict::CLOSE ]);
+ $this->discountEndAfter($discount_id);
+ return true;
+ }
+
+ /**
+ * 活动开启
+ * @return void
+ */
+ public function discountStartAfter($discount_ids)
+ {
+ if (!is_array($discount_ids)) {
+ $discount_ids = [$discount_ids];
+ }
+ $this->setGoodsDiscount($discount_ids);
+ return true;
+
+ }
+
+ /**
+ * 活动结束
+ * @return void
+ */
+ public function discountEndAfter($discount_ids)
+ {
+ if (!is_array($discount_ids)){
+ $discount_ids = [$discount_ids];
+ }
+ $this->cancelGoodsDiscount($discount_ids);
+ return true;
+ }
+
+
+ /**
+ * 领取记录
+ * @param int $id
+ * @return void
+ */
+ public function order(int $discount_id, $where)
+ {
+ $order = 'create_time desc';
+ $search_model = ( new Order() )
+ ->where([ [ 'order.pay_time', '>', 0 ] ])
+ ->withSearch([ 'search_type', 'order_from', 'join_status', 'create_time', 'pay_time' ], $where)
+ ->with([
+ 'member' => function($query) {
+ $query->field('member_id, nickname, mobile, headimg');
+ },
+ 'pay'
+ ])
+ ->withJoin([ 'shopOrderDiscount' => function($query) use ($discount_id) {
+ $query->where([ [ 'discount_type', '=', ActiveDict::DISCOUNT ], [ 'discount_type_id', '=', $discount_id ] ]);
+ } ], 'left')->order($order);
+
+ $order_status_list = OrderDict::getStatus();
+ $list = $this->pageQuery($search_model, function($item, $key) use ($order_status_list) {
+ $item[ 'order_status_data' ] = $order_status_list[ $item[ 'status' ] ] ?? [];
+ $item_pay = $item[ 'pay' ];
+ if (!empty($item_pay)) {
+ $item_pay->append([ 'type_name' ]);
+ }
+ });
+ return $list;
+ }
+
+
+ /**
+ * 会员
+ * @param int $discount_id
+ * @param $where
+ * @return array
+ * @throws \think\db\exception\DbException
+ */
+ public function member(int $discount_id, $where)
+ {
+ $active_goods_ids = ( new DiscountGoods() )->where([ [ 'discount_id', '=', $discount_id ] ])->column('goods_id');
+ $order = 'create_time desc';
+ $search_model = ( new Order() )
+ ->where([ [ 'order.pay_time', '>', 0 ] ])
+ ->withJoin([ 'shopOrderDiscount' => function($query) use ($discount_id) {
+ $query->where([ [ 'discount_type', '=', ActiveDict::DISCOUNT ], [ 'discount_type_id', '=', $discount_id ] ]);
+ } ], 'left')
+ ->with([ 'member' => function($query) {
+ $query->field('username,member_id, nickname, mobile, headimg');
+ }, 'orderGoods' ])
+ ->order($order)
+ ->field('order.member_id,COUNT(order.member_id) as member_count, group_concat(order.create_time) as create_time_data,group_concat(order.order_id) as order_ids')
+ ->group('order.member_id');
+ $list = $this->pageQuery($search_model, function($item, $key) use ($active_goods_ids) {
+ $create_time_data = explode(',', $item[ 'create_time_data' ]);
+ $item[ 'create_time' ] = date('Y-m-d H:i:s', end($create_time_data));
+
+ });
+ if (!empty($list[ 'data' ])) {
+ $member_ids = array_column($list[ 'data' ], 'member_id');
+ $data_list = ( new Order() )
+ ->where([ [ 'order.member_id', 'in', $member_ids ], [ 'order.pay_time', '>', 0 ] ])
+ ->withJoin([ 'shopOrderDiscount' => function($query) use ($discount_id) {
+ $query->where([ [ 'discount_type', '=', ActiveDict::DISCOUNT ], [ 'discount_type_id', '=', $discount_id ] ]);
+ } ], 'left')
+ ->with([ 'orderGoods' ])
+ ->select()->toArray();
+
+ foreach ($list[ 'data' ] as $key => $item) {
+ $item[ 'active_order_money' ] = 0;
+ foreach ($data_list as $k => $v) {
+ if ($item[ 'member_id' ] == $v[ 'member_id' ]) {
+ foreach ($v[ 'orderGoods' ] as $order_goods) {
+ if (in_array($order_goods[ 'goods_id' ], $active_goods_ids)) {
+ $item[ 'active_order_money' ] += $order_goods[ 'order_goods_money' ];
+ }
+ }
+ }
+
+ }
+ $list[ 'data' ][ $key ] = $item;
+ }
+ }
+
+ return $list;
+ }
+
+ /**
+ * 商品
+ * @param int $discount_id
+ * @param $where
+ * @return array
+ * @throws \think\db\exception\DbException
+ */
+ public function goods(int $discount_id, $where)
+ {
+ $active_goods_model = new DiscountGoods();
+ $search_model = $active_goods_model
+ ->alias('discount_goods')
+ ->where([
+ [ 'discount_goods.discount_id', '=', $discount_id ],
+ [ 'goods.goods_name', 'like', '%' . $where[ 'keyword' ] . '%' ],
+ ])
+ ->field('
+ goods.goods_name,
+ goods.goods_cover,
+ discount_goods_id,
+ discount_id,
+ discount_goods.goods_id,
+ discount_goods.sku_id,
+ goods_sku.price,
+ SUM(discount_goods.order_money) as order_money,
+ SUM(discount_goods.order_num) as order_num,
+ SUM(discount_goods.member_num) as member_num,
+ SUM(discount_goods.success_num) as success_num
+ ')
+ ->leftJoin('shop_goods goods', 'discount_goods.goods_id = goods.goods_id')
+ ->leftJoin('shop_goods_sku goods_sku', 'discount_goods.sku_id = goods_sku.sku_id')
+ ->group('discount_goods.goods_id')
+ ->append([ 'goods_cover_thumb_small' ]);
+ return $this->pageQuery($search_model);
+ }
+
+ /**
+ * 配置设置
+ * @param array $params
+ * @return array
+ */
+ public function setConfig($key, $data)
+ {
+ ( new CoreConfigService() )->setConfig($key, $data);
+ return true;
+ }
+
+ /**
+ * 折扣页面轮播图配置
+ */
+ public function getDiscountBannerConfig()
+ {
+ $data = ( new CoreConfigService() )->getConfigValue('SHOP_DISCOUNT_BANNER_CONFIG');
+ if (empty($data)) {
+ $data = [];
+ }
+ return $data;
+ }
+
+ /**
+ * 订单支付后累计
+ * @param $order
+ * @return bool
+ */
+ public function orderPayAfter($order)
+ {
+ $order_discount_model = new OrderDiscounts();
+ $order_discount = $order_discount_model->field('order_id, order_goods_ids, num, money, discount_type, discount_type_id, member_id, goods_id, sku_id')->where([ [ 'order_id', '=', $order[ 'order_id' ] ], [ 'discount_type', '=', ActiveDict::DISCOUNT ] ])->field('order_id,discount_type_id')->select()->toArray();
+ if (empty($order_discount)) return true;
+
+ $discount_model = (new Discount());
+ $discount_goods_model = (new DiscountGoods());
+
+ Db::startTrans();
+ try {
+ foreach ($order_discount as $value){
+ $member_goods_count = $order_discount_model->where([
+ [ 'discount_type', '=', ActiveDict::DISCOUNT ],
+ [ 'discount_type_id', '=', $value[ 'discount_type_id' ] ],
+ [ 'order_id', '<>', $value[ 'order_id' ] ],
+ [ 'member_id', '=', $value[ 'member_id' ] ],
+ ])->count();
+
+ $discount_goods_query = $discount_goods_model->where([
+ [ 'discount_id', '=', $value[ 'discount_type_id' ] ],
+ [ 'goods_id', '=', $value[ 'goods_id' ] ],
+ [ 'sku_id', '=', $value[ 'sku_id' ] ],
+ ])->inc('order_money',$value[ 'money' ])->inc('order_num')->inc('success_num');
+
+ $discount_query = $discount_model->where([
+ [ 'discount_id', '=', $value[ 'discount_type_id' ] ],
+ ])->inc('order_money',$value[ 'money' ])->inc('order_num')->inc('success_num');
+
+ if (empty($member_goods_count)){
+ $discount_goods_query->inc('member_num');
+ $discount_query->inc('member_num');
+ }
+
+ $discount_goods_query->update();
+ $discount_query->update();
+ }
+ Db::commit();
+ return true;
+ } catch (\Exception $e) {
+ Db::rollback();
+ throw new CommonException($e->getMessage());
+ }
+
+ }
+
+ /**
+ * 数字格式转化转换
+ * @param $num
+ * @return string
+ */
+ public function formatNumber($num) {
+ return ($num == intval($num)) ? intval($num) : round($num, 1);
+ }
+
+}
diff --git a/niucloud/addon/shop/app/service/admin/marketing/ManjianService.php b/niucloud/addon/shop/app/service/admin/marketing/ManjianService.php
new file mode 100644
index 000000000..c2ad5ae92
--- /dev/null
+++ b/niucloud/addon/shop/app/service/admin/marketing/ManjianService.php
@@ -0,0 +1,666 @@
+model = new Manjian();
+ }
+
+ /**
+ * 获取满减送列表
+ * @param array $where
+ * @return array
+ */
+ public function getPage(array $where = [])
+ {
+ //活动名称、活动类型、活动详情、活动状态、支付订单数、参与会员数、支付金额 、活动时间
+ $field = 'manjian_id,manjian_name,condition_type,rule_json,status,total_order_num,total_member_num,total_order_money,start_time,end_time';
+ $order = 'create_time desc';
+ $search_model = $this->model
+ ->withSearch(["manjian_name", "status", "create_time", "active_id"], $where)
+ ->append(['status_name'])
+ ->field($field)
+ ->order($order);
+ $list = $this->pageQuery($search_model);
+ return $list;
+ }
+
+ /**
+ * 关闭满减送
+ * @param $manjian_id
+ */
+ public function closeManjian($manjian_id)
+ {
+ $manjian_info = $this->model->where([['manjian_id', '=', $manjian_id]])->field('status,end_time')->findOrEmpty()->toArray();
+ if (!empty($manjian_info)) {
+ if ($manjian_info['end_time'] >= time() && $manjian_info['status'] == ManjianDict::ACTIVE) {
+ $this->model->where([['manjian_id', '=', $manjian_id], ['status', '=', ManjianDict::ACTIVE]])->update(['status' => ManjianDict::CLOSE]);
+ (new ManjianGoods())->where([['manjian_id', '=', $manjian_id]])->update(['status' => ManjianDict::CLOSE]);
+ } else {
+ throw new AdminException('MANJIANSONG_CLOSED');
+ }
+ } else {
+ throw new AdminException('MANJIANSONG_NOT_FOUND');
+ }
+ }
+
+ /**
+ * 删除满减送活动
+ * @param $manjian_id
+ */
+ public function del($manjian_id)
+ {
+ $manjian_info = $this->model->where([ ['manjian_id', '=', $manjian_id]])->field('status,end_time')->findOrEmpty()->toArray();
+ if (!empty($manjian_info)) {
+ if ($manjian_info['status'] == ActiveDict::ACTIVE) throw new AdminException('ACTIVE_NOT_DELETE');
+ $this->model->where([['manjian_id', '=', $manjian_id]])->delete();
+ (new ManjianGoods())->where([['manjian_id', '=', $manjian_id]])->delete();
+ } else {
+ throw new AdminException('MANJIANSONG_NOT_FOUND');
+ }
+ }
+
+ /**
+ * 满减送活动详情
+ * @param $manjian_id
+ */
+ public function info($manjian_id)
+ {
+ //条件类型、活动名称、活动开始时间、活动结束时间、活动状态、活动创建时间、参与订单数、参与会员数、支付金额、活动详情(例:满100.00元减5.00元、包邮、送1积分...)
+ $info = $this->model
+ ->field('manjian_id,manjian_name,goods_type,start_time,end_time,status,create_time,total_order_num,total_member_num,total_order_money,rule_json')
+ ->where([['manjian_id', '=', $manjian_id]])
+ ->append(['status_name', 'goods_type_name'])
+ ->findOrEmpty()
+ ->toArray();
+ return $info;
+ }
+
+ /**
+ * 会员
+ * @param int $manjian_id
+ * @param $where
+ * @return array
+ * @throws \think\db\exception\DbException
+ */
+ public function member(int $manjian_id, $where)
+ {
+ $manjian_records = (new ManjianGiveRecords())->field('member_id,order_id')->withJoin(['order' => function ($query) {
+ $query->field('order.create_time,order_money as total_order_money');
+ }])->where([['manjian_id', '=', $manjian_id]])
+ ->select()->toArray();
+ $member_ids = array_unique(array_column($manjian_records, 'member_id'));
+ $record_info = [];
+ foreach ($manjian_records as $key => $value) {
+ unset($value['order']);
+ $record_info[$value['member_id']][] = $value;
+ }
+
+ $search_model = (new Member())->field('username,member_id, nickname, mobile, headimg')->where([['member_id', 'in', $member_ids]]);
+ $list = $this->pageQuery($search_model);
+ if (!empty($list['data'])) {
+ foreach ($list['data'] as &$value) {
+ $value['total_order_money'] = 0;
+ $value['total_num'] = 0;
+ $value['finally_order_time'] = 0;
+ if (isset($record_info[$value['member_id']])) {
+ $member_records = $record_info[$value['member_id']];
+ $total_order_money = 0;
+ foreach (array_column($member_records, 'total_order_money') as $order_money) {
+ $total_order_money = bcadd($total_order_money, $order_money, 2);
+ }
+ $value['total_order_money'] = $total_order_money;
+ $value['total_num'] = count($member_records);
+ foreach ($member_records as $v) {
+ if ($v['create_time'] > $value['finally_order_time']) {
+ $value['finally_order_time'] = $v['create_time'];
+ }
+ }
+ }
+ }
+ }
+
+ return $list;
+ }
+
+ /**
+ * 添加满减送
+ * @param array $data
+ * @return mixed
+ */
+ public function add(array $data)
+ {
+ $data['start_time'] = strtotime($data['start_time']);
+ $data['end_time'] = strtotime($data['end_time']);
+ if (!empty($data['end_time']) && $data['end_time'] < time()) throw new AdminException('END_TIME_NOT_LESS_CURRENT_TIME');
+
+ $goods_ids = [];
+ if ($data['goods_type'] != ManjianDict::ALL_GOODS) {
+ if (isset($data['goods_data']) && !empty($data['goods_data'])) {
+ $goods_ids = array_unique(array_column($data['goods_data'], 'goods_id'));
+ }
+ }
+ if ($data['goods_type'] != ManjianDict::SELECTED_GOODS){
+ $other_active = $this->model
+ ->where([
+ ['goods_type', '<>', ManjianDict::ALL_GOODS],
+ ['status', 'in', [ManjianDict::ACTIVE]],
+ ])->where(function ($query) use ($data) {
+ $query->whereOr([
+ ['start_time|end_time', 'between', [$data['start_time'], $data['end_time']]],
+ [['start_time', '<=', $data['start_time']], ['end_time', '>=', $data['end_time']]],
+ [['start_time', '>=', $data['start_time']], ['end_time', '<=', $data['end_time']]]
+ ]);
+ })->count();
+ if ($other_active > 0) {
+ throw new AdminException('MANJIAN_TIME_HINT');
+ }
+ }
+
+ //验证商品是否参加活动
+ //有正在进行的全部商品活动
+ $all_goods_count = $this->model
+ ->where([
+ ['goods_type', '=', ManjianDict::ALL_GOODS],
+ ['status', 'in', [ManjianDict::NOT_ACTIVE, ManjianDict::ACTIVE]],
+ ])->where(function ($query) use ($data) {
+ $query->whereOr([
+ ['start_time|end_time', 'between', [$data['start_time'], $data['end_time']]],
+ [['start_time', '<=', $data['start_time']], ['end_time', '>=', $data['end_time']]],
+ [['start_time', '>=', $data['start_time']], ['end_time', '<=', $data['end_time']]]
+ ]);
+ })->count();
+ if ($all_goods_count > 0) throw new AdminException('MANJIANSONG_ALL_GOODS_EXIT');
+
+ $manjian_goods_model = new ManjianGoods();
+ $select_goods_id = $manjian_goods_model
+ ->where([['manjian_goods.manjian_goods_id', '>',0]])
+ ->withJoin([
+ 'manjian' => function (Query $query) use ($data) {
+ $query->where([['manjian.status', 'in', [ManjianDict::NOT_ACTIVE, ManjianDict::ACTIVE]], ['manjian.goods_type', '=', ManjianDict::SELECTED_GOODS]])->where(function ($query) use ($data) {
+ $query->whereOr([['manjian.start_time|manjian.end_time', 'between', [$data['start_time'], $data['end_time']]],
+ [['manjian.start_time', '<=', $data['start_time']], ['manjian.end_time', '>=', $data['end_time']]],
+ [['manjian.start_time', '>=', $data['start_time']], ['manjian.end_time', '<=', $data['end_time']]]]);
+ });
+ },
+ ], 'inner')
+ ->column('goods_id');
+
+ $select_goods_not_id = $manjian_goods_model
+ ->where([['manjian_goods.manjian_goods_id', '>', 0]])
+ ->withJoin([
+ 'manjian' => function (Query $query) use ($data) {
+ $query->where([ ['manjian.status', 'in', [ManjianDict::NOT_ACTIVE, ManjianDict::ACTIVE]], ['manjian.goods_type', '=', ManjianDict::SELECTED_GOODS_NOT]])->where(function ($query) use ($data) {
+ $query->whereOr([
+ ['manjian.start_time|manjian.end_time', 'between', [$data['start_time'], $data['end_time']]],
+ [['manjian.start_time', '<=', $data['start_time']], ['manjian.end_time', '>=', $data['end_time']]],
+ [['manjian.start_time', '>=', $data['start_time']], ['manjian.end_time', '<=', $data['end_time']]]
+ ]);
+ });
+ },
+ ], 'inner')
+ ->column('goods_id');
+
+ $error = [
+ 'code' => 1,
+ 'data' => []
+ ];
+ if ($data['goods_type'] != ManjianDict::ALL_GOODS) {
+ $used_goods_ids = array_merge($select_goods_id, $select_goods_not_id);
+ $goods_id_intersect = array_intersect($goods_ids, $used_goods_ids);
+ if (!empty($goods_id_intersect)) {
+ throw new AdminException('MANJIANSONG_GOODS_NOT_REPEAR');
+ }
+ }
+
+// switch ($data['goods_type']) {
+// case ManjianDict::ALL_GOODS:
+// if (!empty($select_goods_id) || !empty($select_goods_not_id)) {
+// throw new AdminException('MANJIANSONG_GOODS_NOT_REPEAR');
+// }
+// break;
+// case ManjianDict::SELECTED_GOODS_NOT:
+// if (!empty($select_goods_id)) {//参与【123】 【12】 【3】
+// $goods_id_diff = array_diff($select_goods_id, $goods_ids);
+// if (!empty($goods_id_diff)) {
+// throw new AdminException('MANJIANSONG_GOODS_NOT_REPEAR');
+// }
+// }
+// if (!empty($select_goods_not_id)) {//【678】
+// throw new AdminException('MANJIANSONG_GOODS_NOT_REPEAR');
+// }
+// break;
+// case ManjianDict::SELECTED_GOODS:
+// if (!empty($select_goods_id)) {
+// $goods_id_intersect = array_intersect($goods_ids, $select_goods_id);
+// if (!empty($goods_id_intersect)) {
+// throw new AdminException('MANJIANSONG_GOODS_NOT_REPEAR');
+// }
+// }
+// if (!empty($select_goods_not_id)) {
+// $goods_id_diff = array_diff($goods_ids, $select_goods_not_id);
+// if (!empty($goods_id_diff)) {
+// throw new AdminException('MANJIANSONG_GOODS_NOT_REPEAR');
+// }
+// }
+// break;
+// }
+
+ Db::startTrans();
+ try {
+ // 满减送活动数据
+ $manjian_value['manjian_name'] = $data['manjian_name'];
+ $manjian_value['condition_type'] = $data['condition_type'];
+ $manjian_value['goods_type'] = $data['goods_type'];
+ $manjian_value['join_member_type'] = $data['join_member_type'];
+ $manjian_value['rule_type'] = $data['rule_type'] ?? '';
+ $manjian_value['rule_json'] = $data['rule_json'];
+ $manjian_value['goods_ids'] = array_map(function ($item) {
+ return (string)$item;
+ }, $goods_ids);
+ $manjian_value['level_ids'] = array_map(function ($item) {
+ return (string)$item;
+ }, $data['level_ids']);
+ $manjian_value['label_ids'] = array_map(function ($item) {
+ return (string)$item;
+ }, $data['label_ids']);
+ $manjian_value['status'] = ManjianDict::NOT_ACTIVE;
+ $manjian_value['start_time'] = $data['start_time'];
+ $manjian_value['end_time'] = $data['end_time'];
+ $manjian_value['remark'] = $data['remark'];
+
+ if (!empty($data['start_time']) && $data['start_time'] <= time()) {
+ $manjian_value['status'] = ManjianDict::ACTIVE;
+ } elseif (!empty($data['end_time']) && $data['end_time'] <= time()) {
+ $manjian_value['status'] = ManjianDict::END;
+ }
+ $res = $this->model->create($manjian_value);
+
+ $manjian_goods = [];
+ if ($data['goods_type'] != ManjianDict::ALL_GOODS) {
+ if (!empty($data['goods_data'])) {
+ foreach ($data['goods_data'] as $v) {
+ $manjian_goods[] = [
+ 'manjian_id' => $res->manjian_id,
+ 'goods_id' => $v['goods_id'],
+ 'sku_id' => $v['sku_id'],
+ 'goods_type' => $data['goods_type'],
+ 'status' => $manjian_value['status'],
+ ];
+ }
+ }
+ }
+ (new Manjiangoods())->saveAll($manjian_goods);
+
+ Db::commit();
+ $error['data'] = ['id' => $res->manjian_id];
+ return $error;
+ } catch (\Exception $e) {
+ Db::rollback();
+ throw new AdminException($e->getMessage());
+ }
+ }
+
+ /**
+ * 获取满减送编辑数据
+ * @param array $params
+ * @return array
+ */
+ public function getInit($params = [])
+ {
+ $res = $active_goods = [];
+ if (!empty($params['manjian_id'])) {
+ //获取满减基本信息
+ $manjisn_info = $this->model
+ ->field('manjian_id,manjian_name,condition_type,goods_type,join_member_type,rule_type,rule_json,start_time,end_time,remark,level_ids,label_ids,total_order_money,total_member_num,total_order_num,status,create_time,total_point,total_balance,total_coupon_num,total_goods_num')
+ ->where([['manjian_id', '=', $params['manjian_id']]])
+ ->append(['status_name'])
+ ->findOrEmpty()->toArray();
+
+ $coupon_model = (new Coupon());
+ $goods_model = (new Goods());
+ if (!empty($manjisn_info['rule_json'])) {
+ foreach ($manjisn_info['rule_json'] as &$value) {
+ if (isset($value['coupon']) && !empty($value['coupon'])) {
+ $coupon_ids = array_column($value['coupon'], 'coupon_id');
+ $coupon_info = $coupon_model->field('id,title,type,price')->where([['id', 'in', $coupon_ids]])->append(['type_name'])->select()->toArray();
+ $coupon_info = array_column($coupon_info, null, 'id');
+ foreach ($value['coupon'] as &$item) {
+ if (isset($coupon_info[$item['coupon_id']])) {
+ $item['type_name'] = $coupon_info[$item['coupon_id']]['type_name'] ?? '';
+ $item['title'] = $coupon_info[$item['coupon_id']]['title'] ?? '';
+ $item['price'] = $coupon_info[$item['coupon_id']]['price'] ?? 0;
+ }
+ }
+ }
+ if (isset($value['goods']) && !empty($value['goods'])) {
+ foreach ($value['goods'] as &$goods_item) {
+ $sku_id = $goods_item['sku_id'];
+ $goods_info = $goods_model->field('goods_id,goods_cover,goods_name')->where([ ['goods.goods_id', '=', $goods_item['goods_id']]])
+ ->withJoin(['goodsSku' => function ($query) use ($sku_id) {
+ $query->field('sku_id,sku_name,sku_image,goodsSku.stock,goodsSku.price')->where([['sku_id', '=', $sku_id]]);
+ }])->append(['goods_cover_thumb_small'])->findOrEmpty()->toArray();
+ $goods_info['num'] = $goods_item['num'];
+ $goods_item = $goods_info;
+ }
+ }
+ }
+ }
+
+ if (isset($manjisn_info['label_ids']) && !empty($manjisn_info['label_ids'])) {
+ $manjisn_info['label_ids'] = array_map('intval', $manjisn_info['label_ids']);
+ }
+ if (isset($manjisn_info['level_ids']) && !empty($manjisn_info['level_ids'])) {
+ $manjisn_info['level_ids'] = array_map('intval', $manjisn_info['level_ids']);
+ }
+
+ $res['manjian_info'] = $manjisn_info;
+
+ $active_goods_info = [];
+ //获取满减商品信息
+ if (!empty($manjisn_info['goods_type']) && $manjisn_info['goods_type'] != ManjianDict::ALL_GOODS) {
+ $active_goods = (new ManjianGoods())->field('goods_id,sku_id')->where([ ['manjian_id', '=', $params['manjian_id']]])->select()->toArray();
+ foreach ($active_goods as $v) {
+ $goods_sku_id = $v['sku_id'];
+ $goods_info = $goods_model->field('goods_id,goods_cover,goods_name,status')->where([ ['goods.goods_id', '=', $v['goods_id']]])
+ ->withJoin(['goodsSku' => function ($query) use ($goods_sku_id) {
+ $query->field('sku_id,sku_name,sku_image,goodsSku.stock,goodsSku.price')->where([['sku_id', '=', $goods_sku_id]]);
+ }])->append(['goods_cover_thumb_small'])->findOrEmpty()->toArray();
+ if (!empty($goods_info)) {
+ $active_goods_info[] = $goods_info;
+ }
+ }
+ }
+ $res['manjian_goods'] = $active_goods_info;
+ }
+ return $res;
+ }
+
+ /**
+ * 编辑满减送
+ * @param array $data
+ * @return mixed
+ */
+ public function edit(int $manjian_id, array $data)
+ {
+ $data['start_time'] = strtotime($data['start_time']);
+ $data['end_time'] = strtotime($data['end_time']);
+ if (!empty($data['end_time']) && $data['end_time'] < time()) throw new AdminException('END_TIME_NOT_LESS_CURRENT_TIME');
+
+ $goods_ids = [];
+ if ($data['goods_type'] != ManjianDict::ALL_GOODS) {
+ if (isset($data['goods_data']) && !empty($data['goods_data'])) {
+ $goods_ids = array_unique(array_column($data['goods_data'], 'goods_id'));
+ }
+ }
+
+ //有正在进行的全部商品活动
+ $all_goods_count = $this->model
+ ->where([
+ ['manjian_id', '<>', $manjian_id],
+ ['goods_type', '=', ManjianDict::ALL_GOODS],
+ ['status', 'in', [ManjianDict::NOT_ACTIVE, ManjianDict::ACTIVE]],
+ ])->where(function ($query) use ($data) {
+ $query->whereOr([
+ ['start_time|end_time', 'between', [$data['start_time'], $data['end_time']]],
+ [['start_time', '<=', $data['start_time']], ['end_time', '>=', $data['end_time']]],
+ [['start_time', '>=', $data['start_time']], ['end_time', '<=', $data['end_time']]]
+ ]);
+ })->count();
+ if ($all_goods_count > 0) throw new AdminException('MANJIANSONG_ALL_GOODS_EXIT');
+
+ $manjian_goods_model = new ManjianGoods();
+ $select_goods_id = $manjian_goods_model
+ ->where([['manjian_goods.manjian_goods_id', '>', 0]])
+ ->withJoin([
+ 'manjian' => function (Query $query) use ($data, $manjian_id) {
+ $query->where([['manjian.manjian_id', '<>', $manjian_id], ['manjian.status', 'in', [ManjianDict::NOT_ACTIVE, ManjianDict::ACTIVE]], ['manjian.goods_type', '=', ManjianDict::SELECTED_GOODS]])->where(function ($query) use ($data) {
+ $query->whereOr([['manjian.start_time|manjian.end_time', 'between', [$data['start_time'], $data['end_time']]],
+ [['manjian.start_time', '<=', $data['start_time']], ['manjian.end_time', '>=', $data['end_time']]],
+ [['manjian.start_time', '>=', $data['start_time']], ['manjian.end_time', '<=', $data['end_time']]]]);
+ });
+ },
+ ], 'inner')
+ ->column('goods_id');
+
+ $select_goods_not_id = $manjian_goods_model
+ ->where([['manjian_goods.manjian_goods_id', '>', 0]])
+ ->withJoin([
+ 'manjian' => function (Query $query) use ($data, $manjian_id) {
+ $query->where([['manjian.manjian_id', '<>', $manjian_id], ['manjian.status', 'in', [ManjianDict::NOT_ACTIVE, ManjianDict::ACTIVE]], ['manjian.goods_type', '=', ManjianDict::SELECTED_GOODS_NOT]])->where(function ($query) use ($data) {
+ $query->whereOr([['manjian.start_time|manjian.end_time', 'between', [$data['start_time'], $data['end_time']]],
+ [['manjian.start_time', '<=', $data['start_time']], ['manjian.end_time', '>=', $data['end_time']]],
+ [['manjian.start_time', '>=', $data['start_time']], ['manjian.end_time', '<=', $data['end_time']]]]);
+ });
+ },
+ ], 'inner')
+ ->column('goods_id');
+
+ $error = [
+ 'code' => 1,
+ 'data' => []
+ ];
+ if ($data['goods_type'] != ManjianDict::ALL_GOODS) {
+ $used_goods_ids = array_merge($select_goods_id, $select_goods_not_id);
+ $goods_id_intersect = array_intersect($goods_ids, $used_goods_ids);
+ if (!empty($goods_id_intersect)) {
+ throw new AdminException('MANJIANSONG_GOODS_NOT_REPEAR');
+ }
+ }
+// switch ($data['goods_type']) {
+// case ManjianDict::ALL_GOODS:
+// if (!empty($select_goods_id) || !empty($select_goods_not_id)) {
+// throw new AdminException('MANJIANSONG_GOODS_NOT_REPEAR');
+// }
+// break;
+// case ManjianDict::SELECTED_GOODS_NOT:
+// if (!empty($select_goods_id)) {
+// $goods_id_diff = array_diff($select_goods_id, $goods_ids);
+// if (!empty($goods_id_diff)) {
+// throw new AdminException('MANJIANSONG_GOODS_NOT_REPEAR');
+// }
+// }
+// if (!empty($select_goods_not_id)) {
+// throw new AdminException('MANJIANSONG_GOODS_NOT_REPEAR');
+// }
+// break;
+// case ManjianDict::SELECTED_GOODS:
+// if (!empty($select_goods_id)) {
+// $goods_id_intersect = array_intersect($goods_ids, $select_goods_id);
+// if (!empty($goods_id_intersect)) {
+// throw new AdminException('MANJIANSONG_GOODS_NOT_REPEAR');
+// }
+// }
+// if (!empty($select_goods_not_id)) {
+// $goods_id_diff = array_diff($goods_ids, $select_goods_not_id);
+// if (!empty($goods_id_diff)) {
+// throw new AdminException('MANJIANSONG_GOODS_NOT_REPEAR');
+// }
+// }
+// break;
+// }
+
+ Db::startTrans();
+ try {
+ // 满减送活动数据
+ $manjian_value['manjian_name'] = $data['manjian_name'];
+ $manjian_value['condition_type'] = $data['condition_type'];
+ $manjian_value['goods_type'] = $data['goods_type'];
+ $manjian_value['join_member_type'] = $data['join_member_type'];
+ $manjian_value['rule_type'] = $data['rule_type'] ?? '';
+ $manjian_value['rule_json'] = $data['rule_json'];
+ $manjian_value['goods_ids'] = array_map(function ($item) {
+ return (string)$item;
+ }, $goods_ids);
+ $manjian_value['level_ids'] = array_map(function ($item) {
+ return (string)$item;
+ }, $data['level_ids']);
+ $manjian_value['label_ids'] = array_map(function ($item) {
+ return (string)$item;
+ }, $data['label_ids']);
+ $manjian_value['status'] = ManjianDict::NOT_ACTIVE;
+ $manjian_value['start_time'] = $data['start_time'];
+ $manjian_value['end_time'] = $data['end_time'];
+ $manjian_value['remark'] = $data['remark'];
+
+ if (!empty($data['start_time']) && $data['start_time'] <= time()) {
+ $manjian_value['status'] = ManjianDict::ACTIVE;
+ } elseif (!empty($data['end_time']) && $data['end_time'] <= time()) {
+ $manjian_value['status'] = ManjianDict::END;
+ }
+ $this->model->where([['manjian_id', '=', $manjian_id]])->update($manjian_value);
+
+ $manjian_goods = [];
+ if ($data['goods_type'] != ManjianDict::ALL_GOODS) {
+ if (!empty($data['goods_data'])) {
+ foreach ($data['goods_data'] as $v) {
+ $manjian_goods[] = [
+ 'manjian_id' => $manjian_id,
+ 'goods_id' => $v['goods_id'],
+ 'sku_id' => $v['sku_id'],
+ 'goods_type' => $data['goods_type'],
+ 'status' => $manjian_value['status'],
+ ];
+ }
+ }
+ }
+ (new Manjiangoods())->where([['manjian_id', '=', $manjian_id]])->delete();
+ (new Manjiangoods())->saveAll($manjian_goods);
+ Db::commit();
+ $error['data'] = ['id' => $manjian_id];
+ return $error;
+ } catch (\Exception $e) {
+ Db::rollback();
+ throw new AdminException($e->getMessage());
+ }
+ }
+
+ /**
+ * 满减送商品校验
+ * @param $data
+ * @return array
+ */
+ public function checkGoods($data)
+ {
+ $error = [
+ 'code' => 1,
+ 'data' => []
+ ];
+ $goods_ids = $data['goods_ids'];
+ $manjian_goods_model = new ManjianGoods();
+ $select_goods_id = $manjian_goods_model
+ ->where([['manjian_goods.manjian_goods_id', '>', 0 ]])
+ ->withJoin([
+ 'manjian' => function (Query $query) use ($data) {
+ $query->where([['manjian.status', 'in', [ManjianDict::NOT_ACTIVE, ManjianDict::ACTIVE]], ['manjian.goods_type', '=', ManjianDict::SELECTED_GOODS]])->where(function ($query) use ($data) {
+ $query->whereOr([['manjian.start_time|manjian.end_time', 'between', [strtotime($data['start_time']), strtotime($data['end_time'])]],
+ [['manjian.start_time', '<=', strtotime($data['start_time'])], ['manjian.end_time', '>=', strtotime($data['end_time'])]],
+ [['manjian.start_time', '>=', strtotime($data['start_time'])], ['manjian.end_time', '<=', strtotime($data['end_time'])]]]);
+ });
+ },
+ ], 'inner')
+ ->column('goods_id');
+
+ if (!empty($select_goods_id) && $data['goods_type'] != ManjianDict::ALL_GOODS) {
+ if (!empty($data['manjian_id'])) {
+ $select_goods_ids = $manjian_goods_model->where([
+ ['manjian_id', '=', $data['manjian_id']]
+ ])->column('goods_id');
+ $goods_ids = array_diff($goods_ids, $select_goods_ids);
+ }
+ $goods_id_intersect = array_intersect($goods_ids, $select_goods_id);
+ if (!empty($goods_id_intersect)) {
+ foreach ($goods_id_intersect as $goods_id) {
+ $manjian_info = $manjian_goods_model->where([
+ ['goods_id', '=', $goods_id],
+ ['status', 'in', [ManjianDict::NOT_ACTIVE, ManjianDict::ACTIVE]],
+// [ 'goods_type', '=', $data[ 'goods_type' ] ]
+ ])->with(['manjian' => function ($query) use ($data) {
+ $query->field('manjian_id,manjian_name');
+ }])->findOrEmpty()->toArray();
+ if (!empty($manjian_info)) {
+ $error['code'] = -1;
+ $error['data'][] = [
+ 'goods_id' => $goods_id,
+ 'error_msg' => '该商品已参加【' . $manjian_info['manjian']['manjian_name'] . '】活动'
+ ];
+ }
+ }
+ }
+ }
+ return $error;
+ }
+
+ /**
+ * 批量关闭
+ * @param $data
+ * @return bool
+ */
+ public function batchClose($data)
+ {
+ if (empty($data['manjian_id'])) throw new AdminException('MANJIANSONG_NOT_FOUND');
+
+ $save_data = [];
+ foreach ($data['manjian_id'] as $key => $value) {
+ $save_data[$key]['manjian_id'] = $value;
+ $save_data[$key]['status'] = ManjianDict::CLOSE;
+ }
+ $this->model->saveAll($save_data);
+ return true;
+ }
+
+ /**
+ * 批量删除
+ * @param $data
+ * @return bool
+ */
+ public function batchDelete($data)
+ {
+ if (empty($data['manjian_id'])) throw new AdminException('MANJIANSONG_NOT_FOUND');
+ $this->model->where([['manjian_id', 'in', $data['manjian_id']]])->delete();
+ return true;
+ }
+
+ /**
+ * 获取满减信息
+ * @return array
+ */
+ public function getManjianInfo($data)
+ {
+ return (new CoreManjianService())->getManjianInfo($data);
+ }
+
+}
diff --git a/niucloud/addon/shop/app/service/admin/marketing/MarketingService.php b/niucloud/addon/shop/app/service/admin/marketing/MarketingService.php
new file mode 100644
index 000000000..0ac29dbe1
--- /dev/null
+++ b/niucloud/addon/shop/app/service/admin/marketing/MarketingService.php
@@ -0,0 +1,76 @@
+arrayUniqueness($category, 'key');
+ foreach ($category as &$value) {
+ $value[ 'child' ] = [];
+ foreach ($app as $v) {
+ if ($value[ 'key' ] == $v[ 'category' ]) {
+ $value[ 'child' ][] = $v;
+ }
+ }
+ }
+ return $category;
+ }
+
+ //去重
+ function arrayUniqueness($arr, $key)
+ {
+ $res = array();
+ foreach ($arr as $value) {
+ //查看有没有重复项
+ if (isset($res[ $value[ $key ] ])) {
+ //有:销毁
+ unset($value[ $key ]);
+ } else {
+ $res[ $value[ $key ] ] = $value;
+ }
+ }
+ return $res;
+ }
+
+}
diff --git a/niucloud/addon/shop/app/service/admin/marketing/NewcomerService.php b/niucloud/addon/shop/app/service/admin/marketing/NewcomerService.php
new file mode 100644
index 000000000..680222d93
--- /dev/null
+++ b/niucloud/addon/shop/app/service/admin/marketing/NewcomerService.php
@@ -0,0 +1,386 @@
+model = new Active();
+ }
+
+ /**
+ * 新人专享设置
+ * @param array $data
+ * @return bool
+ */
+ public function setConfig(array $data)
+ {
+ $goods_data = json_decode($data[ 'goods_data' ], true);
+ if ($data[ 'active_status' ] == ActiveDict::ACTIVE) {
+ $this->checkGoods($goods_data);
+ }
+ try {
+ $active_value[ 'validity_type' ] = $data[ 'validity_type' ];
+ $active_value[ 'validity_day' ] = $data[ 'validity_day' ];
+ $active_value[ 'validity_time' ] = !empty($data[ 'validity_time' ]) ? strtotime($data[ 'validity_time' ]) : 0;
+ $active_value[ 'participation_way' ] = $data[ 'participation_way' ];
+ $active_value[ 'appoint_time' ] = !empty($data[ 'appoint_time' ]) ? strtotime($data[ 'appoint_time' ]) : 0;
+ $active_value[ 'limit_num' ] = $data[ 'limit_num' ];
+ $active_value[ 'banner_list' ] = $data[ 'banner_list' ];
+
+ $active_goods = [];
+ foreach ($goods_data as $k => $v) {
+ $active_goods[] = [
+ 'goods_id' => $v[ 'goods_id' ],
+ 'sku_id' => $v[ 'sku_id' ],
+ 'active_goods_type' => ActiveDict::GOODS_SINGLE,
+ 'active_class' => ActiveDict::NEWCOMER_DISCOUNT,
+ 'active_goods_value' => json_encode($v),
+ 'active_goods_status' => $data[ 'active_status' ],
+ 'active_goods_price' => $v[ 'newcomer_price' ],
+ ];
+ }
+ $data[ 'active_goods_info' ] = $data[ 'goods_data' ];
+ $data[ 'active_goods' ] = $active_goods;
+ $data[ 'active_type' ] = ActiveDict::GOODS;
+ $data[ 'active_goods_type' ] = ActiveDict::GOODS_SINGLE;
+ $data[ 'active_class' ] = ActiveDict::NEWCOMER_DISCOUNT;
+ $data[ 'active_value' ] = $active_value;
+
+ $info = $this->model->where([[ 'active_class', '=', ActiveDict::NEWCOMER_DISCOUNT ] ])->findOrEmpty();
+ if ($info->isEmpty()) {
+ ( new CoreActiveService() )->add($data);
+ } else {
+ ( new CoreActiveService() )->edit($info[ 'active_id' ], $data);
+ }
+ return true;
+ } catch (\Exception $e) {
+ throw new CommonException($e->getMessage());
+ }
+ }
+
+ /**
+ * 获取新人专享配置
+ * @return array
+ */
+ public function getConfig()
+ {
+ $value = ( new CoreNewcomerService() )->getConfig();
+ if (!empty($value[ 'active_id' ])) {
+ $active_goods = ( new ActiveGoods() )->field('goods_id,sku_id,active_goods_value')->where([ [ 'active_id', '=', $value[ 'active_id' ] ], [ 'active_class', '=', ActiveDict::NEWCOMER_DISCOUNT ] ])
+ ->with([
+ 'goods' => function ($query) {
+ $query->field('goods_id,goods_name,goods_type,goods_cover')->append([ 'goods_type_name', 'goods_cover_thumb_mid' ]);
+ },
+ 'goodsSkuOne' => function ($query) {
+ $query->field('sku_id,sku_name,sku_image,goods_id,price,stock');
+ }
+ ])
+ ->select()->toArray();
+ foreach ($active_goods as $k => &$item) {
+ if (!empty($item[ 'goods' ])) {
+ $item[ 'goods_name' ] = $item[ 'goods' ][ 'goods_name' ];
+ $item[ 'goods_type' ] = $item[ 'goods' ][ 'goods_type' ];
+ $item[ 'goods_type_name' ] = $item[ 'goods' ][ 'goods_type_name' ];
+ $item[ 'sku_name' ] = $item[ 'goodsSkuOne' ][ 'sku_name' ];
+ $item[ 'sku_image' ] = $item[ 'goodsSkuOne' ][ 'sku_image' ];
+ if (empty($item[ 'sku_image' ])) {
+ $item[ 'sku_image' ] = $item[ 'goods' ][ 'goods_cover_thumb_mid' ];
+ }
+ $item[ 'price' ] = $item[ 'goodsSkuOne' ][ 'price' ];
+ $item[ 'stock' ] = $item[ 'goodsSkuOne' ][ 'stock' ];
+ $item[ 'active_goods_value' ] = json_decode($item[ 'active_goods_value' ], true);
+ } else {
+ unset($active_goods[ $k ]);
+ }
+ }
+ $active_goods = array_values($active_goods);
+ $value[ 'active_goods' ] = $active_goods;
+ }
+ return $value;
+ }
+
+ /**
+ * 商品结构校验
+ * @param $goods_data
+ * @return void
+ */
+ public function checkGoods($goods_data)
+ {
+ if (empty($goods_data)) throw new AdminException('ACTIVE_GOODS_NOT_EMPTY');
+ foreach ($goods_data as $v) {
+ if (empty($v)) throw new AdminException('ACTIVE_GOODS_SKU_NOT_EMPTY');
+ if (!isset($v[ 'newcomer_price' ]) || $v[ 'newcomer_price' ] == '') throw new AdminException('ACTIVE_GOODS_NEWCOMER_PRICE_NOT_EMPTY');
+ }
+ }
+
+ /**
+ * 获取商品选择分页列表
+ * @param array $where
+ * @return array
+ */
+ public function getSelectPage(array $where = [])
+ {
+ $goods_model = new Goods();
+ $goods_sku_model = new GoodsSku();
+ $active_goods_model = new ActiveGoods();
+ $active_goods = $active_goods_model->field('goods_id,sku_id,active_goods_value')->where([
+ [ 'active_class', '=', ActiveDict::NEWCOMER_DISCOUNT ],
+// [ 'active_goods_status', '=', ActiveDict::ACTIVE ]
+ ])->select()->toArray();
+ $active_goods_ids = array_unique(array_column($active_goods, 'goods_id'));
+ $active_sku_ids = array_column($active_goods, 'sku_id');
+ $active_goods = array_column($active_goods, null, 'sku_id');
+
+ $field = 'goods_id, goods_name, goods_type, goods_cover,goods_image, stock,sub_title,goods_desc';
+ $order = 'sort desc,create_time desc';
+
+ $sku_where = [
+ [ 'goodsSku.is_default', '=', 1 ],
+ [ 'goods.is_gift', '=', GoodsDict::NOT_IS_GIFT ]
+ ];
+
+ if (!empty($where[ 'keyword' ])) {
+ $sku_where[] = [ 'goods_name|sub_title', 'like', '%' . $where[ 'keyword' ] . '%' ];
+ }
+
+ if ($where[ 'select_type' ] == 'all') {
+ $sku_where[] = [ 'goods.stock', '>', 0 ];
+ $sku_where[] = [ 'status', '=', 1 ];
+ $sku_where[] = [ 'goods.goods_id', 'in', $active_goods_ids ];
+ }
+ if ($where[ 'select_type' ] == 'selected') {
+ $goods_ids = $goods_sku_model->where([
+ [ 'sku_id', 'in', $where[ 'sku_ids' ] ]
+ ])->column('goods_id');
+ $sku_where[] = [ 'goods.goods_id', 'in', $goods_ids ];
+ }
+
+ $verify_goods_ids = [];
+ $verify_sku_ids = [];
+ // 检测商品id集合是否存在,移除不存在的商品id,纠正数据准确性
+ if (!empty($where[ 'verify_goods_ids' ]) && !empty($active_goods_ids)) {
+ $verify_goods_ids = $goods_model->where([
+ [ 'goods_id', 'in', $where[ 'verify_goods_ids' ] ],
+ [ 'status', '=', 1 ]
+ ])->field('goods_id')->select()->toArray();
+
+ if (!empty($verify_goods_ids)) {
+ // 移除不在新人活动列表中的商品
+ foreach ($verify_goods_ids as $k => $v) {
+ if (!in_array($v[ 'goods_id' ], $active_goods_ids)) unset($verify_goods_ids[ $k ]);
+ }
+ $verify_goods_ids = array_values($verify_goods_ids);
+ $verify_goods_ids = array_column($verify_goods_ids, 'goods_id');
+ }
+ }
+
+ // 检测商品id集合是否存在,移除不存在的商品id,纠正数据准确性
+ if (!empty($where[ 'verify_sku_ids' ]) && !empty($active_sku_ids)) {
+ $verify_sku_ids = $goods_sku_model->where([
+ [ 'sku_id', 'in', $where[ 'verify_sku_ids' ] ]
+ ])->field('sku_id')->select()->toArray();
+
+ if (!empty($verify_sku_ids)) {
+ // 移除不在新人活动列表中的商品
+ foreach ($verify_sku_ids as $k => $v) {
+ if (!in_array($v[ 'sku_id' ], $active_sku_ids)) unset($verify_sku_ids[ $k ]);
+ }
+ $verify_sku_ids = array_values($verify_sku_ids);
+ $verify_sku_ids = array_column($verify_sku_ids, 'sku_id');
+ }
+ }
+
+ $search_model = $goods_model
+ ->withSearch([ "goods_category", "goods_type" ], $where)
+ ->field($field)
+ ->withJoin([
+ 'goodsSku' => [ 'sku_id', 'sku_name', 'goods_id', 'price', 'stock', 'sku_spec_format' ],
+ ])
+ ->with([
+ 'skuList' => function (Query $query) use ($active_sku_ids) {
+ $query->where([ [ 'sku_id', 'in', $active_sku_ids ] ]);
+ }
+ ])
+ ->where($sku_where)->order($order)->append([ 'goods_type_name', 'goods_cover_thumb_small', 'goods_cover_thumb_mid' ]);
+ $list = $this->pageQuery($search_model);
+
+ foreach ($list[ 'data' ] as &$item) {
+ if (!empty($item[ 'skuList' ]) && !empty($active_goods)) {
+ foreach ($item[ 'skuList' ] as &$sku_item) {
+ $active_goods_value = json_decode($active_goods[ $sku_item[ 'sku_id' ] ][ 'active_goods_value' ], true);
+ $sku_item[ 'newcomer_price' ] = $active_goods_value[ 'newcomer_price' ] ?? 0;
+ }
+ if (!empty($item[ 'goodsSku' ])) {
+ if (in_array($item[ 'goodsSku' ][ 'sku_id' ], $active_sku_ids)) {
+ $active_goods_value = json_decode($active_goods[ $item[ 'goodsSku' ][ 'sku_id' ] ][ 'active_goods_value' ], true);
+ $item[ 'goodsSku' ][ 'newcomer_price' ] = $active_goods_value[ 'newcomer_price' ] ?? 0;
+ } else {
+ $item[ 'goodsSku' ][ 'newcomer_price' ] = $item[ 'skuList' ][ 0 ][ 'newcomer_price' ];
+ }
+ }
+ }
+ }
+
+ $list[ 'verify_goods_ids' ] = $verify_goods_ids;
+ $list[ 'verify_sku_ids' ] = $verify_sku_ids;
+
+ return $list;
+ }
+
+ /**
+ * 获取已选商品列表
+ * @param array $where
+ * @return array
+ */
+ public function getSelectSku(array $where = [])
+ {
+ $goods_model = new Goods();
+ $active_goods_model = new ActiveGoods();
+ $active_goods = $active_goods_model->field('goods_id,sku_id,active_goods_value')->where([
+ [ 'active_class', '=', ActiveDict::NEWCOMER_DISCOUNT ],
+// [ 'active_goods_status', '=', ActiveDict::ACTIVE ]
+ ])->select()->toArray();
+ $active_goods_ids = array_unique(array_column($active_goods, 'goods_id'));
+ $active_sku_ids = array_column($active_goods, 'sku_id');
+ $active_goods = array_column($active_goods, null, 'sku_id');
+ $field = 'goods_id, goods_name, goods_type, goods_cover, stock';
+ $order = 'sort desc,create_time desc';
+
+ $select_goods_list = [];// 已选商品列表
+
+ // 检测商品id集合是否存在,移除不存在的商品id,纠正数据准确性
+ if (!empty($where[ 'verify_goods_ids' ]) && !empty($active_goods_ids)) {
+ $verify_goods_ids = $goods_model->where([
+ [ 'goods_id', 'in', $where[ 'verify_goods_ids' ] ],
+ [ 'status', '=', 1 ]
+ ])->field('goods_id')->select()->toArray();
+
+ if (!empty($verify_goods_ids)) {
+ // 移除不在新人活动列表中的商品
+ foreach ($verify_goods_ids as $k => $v) {
+ if (!in_array($v[ 'goods_id' ], $active_goods_ids)) unset($verify_goods_ids[ $k ]);
+ }
+ $verify_goods_ids = array_values($verify_goods_ids);
+ $verify_goods_ids = array_column($verify_goods_ids, 'goods_id');
+ }
+
+ $select_goods_list = $goods_model
+ ->field($field)
+ ->with([
+ 'skuList' => function (Query $query) use ($active_sku_ids) {
+ $query->where([ [ 'sku_id', 'in', $active_sku_ids ] ]);
+ }
+ ])
+ ->where([
+ [ 'goods_id', 'in', $verify_goods_ids ]
+ ])
+ ->order($order)->append([ 'goods_type_name', 'goods_cover_thumb_small', 'goods_cover_thumb_mid' ])
+ ->select()->toArray();
+
+ foreach ($select_goods_list as &$item) {
+ if (!empty($item[ 'skuList' ]) && !empty($active_goods)) {
+ foreach ($item[ 'skuList' ] as &$sku_item) {
+ $active_goods_value = json_decode($active_goods[ $sku_item[ 'sku_id' ] ][ 'active_goods_value' ], true);
+ $sku_item[ 'newcomer_price' ] = $active_goods_value[ 'newcomer_price' ] ?? 0;
+ }
+ if (!empty($item[ 'goodsSku' ])) {
+ if (in_array($item[ 'goodsSku' ][ 'sku_id' ], $active_sku_ids)) {
+ $active_goods_value = json_decode($active_goods[ $item[ 'goodsSku' ][ 'sku_id' ] ][ 'active_goods_value' ], true);
+ $item[ 'goodsSku' ][ 'newcomer_price' ] = $active_goods_value[ 'newcomer_price' ] ?? 0;
+ } else {
+ $item[ 'goodsSku' ][ 'newcomer_price' ] = $item[ 'skuList' ][ 0 ][ 'newcomer_price' ];
+ }
+ }
+ }
+ }
+ }
+
+ // 检测商品id集合是否存在,移除不存在的商品id,纠正数据准确性
+ if (!empty($where[ 'verify_sku_ids' ]) && !empty($active_sku_ids)) {
+ $goods_sku_model = new GoodsSku();
+ $verify_sku_ids = $goods_sku_model->where([
+ [ 'sku_id', 'in', $where[ 'verify_sku_ids' ] ]
+ ])->field('sku_id')->select()->toArray();
+
+ if (!empty($verify_sku_ids)) {
+ // 移除不在新人活动列表中的商品
+ foreach ($verify_sku_ids as $k => $v) {
+ if (!in_array($v[ 'sku_id' ], $active_sku_ids)) unset($verify_sku_ids[ $k ]);
+ }
+ $verify_sku_ids = array_values($verify_sku_ids);
+ $verify_sku_ids = array_column($verify_sku_ids, 'sku_id');
+ }
+
+ $goods_ids = $goods_sku_model->where([
+ [ 'sku_id', 'in', $verify_sku_ids ]
+ ])->field('goods_id')->select()->toArray();
+ if (!empty($goods_ids)) {
+ $goods_ids = array_column($goods_ids, 'goods_id');
+ $goods_ids = array_unique($goods_ids);
+ }
+
+ $select_goods_list = $goods_model
+ ->field($field)
+ ->with([
+ 'skuList' => function (Query $query) use ($verify_sku_ids) {
+ $query->where([ [ 'sku_id', 'in', $verify_sku_ids ] ]);
+ }
+ ])
+ ->where([
+ [ 'goods_id', 'in', $goods_ids ]
+ ])
+ ->order($order)->append([ 'goods_type_name', 'goods_cover_thumb_small', 'goods_cover_thumb_mid' ])
+ ->select()->toArray();
+
+ foreach ($select_goods_list as &$item) {
+ if (!empty($item[ 'skuList' ]) && !empty($active_goods)) {
+ foreach ($item[ 'skuList' ] as &$sku_item) {
+ $active_goods_value = json_decode($active_goods[ $sku_item[ 'sku_id' ] ][ 'active_goods_value' ], true);
+ $sku_item[ 'newcomer_price' ] = $active_goods_value[ 'newcomer_price' ] ?? 0;
+ }
+ if (!empty($item[ 'goodsSku' ])) {
+ if (in_array($item[ 'goodsSku' ][ 'sku_id' ], $verify_sku_ids)) {
+ $active_goods_value = json_decode($active_goods[ $item[ 'goodsSku' ][ 'sku_id' ] ][ 'active_goods_value' ], true);
+ $item[ 'goodsSku' ][ 'newcomer_price' ] = $active_goods_value[ 'newcomer_price' ] ?? 0;
+ } else {
+ $item[ 'goodsSku' ][ 'newcomer_price' ] = $item[ 'skuList' ][ 0 ][ 'newcomer_price' ];
+ }
+ }
+ }
+ }
+ }
+
+ return $select_goods_list;
+ }
+
+}
diff --git a/niucloud/addon/shop/app/service/admin/marketing/pointexchange/ExchangeService.php b/niucloud/addon/shop/app/service/admin/marketing/pointexchange/ExchangeService.php
new file mode 100644
index 000000000..3b443112a
--- /dev/null
+++ b/niucloud/addon/shop/app/service/admin/marketing/pointexchange/ExchangeService.php
@@ -0,0 +1,418 @@
+model = new Exchange();
+ }
+
+ /**
+ * 获取积分商城列表
+ * @param array $where
+ * @return array
+ */
+ public function getPage(array $where = [])
+ {
+ $field = 'total_exchange_num,stock,id,type,names,title,image,status,product_detail,point,price,limit_num,content,sort,total_point_num,total_price_num,total_order_num,total_member_num,update_time,create_time';
+ $order = 'id desc';
+ $search_model = $this->model->where([ [ 'id', '>', 0 ] ])->withSearch([ 'names', 'status', 'create_time' ], $where)->append([ 'type_name', 'status_name', 'goods_cover_thumb_small' ])->field($field)->order($order);
+ $list = $this->pageQuery($search_model);
+ return $list;
+ }
+
+ /**
+ * 获取积分商城分页列表(用于弹框选择)
+ * @param array $where
+ * @return array
+ */
+ public function getSelectPage(array $where = [])
+ {
+ $verify_ids=[];
+ // 检测id集合是否存在,移除不存在的id,纠正数据准确性
+ if (!empty($where[ 'verify_ids' ])) {
+ $verify_ids = $this->model->where([
+ [ 'id', 'in', $where[ 'verify_ids' ] ]
+ ])->field('id')->select()->toArray();
+
+ if (!empty($verify_ids)) {
+ $verify_ids = array_column($verify_ids, 'id');
+ }
+ }
+
+ $field = 'total_exchange_num,stock,id,type,names,title,image,status,product_detail,point,price,limit_num,content,sort,total_point_num,total_price_num,total_order_num,total_member_num,update_time,create_time';
+ $order = 'id desc';
+ $search_model = $this->model->where([ [ 'status', '=', ExchangeDict::UP ] ])->withSearch([ 'names', 'status', 'create_time' ], $where)->append([ 'type_name', 'status_name', 'goods_cover_thumb_small' ])->field($field)->order($order);
+ $list = $this->pageQuery($search_model);
+ $list[ 'verify_ids' ] = $verify_ids;
+ return $list;
+ }
+
+ /**
+ * 获取积分商城详情
+ * @param int $id
+ * @return array
+ */
+ public function getDetail(int $id)
+ {
+ $field = 'stock,total_exchange_num,id,type,names,title,image,status,product_detail,point,price,limit_num,content,sort,total_point_num,total_price_num,total_order_num,total_member_num,update_time,create_time';
+ $info = $this->model->where([ [ 'id', '=', $id ] ])->append([ 'type_name' ])->field($field)->findOrEmpty()->toArray();
+ switch ($info[ 'type' ]) {
+ case ExchangeDict::GOODS:
+ $goods_id = 0;
+ foreach ($info[ 'product_detail' ] as $k => $v) {
+ if (!empty($v[ 'goods_id' ])) {
+ $goods_id = $v[ 'goods_id' ];
+ }
+ }
+ $info[ 'goods_list' ] = ( new GoodsSku() )->where([ [ 'goods_id', '=', $goods_id ] ])->field('sku_spec_format,sku_id,sku_name,sku_image,sku_no,price as goods_price,stock as goods_stock')->select()->toArray();
+ $info[ 'goods_info' ] = ( new Goods() )->where([ [ 'goods_id', '=', $goods_id ] ])->field('goods_id,goods_name,goods_image,goods_cover')->findOrEmpty()->toArray();
+ $info[ 'goods_info' ][ 'spec_type' ] = empty($info[ 'goods_list' ][ 0 ][ 'sku_spec_format' ]) ? 'single' : 'multi';
+ $info[ 'goods_info' ][ 'goods_price' ] = $info[ 'goods_list' ][ 0 ][ 'goods_price' ];
+ foreach ($info[ 'goods_list' ] as &$item) {
+ $product_detail_key = array_search($item[ 'sku_id' ], array_column($info[ 'product_detail' ], 'sku_id'));
+ if ($product_detail_key !== false) {
+ $item[ 'is_enabled' ] = 1;
+ $item = array_merge($item, $info[ 'product_detail' ][ $product_detail_key ]);
+ } else {
+ $item[ 'is_enabled' ] = 0;
+ }
+ }
+ break;
+ }
+ return $info;
+ }
+
+ /**
+ * 获取积分商城详情
+ * @param $where
+ * @return mixed
+ */
+ public function getInfo($where)
+ {
+ $field = 'stock,total_exchange_num,id,type,names,title,image,status,product_detail,point,price,limit_num,content,sort,total_point_num,total_price_num,total_order_num,total_member_num,update_time,create_time';
+ $info = $this->model->withSearch([ 'ids', 'names', 'status', 'create_time', 'product_detail', 'sku_id', 'goods_id' ], $where)->append([ 'type_name' ])->field($field)->findOrEmpty()->toArray();
+ return $info;
+ }
+
+ /**
+ * 添加积分商城
+ * @param array $data
+ * @return mixed
+ */
+ public function add(array $data)
+ {
+ $product_detail = json_decode($data[ 'product_detail' ], true);
+ $this->verifyData($data);
+ $check_condition = [
+ [ 'active_goods.active_class', '=', ActiveDict::EXCHANGE ],
+ [ 'active_goods.goods_id', 'in', $product_detail[ 0 ][ 'goods_id' ] ],
+ ];
+ $goods_where = [];
+ $active_goods_model = new ActiveGoods();
+ $count = $active_goods_model->where($check_condition)
+ ->withJoin([
+ 'active' => function(Query $query) use ($goods_where) {
+ $query->where($goods_where);
+ },
+ ], 'inner')
+ ->count();
+ if ($count > 0) throw new AdminException('EXCHANGE_GOODS_ACTIVITY_EXISTING');
+ Db::startTrans();
+ try {
+ $create_data = [
+ 'names' => $data[ 'names' ] ?? '',
+ 'type' => $data[ 'type' ] ?? '',
+ 'title' => $data[ 'title' ] ?? '',
+ 'image' => $data[ 'image' ] ?? '',
+ 'product_detail' => $data[ 'product_detail' ] ?? '',
+ 'point' => $data[ 'point' ] ?? 0,
+ 'price' => $data[ 'price' ] ?? 0,
+ 'stock' => $data[ 'stock' ] ?? 0,
+ 'limit_num' => $data[ 'limit_num' ] ?? '',
+ 'content' => $data[ 'content' ] ?? '',
+ 'create_time' => time(),
+ 'update_time' => time(),
+ 'status' => ExchangeDict::UP,
+ ];
+ $res = $this->model->create($create_data);
+ $active_goods[] = [
+ 'goods_id' => $product_detail[ 0 ][ 'goods_id' ],
+ 'active_goods_type' => ActiveDict::GOODS_SINGLE,
+ 'active_class' => ActiveDict::EXCHANGE,
+ 'active_goods_value' => json_encode($product_detail),
+ 'active_goods_status' => ActiveDict::ACTIVE,
+ 'active_goods_price' => $create_data[ 'price' ],
+ 'active_goods_point' => $create_data[ 'point' ],
+ ];
+ $data[ 'active_goods' ] = $product_detail;
+ $data[ 'active_status' ] = ActiveDict::ACTIVE;
+ $data[ 'active_type' ] = ActiveDict::GOODS;
+ $data[ 'active_goods_type' ] = ActiveDict::GOODS_SINGLE;
+ $data[ 'active_class' ] = ActiveDict::EXCHANGE;
+ $data[ 'active_name' ] = $create_data[ 'names' ] ?? '';
+ $data[ 'active_desc' ] = $create_data[ 'content' ] ?? '';
+ $data[ 'start_time' ] = time();
+ $data[ 'end_time' ] = 0;
+ $data[ 'active_goods' ] = $active_goods;
+ $active_id = ( new CoreActiveService() )->add($data);
+ Db::commit();
+ return $res->id;
+ } catch (\Exception $e) {
+ Db::rollback();
+ throw new CommonException($e->getMessage());
+ }
+ }
+
+
+ /**
+ * 验证积分商城 数据保存
+ * @param int $id
+ * @param array $data
+ * @return bool
+ */
+ public function verifyData(&$data)
+ {
+ if (empty(ExchangeDict::getType($data[ 'type' ]))) throw new AdminException('EXCHANGE_GOODS_CONFIRM_TYPE');
+ $product_detail = json_decode($data[ 'product_detail' ], true);
+ if ($data[ 'type' ] == 'goods') {
+ if (empty($product_detail)) throw new AdminException('EXCHANGE_GOODS_NOT_EMPTY');
+ $data[ 'stock' ] = 0;
+ foreach ($product_detail as &$item) {
+ if ($item[ 'point' ] <= 0) throw new AdminException('EXCHANGE_GOODS_POINT_GREATER_THAN_ZERO');
+ if ($item[ 'stock' ] < 0) throw new AdminException('EXCHANGE_GOODS_STOCK_GREATER_THAN_ZERO');
+ if (empty($item[ 'price' ])) $item[ 'price' ] = 0;
+ $data[ 'stock' ] += $item[ 'stock' ];
+ }
+ array_multisort(array_column($product_detail, "point"), SORT_ASC, $product_detail);
+ $data[ 'point' ] = $product_detail[ 0 ][ 'point' ];
+ $data[ 'price' ] = $product_detail[ 0 ][ 'price' ];
+ $data[ 'limit_num' ] = $product_detail[ 0 ][ 'limit_num' ];
+ $data[ 'product_detail' ] = json_encode($product_detail);
+ }
+ }
+
+ /**
+ * 编辑积分商城
+ * @param int $id
+ * @param array $data
+ * @return bool
+ */
+ public function edit(int $id, array $data)
+ {
+ $info = $this->model->where([ [ 'id', '=', $id ] ])->findOrEmpty();
+ if ($info->isEmpty()) throw new AdminException('EXCHANGE_DATA_NOT_FOUND');
+// $product_detail = json_decode($data[ 'product_detail' ], true);
+ $this->verifyData($data);
+ Db::startTrans();
+ try {
+ $save_data = [
+ 'names' => $data[ 'names' ] ?? '',
+ 'type' => $data[ 'type' ] ?? '',
+ 'title' => $data[ 'title' ] ?? '',
+ 'image' => $data[ 'image' ] ?? '',
+ 'product_detail' => $data[ 'product_detail' ] ?? '',
+ 'point' => $data[ 'point' ] ?? 0,
+ 'price' => $data[ 'price' ] ?? 0,
+ 'stock' => $data[ 'stock' ] ?? 0,
+ 'limit_num' => $data[ 'limit_num' ] ?? '',
+ 'content' => $data[ 'content' ] ?? '',
+ 'update_time' => time(),
+ ];
+ $this->model->where([ [ 'id', '=', $id ] ])->update($save_data);
+ Db::commit();
+ return true;
+ } catch (\Exception $e) {
+ Db::rollback();
+ throw new CommonException($e->getMessage());
+ }
+ }
+
+ /**
+ * 修改积分商品上下架状态
+ * @param $data
+ * @return Goods
+ */
+ public function editStatus($data, $id)
+ {
+ if ($data[ 'status' ] == 1) {
+ $data_info = $this->getInfo([ 'ids' => $id ]);
+ if (!empty($data_info))
+ $goods_info = ( new Goods() )->where([ [ 'goods_id', '=', $data_info[ 'product_detail' ][ 0 ][ 'goods_id' ] ] ])->field('status')->findOrEmpty()->toArray();
+ if ($goods_info[ 'status' ] == 0) throw new AdminException('SHOP_GOODS_DELISTED');
+ }
+ return $this->model->where([ [ 'id', '=', $id ] ])->update([ 'status' => $data[ 'status' ] ]);
+ }
+
+
+ /**
+ * 修改排序号
+ * @param $data
+ * @return mixed
+ */
+ public function modifySort($data, $id = 0)
+ {
+ return $this->model->where([ [ 'id', '=', $id ] ])->update([ 'sort' => $data[ 'sort' ] ]);
+ }
+
+
+ /**
+ * 删除积分商城
+ * @param int $active_id
+ * @return bool
+ */
+ public function del(int $id)
+ {
+ $info = $this->model->where([ [ 'id', '=', $id ] ])->findOrEmpty();
+ if ($info->isEmpty()) throw new AdminException('EXCHANGE_DATA_NOT_FOUND');
+ Db::startTrans();
+ try {
+ $goods_id = 0;
+ foreach ($info[ 'product_detail' ] as $k => $v) {
+ if (!empty($v[ 'goods_id' ])) {
+ $goods_id = $v[ 'goods_id' ];
+ }
+ }
+ $active_info = ( new ActiveGoods() )->where([
+ [ 'goods_id', 'in', $goods_id ],
+ [ 'active_class', '=', ActiveDict::EXCHANGE ],
+ ])->field('active_id')->findOrEmpty()->toArray();
+ if (!empty($active_info)) ( new CoreActiveService() )->del($active_info[ 'active_id' ], 1);
+ $this->model->where([ [ 'id', '=', $id ] ])->delete();
+ Db::commit();
+ return true;
+ } catch (\Exception $e) {
+ Db::rollback();
+ throw new CommonException($e->getMessage());
+ }
+ }
+
+ /**
+ * 批量删除积分商城
+ * @param array $ids
+ * @return bool
+ */
+ public function batchDelete($ids)
+ {
+ $point_exchange_list = $this->model->where([ [ 'id', 'in', $ids ] ])->select()->toArray();
+ foreach ($point_exchange_list as $value){
+ if ($value[ 'status' ] == ExchangeDict::UP) throw new AdminException('EXIST_NOT_DOWN_ACTIVE');
+ }
+
+ $goods_ids = [];
+ foreach ($point_exchange_list as $value){
+ foreach ($value[ 'product_detail' ] as $v) {
+ if (!empty($v[ 'goods_id' ])) {
+ $goods_ids[] = $v[ 'goods_id' ];
+ }
+ }
+ }
+ $goods_ids = array_unique($goods_ids);
+
+ $active_ids = ( new ActiveGoods() )->where([
+ [ 'goods_id', 'in', $goods_ids ],
+ [ 'active_class', '=', ActiveDict::EXCHANGE ],
+ ])->column('active_id');
+ Db::startTrans();
+ try {
+ $this->model->where([ [ 'id', 'in', $ids ] ])->delete();
+ (new Active())->where([ [ 'active_id', 'in', $active_ids ], [ 'active_class', '=', ActiveDict::EXCHANGE ] ])->delete();
+ (new ActiveGoods())->where([ [ 'active_id', 'in', $active_ids ], [ 'active_class', '=', ActiveDict::EXCHANGE ] ])->delete();
+ Db::commit();
+ return true;
+ } catch (\Exception $e) {
+ Db::rollback();
+ throw new CommonException($e->getMessage());
+ }
+ }
+
+ /**
+ * 批量下架积分商城
+ * @param array $ids
+ * @return bool
+ */
+ public function batchDown($ids)
+ {
+ $this->model->where([ [ 'id', 'in', $ids ], [ 'status', '=', ExchangeDict::UP] ])->update( [ 'status' => ExchangeDict::DOWN] );
+
+ return true;
+ }
+
+ /**
+ * 批量上架积分商城
+ * @param array $ids
+ * @return bool
+ */
+ public function batchUp($ids)
+ {
+ $this->model->where([ [ 'id', 'in', $ids ], [ 'status', '=', ExchangeDict::DOWN] ])->update( [ 'status' => ExchangeDict::UP] );
+
+ return true;
+ }
+
+
+ /**
+ * 商品编辑业务
+ * @param $exchange_goods_info
+ * @param string $status
+ * @param array $sku_list
+ * @return bool
+ */
+ public function afterGoodsEdit($exchange_goods_info, $status = '', $sku_list = [])
+ {
+ Db::startTrans();
+ try {
+ if ($status != '' && $status == '0') $save_data[ 'status' ] = $status;
+ if (!empty($sku_list)) {
+ foreach ($exchange_goods_info[ 'product_detail' ] as &$item) {
+ $item[ 'stock' ] = $item[ 'stock' ] > $sku_list[ $item[ 'sku_id' ] ][ 'stock' ] ? $sku_list[ $item[ 'sku_id' ] ][ 'stock' ] : $item[ 'stock' ];
+ }
+ $save_data[ 'type' ] = $exchange_goods_info[ 'type' ];
+ $save_data[ 'product_detail' ] = json_encode($exchange_goods_info[ 'product_detail' ]);
+ $this->verifyData($save_data);
+ }
+ if (isset($save_data)) $this->model->where([ [ 'id', '=', $exchange_goods_info[ 'id' ] ] ])->update($save_data);
+ Db::commit();
+ return true;
+ } catch (\Exception $e) {
+ Db::rollback();
+ throw new CommonException($e->getMessage());
+ }
+
+ }
+
+
+}
diff --git a/niucloud/addon/shop/app/service/admin/order/ConfigService.php b/niucloud/addon/shop/app/service/admin/order/ConfigService.php
new file mode 100644
index 000000000..1654c7f31
--- /dev/null
+++ b/niucloud/addon/shop/app/service/admin/order/ConfigService.php
@@ -0,0 +1,57 @@
+order_config_service = new CoreOrderConfigService();
+ }
+
+ /**
+ * 交易设置
+ * @param array $params
+ * @return array
+ */
+ public function setConfig($params)
+ {
+ if ($params['evaluate_is_to_examine'] == 0) {
+ ( new EvaluateService() )->auditEditBatch();
+ }
+ return $this->order_config_service->setConfig($params);
+ }
+
+ /**
+ * 获取交易设置
+ * @return array
+ */
+ public function getConfig()
+ {
+ return $this->order_config_service->getConfig();
+ }
+
+}
diff --git a/niucloud/addon/shop/app/service/admin/order/InvoiceService.php b/niucloud/addon/shop/app/service/admin/order/InvoiceService.php
new file mode 100644
index 000000000..f18e44edd
--- /dev/null
+++ b/niucloud/addon/shop/app/service/admin/order/InvoiceService.php
@@ -0,0 +1,134 @@
+model = new Invoice();
+ }
+
+ public function getPage(array $where)
+ {
+ $order = 'id desc';
+ $search_model = $this->model
+ ->withSearch(["is_invoice", "header_type", "header_name", "create_time", "invoice_time"], $where)
+ ->where([['status', '=', InvoiceDict::OPEN]])
+ ->append(['header_type_name', 'type_name', 'invoice_type_name','pay_voucher_thumb_mid','pay_voucher_thumb_small','pay_voucher_thumb_big','invoice_voucher_thumb_mid','invoice_voucher_thumb_small','invoice_voucher_thumb_big'])
+ ->field('*')->order($order);
+ $list = $this->pageQuery($search_model);
+ foreach ($list['data'] as &$item) {
+ $item['is_can_jump'] = 1;
+ if (count(explode(',', $item['trade_id'])) > 1) {
+ $item['is_can_jump'] = 0;
+ }
+ }
+ return $list;
+ }
+
+ public function getInfo(int $id)
+ {
+ $detail = $this->model->where([['id', '=', $id], ['status', '=', InvoiceDict::OPEN]])->field('*')->append(['header_type_name', 'type_name'])->findOrEmpty()->toArray();
+ return $detail;
+ }
+
+ /**
+ * 开票
+ * @param int $id
+ * @param array $data
+ * @return true
+ */
+ public function invoicing(int $id, array $data)
+ {
+ $invoice = $this->model->where([['id', '=', $id], ['status', '=', 2]])->findOrEmpty();
+ if ($invoice->isEmpty()) throw new CommonException('INVOICE_NOT_EXIST');
+ if ($invoice['is_invoice']) throw new CommonException('INVOICED');
+
+ $invoice->is_invoice = 1;
+ $invoice->invoice_number = $data['invoice_number'];
+ $invoice->invoice_voucher = $data['invoice_voucher'];
+ $invoice->remark = $data['remark'];
+ $invoice->invoice_time = time();
+
+ $invoice->save();
+
+ return true;
+ }
+
+ /**
+ * 开票
+ * @param int $id
+ * @param array $data
+ * @return true
+ */
+ public function audit($data)
+ {
+ (new CoreInvoiceService())->audit($data['ids']);
+ return true;
+ }
+
+ public function add($data)
+ {
+ $order_info = (new OrderService())->getInfoByOrderNo($data['order_no']);
+ if (empty($order_info)) {
+ throw new AdminException('SHOP_ORDER_NOT_FOUND');
+ }
+ $trade_id = $order_info['order_id'];
+ $member_id = $order_info['member_id'];
+ $invoice_info = $this->model->where([
+ 'trade_id' => $trade_id,
+ 'member_id' => $member_id
+ ])->findOrEmpty();
+ if (!$invoice_info->isEmpty()) {
+ throw new CommonException('INVOICE_IS_EXIST');
+ }
+ $insert = [
+ 'member_id' => $member_id,
+ 'trade_type' => InvoiceDict::TYPE,
+ 'trade_id' => $trade_id,
+ 'header_type' => $data['header_type'],
+ 'header_name' => $data['header_name'],
+ 'type' => $data['type'],
+ 'name' => $data['name'],
+ 'pay_voucher' => $data['pay_voucher'],
+ 'tax_number' => $data['tax_number'],
+ 'mobile' => $data['mobile'],
+ 'email' => $data['email'],
+ 'telephone' => $data['telephone'],
+ 'address' => $data['address'],
+ 'bank_name' => $data['bank_name'],
+ 'bank_card_number' => $data['bank_card_number'],
+ 'money' => $data['money'],
+ 'is_invoice' => InvoiceDict::WAIT_INVOICE,
+ 'create_time' => time(),
+ 'status' => InvoiceDict::OPEN,
+ ];
+ $invoice_id = (new CoreInvoiceService())->add($insert);
+ (new CoreOrderService())->setInvoiceIdByOrderId([$trade_id], $invoice_id);
+ }
+
+}
diff --git a/niucloud/addon/shop/app/service/admin/order/OrderBatchDeliveryService.php b/niucloud/addon/shop/app/service/admin/order/OrderBatchDeliveryService.php
new file mode 100644
index 000000000..97b181b99
--- /dev/null
+++ b/niucloud/addon/shop/app/service/admin/order/OrderBatchDeliveryService.php
@@ -0,0 +1,95 @@
+model = new OrderBatchDelivery();
+ }
+
+ /**
+ * 分页列表
+ * @param array $where
+ * @return array
+ */
+ public function getPage(array $where)
+ {
+ $field = 'id,main_id,status,type,total_num,success_num,fail_num,create_time,data, update_time, output, fail_output, fail_remark';
+ $order = 'create_time desc';
+ $search_model = $this->model
+ ->withSearch([ 'status', 'type', 'create_time', 'main_id' ], $where)
+ ->field($field)
+ ->with([
+ 'user' => function($query) {
+ $query->field('uid, username, head_img, real_name');
+ }
+ ])->order($order)->append([ 'type_name', 'status_name' ]);
+ return $this->pageQuery($search_model);
+ }
+
+ /**
+ * 获取详情
+ * @param $id
+ * @return array
+ * @throws \think\db\exception\DbException
+ */
+ public function getInfo($id)
+ {
+ $field = 'id,main_id,status,type,total_num,success_num,fail_count,create_time,data, update_time, output, fail_output, fail_remark';
+ return $this->model
+ ->where([
+ [ 'id', '=', $id ]
+ ])
+ ->field($field)
+ ->with([
+ 'user' => function($query) {
+ $query->field('extend,order_goods_id, order_id, member_id, goods_id, sku_id, goods_name, sku_name, goods_image, sku_image, price, num, goods_money, is_enable_refund, goods_type, delivery_status, status,discount_money')->append([ 'delivery_status_name', 'status_name', 'goods_image_thumb_small' ]);
+ }
+ ])->append([ 'type_name', 'status_name' ])->findOrEmpty()->toArray();
+ }
+
+ /**
+ * 加入批量发货任务
+ * @param $data
+ * @return void
+ */
+ public function addBatchOrderDelivery($data)
+ {
+ $data[ 'type' ] = OrderBatchDeliveryDict::DELIVERY;
+ $data[ 'main_id' ] = $this->uid;
+ ( new CoreOrderBatchDeliveryService() )->add($data);
+ return true;
+ }
+
+ /**
+ * 手动执行任务
+ * @param $id
+ * @return void
+ */
+ public function execute($id)
+ {
+ return ( new CoreOrderBatchDeliveryService() )->execute($id);
+ }
+
+}
diff --git a/niucloud/addon/shop/app/service/admin/order/OrderCloseService.php b/niucloud/addon/shop/app/service/admin/order/OrderCloseService.php
new file mode 100644
index 000000000..81ebc7bf8
--- /dev/null
+++ b/niucloud/addon/shop/app/service/admin/order/OrderCloseService.php
@@ -0,0 +1,45 @@
+uid;
+ $data[ 'close_type' ] = OrderDict::SHOP_CLOSE;
+ $data[ 'order_id' ] = $order_id;
+ ( new CoreOrderCloseService() )->close($data);
+ return true;
+ }
+
+}
diff --git a/niucloud/addon/shop/app/service/admin/order/OrderDeliveryService.php b/niucloud/addon/shop/app/service/admin/order/OrderDeliveryService.php
new file mode 100644
index 000000000..1d17efb8c
--- /dev/null
+++ b/niucloud/addon/shop/app/service/admin/order/OrderDeliveryService.php
@@ -0,0 +1,89 @@
+uid;
+ ( new CoreOrderDeliveryService() )->delivery($data);
+ return true;
+ }
+
+ /**
+ * 获取订单发货包裹列表
+ * @param $params
+ * @return mixed
+ */
+ public function getDeliveryPackageList($params)
+ {
+ $list = ( new OrderDelivery() )
+ ->where([
+ [ 'order_id', '=', $params[ 'order_id' ] ]
+ ])
+ ->field('id, order_id, name, delivery_type, sub_delivery_type,express_company_id, express_number, create_time')->with([
+ 'company' => function($query) {
+ $query->field('company_id, company_name, express_no');
+ },
+ 'order_goods' => function($query) {
+ $query->field('goods_name, sku_name, goods_image, delivery_id, num, price')->append([ 'goods_image_thumb_small' ]);
+ }
+ ])
+ ->select()->toArray();
+ return $list;
+ }
+
+ /**
+ * 物流信息
+ * @param $id
+ */
+ public function getDeliveryPackage($data)
+ {
+ $field = 'id, order_id, name, delivery_type, sub_delivery_type, express_company_id, express_number, local_deliver_id, status, create_time';
+ $info = ( new OrderDelivery() )->where([ [ 'id', '=', $data[ 'id' ] ] ])->with([
+ 'company' => function($query) {
+ $query->field('company_id, company_name, express_no');
+ },
+ 'order_goods' => function($query) {
+ $query->field('goods_name, sku_name, goods_image, delivery_id, num, price')->append([ 'goods_image_thumb_small' ]);
+ }
+ ])->field($field)->findOrEmpty()->toArray();
+ if (!empty($info) && $info[ 'delivery_type' ] == OrderDeliveryDict::EXPRESS && $info[ 'sub_delivery_type' ] != OrderDeliveryDict::NONE_EXPRESS) {
+ $info[ 'mobile' ] = $data[ 'mobile' ];
+ $info = ( new CoreOrderService() )->deliverySearch($info);
+ }
+ return $info;
+ }
+}
diff --git a/niucloud/addon/shop/app/service/admin/order/OrderFinishService.php b/niucloud/addon/shop/app/service/admin/order/OrderFinishService.php
new file mode 100644
index 000000000..d9b7dfcc3
--- /dev/null
+++ b/niucloud/addon/shop/app/service/admin/order/OrderFinishService.php
@@ -0,0 +1,56 @@
+model = new Order();
+ }
+
+ /**
+ * 完成
+ * @param $order_id
+ * @return true
+ */
+ public function finish(int $order_id)
+ {
+ $data[ 'main_type' ] = OrderLogDict::STORE;
+ $data[ 'main_id' ] = $this->uid;
+ $data[ 'order_id' ] = $order_id;
+
+ //查询订单
+ $where = array(
+ ['order_id', '=', $order_id],
+ );
+ $order = $this->model->where($where)->findOrEmpty()->toArray();
+ if (empty($order)) throw new AdminException('SHOP_ORDER_NOT_FOUND');//订单不存在
+ if ($order['status'] != OrderDict::WAIT_TAKE) throw new AdminException('SHOP_ONLY_WAIT_TAKE_CAN_BE_TAKE');//只有待收货的订单才可以收货
+ ( new CoreOrderFinishService() )->finish($data);
+ return true;
+ }
+
+}
diff --git a/niucloud/addon/shop/app/service/admin/order/OrderService.php b/niucloud/addon/shop/app/service/admin/order/OrderService.php
new file mode 100644
index 000000000..43370d770
--- /dev/null
+++ b/niucloud/addon/shop/app/service/admin/order/OrderService.php
@@ -0,0 +1,643 @@
+model = new Order();
+ }
+
+ /**
+ * 分页列表
+ * @param array $where
+ * @return array
+ */
+ public function getPage(array $where)
+ {
+ $field = 'buyer_ask_delivery_time,point,activity_type,order_id,order_no,order_type,order_from,out_trade_no,status,member_id,ip,goods_money,delivery_money,order_money,create_time,pay_time,delivery_type,taker_name,taker_mobile,taker_full_address,take_store_id,is_enable_refund,member_remark,shop_remark,close_type,close_remark,pay_money,relate_source,relate_order_id';
+ $order = 'create_time desc';
+
+ $pay_where = [];
+ if ($where['pay_type']) {
+ if ($where['pay_type'] == PayDict::FRIENDSPAY) {
+ $pay_where = [
+ ['pay.main_id', '<>', Db::raw("pay.from_main_id")],
+ ['pay.from_main_id', '>', 0],
+ ['pay.status', '=', PayDict::STATUS_FINISH]
+ ];
+ } else {
+ $pay_where[] = ['pay.type', '=', $where['pay_type']];
+ }
+ }
+ $member_where = [];
+ if ($where['keyword'] != '') {
+ $member_where = [
+ ['member.member_no|member.nickname|member.username|member.mobile', 'like', "%" . $where['keyword'] . "%"],
+ ];
+ }
+ $search_model = $this->model
+ ->where([['order.order_id', '>', 0]])
+ ->withSearch(['search_type', 'order_from', 'join_status', 'create_time', 'join_pay_time', 'activity_type'], $where)
+ ->field($field)
+ ->withJoin([
+ 'pay' => function (Query $query) use ($pay_where) {
+ $query->where($pay_where);
+ },
+ 'member' => function (Query $query) use ($member_where) {
+ $query->where($member_where);
+ },
+
+ ], 'left')
+ ->with([
+ 'order_goods' => function ($query) {
+ $query->with(['delivery_info' => function ($query) {
+ $query->field('*')->append(['express_company_name']);
+ }])
+ ->field('extend,order_goods_id, order_id, member_id, goods_id, sku_id, goods_name, sku_name, goods_image, sku_image, price, num, goods_money, is_enable_refund, goods_type, delivery_status, status,discount_money,delivery_id,is_gift')
+ ->append(['delivery_status_name', 'status_name', 'goods_image_thumb_small', 'impulse_buy_info']);
+ }
+ ])->order($order)->append(['order_from_name', 'order_type_name', 'status_name', 'delivery_type_name','activity_type_name']);
+ $order_status_list = OrderDict::getStatus();
+ $order_close_list = OrderDict::getCloseType();
+ $list = $this->pageQuery($search_model, function ($item, $key) use ($order_status_list, $order_close_list) {
+ $item['close_type_name'] = $order_close_list[$item['close_type']] ?? "";
+ $item['order_status_data'] = $order_status_list[$item['status']] ?? [];
+ $item_pay = $item['pay'];
+ if (!empty($item_pay)) {
+ $item_pay->append(['type_name']);
+ $item_pay['pay_type_name'] = PayDict::getPayType()[PayDict::FRIENDSPAY]['name'] ?? '';
+ }
+ });
+ $list['data'] = $this->getOrderRelateSourceInfo($list['data']);
+ return $list;
+ }
+
+ /**
+ * 获取订单来源的活动
+ * @param $order_data
+ * @return mixed
+ */
+ private function getOrderRelateSourceInfo($order_data)
+ {
+ $relate_activity_list = array_reduce($order_data, function ($result, $order_data) {
+ $source = $order_data['relate_source'];
+ $result[$source][] = [
+ 'order_id' => $order_data['order_id'],
+ 'relate_order_id' => $order_data['relate_order_id'],
+ ];
+ return $result;
+ }, []);
+ $active_res_list = event('ThirdAddonGetOrderActive', $relate_activity_list);
+ $active_list = [];
+ foreach ($active_res_list as $item) {
+ if (empty($item)) {
+ continue;
+ }
+ $active_list += $item;
+ }
+ foreach ($order_data as &$datum) {
+ $datum['relate_active_info'] = $active_list[$datum['order_id']] ?? [];
+ }
+ return $order_data;
+ }
+
+ /**
+ * 详情
+ * @param int $order_id
+ * @return array
+ */
+ public function getDetail(int $order_id)
+ {
+ $field = 'activity_type,point,order_id,order_no,order_type,order_from,out_trade_no,status,member_id,ip,goods_money,delivery_money,order_money,invoice_id,create_time,pay_time,delivery_time,take_time,finish_time,close_time,delivery_type,taker_name,taker_mobile,buyer_ask_delivery_time,taker_province,taker_city,taker_district,taker_address,taker_full_address,taker_longitude,taker_latitude,take_store_id,is_enable_refund,member_remark,shop_remark,close_remark,discount_money,form_record_id';
+ $info = $this->model->where([['order_id', '=', $order_id]])->field($field)
+ ->with(
+ [
+ 'order_goods' => function ($query) {
+ $query->field('extend,order_goods_id, order_id, member_id, goods_id, sku_id, goods_name, sku_name, goods_image, sku_image, price, num, goods_money, is_enable_refund, goods_type, delivery_status, status,discount_money,delivery_id,is_gift,form_record_id')->append(['delivery_status_name', 'status_name', 'impulse_buy_info']);
+ },
+ 'member' => function ($query) {
+ $query->field('member_id, nickname, mobile, headimg');
+ },
+ 'order_log' => function ($query) {
+ $query->field('order_id, content, main_type, create_time, main_id, type')->order("create_time desc, id desc")->append(['main_type_name', 'type_name', 'main_name']);
+ },
+ 'order_discount' => function ($query) {
+ $query->field('order_id,discount_type,money,content');
+ }
+ ])->append(['order_from_name', 'order_type_name', 'status_name', 'delivery_type_name'])->findOrEmpty()->toArray();
+ $info['verify_code'] = ''; // 核销码
+ $info['verifier_member'] = ''; // 核销员
+ $order_status_list = OrderDict::getStatus();
+ if (!empty($info)) $info['order_status_data'] = $order_status_list[$info['status']] ?? [];
+ if ($info['delivery_type'] == DeliveryDict::STORE) {
+ $info['store'] = (new Store())->where([['store_id', '=', $info['take_store_id']]])
+ ->field('store_id, store_name, full_address, store_mobile, trade_time')
+ ->findOrEmpty()->toArray();
+ $verify_info = (new Verify())->where([
+ ['type', '=', 'shopPickUpOrder'],
+ ['relate_tag', '=', $order_id]
+ ])->field('id, code, verifier_member_id')->with(['member' => function ($query) {
+ $query->field('member_id, nickname');
+ }])->findOrEmpty()->toArray();
+ if (!empty($verify_info)) {
+ $info['verify_code'] = $verify_info['code'];
+ $info['verifier_member'] = $verify_info['member'];
+ }
+ }
+
+ if ($info['delivery_type'] == DeliveryDict::EXPRESS || $info['delivery_type'] == DeliveryDict::LOCAL_DELIVERY) {
+ $info['order_delivery'] = (new OrderDelivery())
+ ->where([['order_id', '=', $info['order_id']]])
+ ->field('id, order_id, name, delivery_type, sub_delivery_type,express_company_id, express_number, create_time,third_delivery')
+ ->append(['third_delivery_name'])
+ ->select()->toArray();
+ if ($info['delivery_type'] == DeliveryDict::LOCAL_DELIVERY) {
+ $third_party_config = (new CoreLocalDeliveryService())->getConfig();
+ foreach ($info['order_delivery'] as $k => $item) {
+ if (!empty($item['third_delivery'])) {
+ $third_delivery = $item['third_delivery'];
+ $loader = new ThirdDeliveryLoader($third_delivery, $third_party_config[$third_delivery]);
+ //三方配送下单
+ $info['order_delivery'][$k]['third_delivery_info'] = $loader->queryOrderInfo([
+ 'order_no' => $info['order_no']
+ ]);
+ }
+ }
+ }
+ }
+
+
+ if ($info['out_trade_no']) {
+ $info['pay'] = (new Pay())->where([['out_trade_no', '=', $info['out_trade_no']]])
+ ->field('main_id, out_trade_no, type, pay_time, status')->append(['type_name'])->findOrEmpty()->toArray();
+
+ if (!empty($info['pay'])) {
+ if ($info['member_id'] != $info['pay']['main_id']) {
+ $member_info = (new Member())->where([['member_id', '=', $info['pay']['main_id']]])->findOrEmpty()->toArray();
+ if (!empty($member_info)) {
+ $info['pay']['pay_member'] = $member_info['nickname'];
+ }
+ }
+ $info['pay']['pay_type_name'] = PayDict::getPayType()[PayDict::FRIENDSPAY]['name'] ?? '';
+ }
+ }
+
+ $coupon_money = 0;
+ $manjian_discount_money = 0;
+ if ($info['order_discount']) {
+ foreach ($info['order_discount'] as $item) {
+ if ($item['discount_type'] == 'coupon') {
+ $coupon_money += $item['money'];
+ }
+ if ($item['discount_type'] == 'manjian') {
+ $manjian_discount_money += $item['money'];
+ }
+ }
+ }
+ $info['coupon_money'] = number_format($coupon_money, 2, '.', '');
+ $info['manjian_discount_money'] = number_format($manjian_discount_money, 2, '.', '');
+
+ $diy_form_records_fields_model = new DiyFormRecordsFields();
+ if (!empty($info['form_record_id'])) {
+ $field_count = $diy_form_records_fields_model->where([['record_id', '=', $info['form_record_id']]])->count();
+ if ($field_count > 0) {
+ $info['form_record_show'] = true;
+ } else {
+ $info['form_record_show'] = false;
+ }
+ }
+ if (!empty($info['order_goods'])) {
+ foreach ($info['order_goods'] as &$item) {
+ $field_count = $diy_form_records_fields_model->where([['record_id', '=', $item['form_record_id']]])->count();
+ if ($field_count > 0) {
+ $item['form_record_show'] = true;
+ } else {
+ $item['form_record_show'] = false;
+ }
+ $impulse_buy_tips = '';
+ if (isset($item['extend']['is_impulse_buy']) == 1) {
+ $impulse_buy_num = $item['extend']['impulse_buy_goods_num'] ?? 0;//5
+ $impulse_buy_price_total = $item['extend']['impulse_buy_price'] ?? 0;
+ if ($impulse_buy_num > 0) {
+ $impulse_buy_price = $impulse_buy_price_total / $impulse_buy_num;
+ if ($impulse_buy_num == 1) {
+ $impulse_buy_tips = '第1' . '件' . $impulse_buy_price . '元';
+ } else {
+ $impulse_buy_tips = '第1-' . $impulse_buy_num . '件' . $impulse_buy_price . '元';
+ if ($item['num'] > $impulse_buy_num) {
+ if ($impulse_buy_num + 1 == $item['num']) {
+ $impulse_buy_tips .= ' 第' . ($impulse_buy_num + 1) . '件' . $item['price'] . '元';
+ } else {
+ $impulse_buy_tips .= ' 第' . ($impulse_buy_num + 1) . '-' . $item['num'] . '件' . $item['price'] . '元';
+ }
+ }
+ }
+ } else {//全原价
+ $impulse_buy_tips = '第1-' . $item['num'] . '件' . $item['price'] . '元';
+ }
+ }
+ $item['impulse_buy_info']['show_tips'] = $impulse_buy_tips;
+ }
+ }
+ return $info;
+ }
+
+ /**
+ * 商家留言
+ * @param $data
+ * @return bool
+ */
+ public function shopRemark($data)
+ {
+ $this->model->where([['order_id', '=', $data['order_id']]])->update(['shop_remark' => $data['shop_remark']]);
+ return true;
+ }
+
+ /**
+ * 订单数量统计
+ * @throws DbException
+ */
+ public function getOrderCount()
+ {
+ $data = [
+ "wait_pay_order" => 0, //待付款
+ "wait_delivery_order" => 0, //待发货
+ "wait_take_order" => 0, //待收货
+ "refund_order" => 0, //退款中(订单项)
+ ];
+
+ $data['wait_pay_order'] = $this->model->where([ ['status', '=', OrderDict::WAIT_PAY]])->count();
+ $data['wait_delivery_order'] = $this->model->where([ ['status', '=', OrderDict::WAIT_DELIVERY]])->count();
+ $data['wait_take_order'] = $this->model->where([ ['status', '=', OrderDict::WAIT_TAKE]])->count();
+ $data['refund_order'] = (new OrderGoods())->where([ ['status', '=', OrderGoodsDict::REFUNDING]])->count();
+
+ return $data;
+ }
+
+ /**
+ * 订单改价
+ * @param $data
+ * @return void
+ */
+ public function editPrice($data)
+ {
+ $order_id = $data['order_id'];
+ $order = $this->model->where([['order_id', '=', $order_id]])->findOrEmpty();
+ if ($order->isEmpty()) throw new AdminException('SHOP_ORDER_NOT_FOUND');
+ if ($order['status'] != OrderDict::WAIT_PAY) throw new AdminException('SHOP_ONLY_PENDING_ORDERS_CAN_BE_REPRICED');
+
+ //关闭相关的支付 todo 封装订单专用的关闭支付相关
+ try {
+ (new CorePayService())->closeByTrade(OrderDict::TYPE, $order_id);
+ } catch (\Exception $e) {
+ throw new AdminException($e->getMessage());
+ }
+
+ $delivery_money = $data['delivery_money'];
+ if ($delivery_money < 0) throw new AdminException('SHOP_THE_SHIPPING_FEE_CANNOT_BE_LESS_THAN_0');
+ $order_goods_data = $data['order_goods_data'];//['order_goods_id' => ['money' => 10]]
+ $order_goods_model = new OrderGoods();
+ $order_goods_list = $order_goods_model->where([['order_id', '=', $order_id]])->select();
+ $goods_money = 0;
+ Db::startTrans();
+ try {
+ foreach ($order_goods_list as $key => $item) {
+ $item_order_goods_id = $item['order_goods_id'];
+ $temp_goods_data = $order_goods_data[$item_order_goods_id] ?? [];
+
+ if (!empty($temp_goods_data)) {
+ $item_money = $temp_goods_data['money'] ?? 0;
+ if ($item_money != 0) {
+ $item_order_goods_money = $item['order_goods_money'];//订单项总额
+ $item_new_order_goods_money = round($item_order_goods_money + $item_money, 2);//
+ if ($item_new_order_goods_money < 0) {
+ throw new AdminException('SHOP_THE_LINE_ITEM_SUBTOTAL_CAN_T_BE_LESS_THAN_0');
+ }
+ $item_new_goods_money = $item_new_order_goods_money + $item['discount_money'];
+ $item_new_price = floor($item_new_goods_money / $item['num'] * 100) / 100;
+
+ $order_goods_list[$key]['old_goods_money'] = $item['goods_money'];
+
+ $item->save([
+ 'price' => $item_new_price,
+ 'goods_money' => $item_new_goods_money,
+ 'order_goods_money' => $item_new_order_goods_money
+ ]);
+ $goods_money += $item_new_goods_money;
+ continue;
+ }
+ }
+ $goods_money += $item['goods_money'];
+ }
+ $order_money = round($goods_money + $delivery_money - $order['discount_money'], 2);
+ if ($order_money < 0) {
+ $order_money = 0;
+ }
+
+ $order['old_delivery_money'] = $order['delivery_money'];
+
+ $order->save([
+ 'goods_money' => $goods_money,
+ 'delivery_money' => $delivery_money,
+ 'order_money' => $order_money
+ ]);
+
+ $order_param = [
+ 'order_data' => $order->toArray(),
+ 'order_goods_data' => $order_goods_list->toArray(),
+ 'main_id' => $this->uid,
+ 'main_type' => OrderLogDict::SYSTEM
+ ];
+ //订单改价操作
+ CoreOrderEventService::orderEditPrice($order_param);
+ //订单改价后操作
+ CoreOrderEventService::orderEditPriceAfter($order_param);
+ if ($order_money == 0) {
+ (new CoreOrderPayService())->pay([ 'trade_id' => $order_id, 'main_type' => OrderLogDict::SYSTEM, 'main_id' => $this->uid]);
+ }
+ Db::commit();
+ return true;
+ } catch (\Exception $e) {
+ Db::rollback();
+ throw new AdminException($e->getMessage());
+ }
+ }
+
+ /**
+ * 修改收货地址
+ * @param $data
+ */
+ public function editDelivery($data)
+ {
+ $data = $this->getEditDeliveryData($data);
+ if ($data['error_code'] < 0) {
+ throw new AdminException($data['error_msg'] ?? '');
+ }
+ $delivery_data = $data['delivery_data'];
+ $this->model->where([['order_id', '=', $data['order_id']]])->update($delivery_data);
+ return true;
+ }
+
+ /**
+ * 订单修改收货地址信息
+ * @param $data
+ */
+ public function getEditDeliveryData($data)
+ {
+ $delivery_type = $data['delivery_type'];
+ $order_id = $data['order_id'];
+ $order = $this->model->where([['order_id', '=', $order_id]])->findOrEmpty()->toArray();
+ $delivery_list = (new DeliveryService())->getDeliveryList();
+ if (empty($order)) throw new AdminException('SHOP_ORDER_NOT_FOUND');
+ if (!in_array($order['status'], [OrderDict::WAIT_PAY, OrderDict::WAIT_DELIVERY])) throw new AdminException('SHOP_ONLY_PENDING_ORDERS_EDIT_TAKER');
+ if ($order['delivery_type'] == OrderDeliveryDict::VIRTUAL) throw new AdminException('SHOP_VIRTUAL_ORDERS_EDIT_TAKER');
+ $order['delivery_data'] = $data;
+
+ $order['order_goods'] = (new OrderGoods())->where([['goods_type', '=', 'real'], ['order_id', '=', $order_id]])->with(['goods'])->select()->toArray();
+ $order['error_code'] = 1;
+ $order['error_msg'] = '';
+ if (empty($delivery_type) || !isset($delivery_list[$delivery_type])) {
+ $order['error_code'] = -1;
+ $order['error_msg'] = get_lang('NOT_SUPPORT_DELIVERY_TYPE');
+ return $order;
+ } else if (!empty($delivery_type) && $delivery_list[$delivery_type]['status'] > 1) {
+ $order['error_code'] = -1;
+ $order['error_msg'] = get_lang('DELIVERY_TYPE_NOT_OPEN');
+ return $order;
+ }
+
+ $goods_name = '';
+ foreach ($order['order_goods'] as $k => &$v) {
+ if (!in_array($delivery_type, $v['goods']['delivery_type'])) {
+ $v['error_code'] = -1;
+ $v['error_msg'] = get_lang('GOODS_NOT_DELIVERY_TYPE');
+ $order['error_code'] = -1;
+ $goods_name .= $v['goods_name'] . ',';
+ }
+ }
+
+ if ($order['error_code'] < 0) {
+ $goods_name = trim($goods_name, ',');
+ if ($goods_name) $order['error_msg'] = $goods_name . '-' . get_lang('GOODS_NOT_DELIVERY_TYPE');
+ return $order;
+ }
+
+ switch ($delivery_type) {
+ case OrderDeliveryDict::EXPRESS:
+ if (empty($data['taker_name'])
+ || empty($data['taker_mobile'])
+ || empty($data['taker_province'])
+ || empty($data['taker_city'])
+ || empty($data['taker_district'])
+ || empty($data['taker_address'])
+ || empty($data['taker_full_address'])
+ ) {
+ $order['error_code'] = -1;
+ $order['error_msg'] = get_lang('EXPRESS_FIELD_EMPTY');
+ }
+ break;
+ case OrderDeliveryDict::LOCAL_DELIVERY:
+ if (empty($data['taker_name'])
+ || empty($data['taker_mobile'])
+ || empty($data['taker_province'])
+ || empty($data['taker_city'])
+ || empty($data['taker_district'])
+ || empty($data['taker_address'])
+ || empty($data['taker_full_address'])
+ || empty($data['taker_longitude'])
+ || empty($data['taker_latitude'])
+ ) {
+ $order['error_code'] = -1;
+ $order['error_msg'] = get_lang('EXPRESS_FIELD_EMPTY');
+ } else {
+ $order = $this->checkLocationInArea($order, $data);
+ }
+ break;
+ case OrderDeliveryDict::STORE:
+ if (empty($data['take_store_id'])) {
+ $order['error_code'] = -1;
+ $order['error_msg'] = get_lang('EXPRESS_FIELD_EMPTY');
+ }
+ break;
+ }
+
+ return $order;
+ }
+
+ /**
+ * 检查收货地址是否在配送区域
+ * @param $order
+ * @param $data
+ * @return mixed
+ */
+ public function checkLocationInArea($order, $data)
+ {
+ $local = (new Local())->where([ [ 'local_id', '>', 0 ] ])->field('fee_type,base_dist,base_price,grad_dist,grad_price,weight_start,weight_unit,weight_price,delivery_type,area,center')->findOrEmpty();
+ if ($local->isEmpty()) {
+ $order['error_code'] = -1;
+ $order['error_msg'] = get_lang('NOT_CONFIGURED_LOCAL_DELIVERY');
+ }
+ // 收货地址
+ $address_point = new Coordinate($data['taker_latitude'], $data['taker_longitude']);
+
+ // 判断所在区域
+ $located_in_area = null;
+ foreach ($local['area'] as $area) {
+ if ($area['area_type'] == 'radius') {
+ $center = new Coordinate($area['area_json']['center']['lat'], $area['area_json']['center']['lng']);
+ $distance = (new Vincenty())->getDistance($address_point, $center);
+ if ($distance <= $area['area_json']['radius']) {
+ $located_in_area = $area;
+ break;
+ }
+ } else {
+ $geofence = new Polygon();
+ $geofence->addPoints(array_map(function ($latlng) {
+ return new Coordinate($latlng['lat'], $latlng['lng']);
+ }, $area['area_json']['paths']));
+ if ($geofence->contains($address_point)) {
+ $located_in_area = $area;
+ break;
+ }
+ }
+ }
+ if (!$located_in_area) {
+ $order['error_code'] = -1;
+ $order['error_msg'] = get_lang('NOT_SUPPORT_DELIVERY_ADDRESS');
+ }
+ return $order;
+ }
+
+ /**
+ * 获取订单来源
+ * @return array
+ */
+ public function getOrderFrom()
+ {
+ $order_from_list = ChannelDict::getType();
+ $from_event_list = array_filter(event('OrderFromList')) ?? [];
+ foreach ($from_event_list as $item) {
+ $order_from_list = array_merge($order_from_list, $item);
+ }
+ return $order_from_list;
+ }
+
+ /**
+ * 待确定删除逻辑之后再细化
+ * @param $order_ids
+ * @return bool|void
+ */
+ public function delete($order_ids)
+ {
+
+ if (empty($order_ids)) throw new AdminException('SHOP_ORDER_NOT_FOUND');
+
+ $status_list = $this->model->field('order_id, status,order_no,create_time')->whereIn('order_id', $order_ids)->with(['orderGoods' => function ($query) {
+ $query->field(' order_id, goods_id');
+ }])->select()->toArray();
+
+ $error_order_str = '';
+ foreach ($status_list as $item) {
+ if ($item['status'] == OrderDict::CLOSE) {
+ continue;
+ }
+ $error_order_str .= $item['order_no'] . ',';
+ }
+
+ $error_order_str = rtrim($error_order_str, ',');
+ if (!empty($error_order_str)) {
+ $error_str = sprintf(get_lang('SHOP_ORDER_DELETE_STATUS_ERROR'), $error_order_str);
+ throw new AdminException($error_str);
+ }
+
+ Db::startTrans();
+ try {
+ //删除订单表
+ $this->model::destroy(function ($query) use ($order_ids) {
+ $query->where([['order_id', 'in', $order_ids]]);
+ });
+
+ //删除订单商品项
+ (new OrderGoods())::destroy(function ($query) use ($order_ids) {
+ $query->where([['order_id', 'in', $order_ids]]);
+ });
+
+ //删除订单退款
+ (new OrderRefund())::destroy(function ($query) use ($order_ids) {
+ $query->where([ [ 'order_id', 'in', $order_ids ]]);
+ });
+
+ //删除统计
+ foreach ($status_list as $value) {
+ if (!empty($value['orderGoods'])) {
+ foreach ($value['orderGoods'] as $v) {
+ CoreGoodsStatService::decStat(['goods_id' => $v['goods_id'], 'time' => $value['create_time'], 'sale_num' => 1]);
+ }
+ CoreStatService::decStat([ 'time' => $value['create_time'], 'order_num' => 1]);
+ }
+ }
+
+ Db::commit();
+ return true;
+ } catch (\Exception $e) {
+ Db::rollback();
+ throw new CommonException($e->getMessage());
+ }
+ }
+
+ public function getInfoByOrderNo($order_no)
+ {
+ return $this->model->where('order_no', $order_no)->findOrEmpty()->toArray();
+ }
+}
diff --git a/niucloud/addon/shop/app/service/admin/refund/RefundActionService.php b/niucloud/addon/shop/app/service/admin/refund/RefundActionService.php
new file mode 100644
index 000000000..0c36bed5e
--- /dev/null
+++ b/niucloud/addon/shop/app/service/admin/refund/RefundActionService.php
@@ -0,0 +1,98 @@
+model = new OrderRefund();
+ }
+
+ /**
+ * 审核退款申请
+ * @param $data ['is-agree]
+ * @return void
+ */
+ public function auditApply($data)
+ {
+ $data[ 'main_type' ] = OrderRefundLogDict::STORE;
+ $data[ 'main_id' ] = $this->uid;
+ (new CoreRefundActionService())->auditApply($data);
+ return true;
+ }
+
+ /**
+ * 审核是否确认收货
+ * @param $data
+ * @return true
+ */
+ public function auditRefundGoods($data)
+ {
+ $data[ 'main_type' ] = OrderRefundLogDict::STORE;
+ $data[ 'main_id' ] = $this->uid;
+ (new CoreRefundActionService())->auditRefundGoods($data);
+ return true;
+ }
+
+ /**
+ * 商家主动退款
+ * @param $data
+ * @return true
+ */
+ public function shopActiveRefund($data)
+ {
+ $data[ 'main_type' ] = OrderRefundLogDict::STORE;
+ $data[ 'main_id' ] = $this->uid;
+ (new CoreRefundActionService())->shopActiveRefund($data);
+ return true;
+ }
+
+ /**
+ * 获取订单可退款金额
+ * @param $data
+ * @return array
+ */
+ public function getOrderRefundMoney($data)
+ {
+ $order_goods_ids = $data[ 'order_goods_ids' ];
+ $refund_money_array = (new CoreRefundService())->getOrderRefundMoney($order_goods_ids);
+ return [
+ 'refund_money' => round($refund_money_array[ 'refund_money' ] ?? 0, 2)
+ ];
+ }
+
+ /**
+ * 商家主动关闭售后
+ * @param $order_refund_no
+ * @return void
+ */
+ public function closeRefund($order_refund_no)
+ {
+ $data[ 'main_type' ] = OrderRefundLogDict::STORE;
+ $data[ 'main_id' ] = $this->uid;
+ $data[ 'order_refund_no' ] =$order_refund_no;
+ (new CoreRefundActionService())->close($data,OrderRefundDict::SHOP_ACTIVE_CLOSE_REFUND);
+ }
+
+}
diff --git a/niucloud/addon/shop/app/service/admin/refund/RefundService.php b/niucloud/addon/shop/app/service/admin/refund/RefundService.php
new file mode 100644
index 000000000..4c1ca83b4
--- /dev/null
+++ b/niucloud/addon/shop/app/service/admin/refund/RefundService.php
@@ -0,0 +1,112 @@
+model = new OrderRefund();
+ }
+
+ /**
+ * 分页列表
+ * @param array $where
+ * @return array
+ */
+ public function getPage(array $where)
+ {
+ $field = 'refund_id, order_id, order_goods_id, order_refund_no, refund_type, reason, member_id, apply_money, money, status, create_time, transfer_time, remark, voucher, source, timeout, refund_no, delivery, shop_reason, refund_address';
+ $order = 'create_time desc';
+
+ $search_model = $this->model
+ ->where([ [ 'refund_id', '>', 0 ] ])
+ ->withSearch([ 'order_refund_no', 'status', 'create_time' ], $where)
+ ->field($field)
+ ->with(
+ [
+ 'order_goods' => function($query) {
+ $query->field('order_goods_id, order_id, member_id, goods_id, sku_id, goods_name, sku_name, goods_image, sku_image, price, num, goods_money,discount_money, is_enable_refund, goods_type')->append([ 'goods_image_thumb_small' ]);
+ },
+ 'member' => function($query) {
+ $query->field('member_id, nickname');
+ }
+ ])->order($order)->append([ 'status_name', 'refund_type_name' ]);
+ $list = $this->pageQuery($search_model);
+ return $list;
+ }
+
+ /**
+ * 详情
+ * @param int $refund_id
+ * @return array
+ */
+ public function getDetail(int $refund_id)
+ {
+ $field = 'refund_id, order_id, order_goods_id, order_refund_no, refund_type, reason, member_id, apply_money, money, status, create_time, transfer_time, remark, voucher, source, timeout, refund_no, delivery, shop_reason, refund_address';
+ $info = $this->model->where([ [ 'refund_id', '=', $refund_id ] ])->field($field)
+ ->with(
+ [
+ 'order_main' => function($query) {
+ $query->field('order_id,order_no,order_type,order_from,out_trade_no,status,member_id,ip,goods_money,delivery_money,order_money,invoice_id,create_time,pay_time,delivery_time,take_time,finish_time,close_time,delivery_type,taker_name,taker_mobile,taker_province,taker_city,taker_district,taker_address,taker_full_address,taker_longitude,taker_latitude,take_store_id,is_enable_refund,member_remark,shop_remark,close_remark,discount_money,point')
+ ->append([ 'order_from_name', 'order_type_name', 'status_name', 'delivery_type_name' ]);
+ },
+ 'order_goods' => function($query) {
+ $query->field('order_goods_id, order_id, member_id, goods_id, sku_id, goods_name, sku_name, goods_image, sku_image, price, num, goods_money, is_enable_refund, goods_type');
+ },
+ 'member' => function($query) {
+ $query->field('member_id, nickname, mobile, headimg, balance');
+ },
+ 'pay_refund' => function($query) {
+ $query->field('refund_no, type, money, create_time, refund_time')->append([ 'type_name' ]);
+ },
+ 'refund_log' => function($query) {
+ $query->field('order_refund_no, content, main_type, create_time ,main_id, type')->order("create_time desc, id desc")->append([ 'main_name', 'type_name', 'main_type_name' ]);
+ }
+ ])->append([ 'status_name', 'refund_type_name' ])->findOrEmpty()->toArray();
+
+ if (!empty($info)) {
+
+ if ($info[ 'order_main' ][ 'delivery_type' ] == DeliveryDict::STORE) {
+ $info[ 'store' ] = ( new Store() )->where([ [ 'store_id', '=', $info[ 'order_main' ][ 'take_store_id' ] ] ])
+ ->field('store_id, store_name, full_address, store_mobile, trade_time')
+ ->findOrEmpty()->toArray();
+ }
+
+ $refund_gift_list = (new CoreManjianService())->refundCheck($info);
+ if (!empty($refund_gift_list)) {
+ $gift_balance = 0;
+ foreach ($refund_gift_list as $value) {
+ if (isset($value[ 'balance' ]) && $value[ 'balance' ] > 0) {
+ $gift_balance = bcadd($gift_balance, $value[ 'balance' ], 2);
+ }
+ }
+ if ($gift_balance > 0) {
+ $info[ 'gift_balance' ] = $gift_balance;
+ }
+ }
+
+ }
+ return $info;
+ }
+
+}
diff --git a/niucloud/addon/shop/app/service/admin/shop_address/ShopAddressService.php b/niucloud/addon/shop/app/service/admin/shop_address/ShopAddressService.php
new file mode 100644
index 000000000..f4b5f0249
--- /dev/null
+++ b/niucloud/addon/shop/app/service/admin/shop_address/ShopAddressService.php
@@ -0,0 +1,148 @@
+model = new ShopAddress();
+ }
+
+ /**
+ * 获取商家地址库列表
+ * @param array $where
+ * @return array
+ */
+ public function getPage(array $where = [])
+ {
+ $field = 'id,contact_name,mobile,province_id,city_id,district_id,address,full_address,lat,lng,is_delivery_address,is_refund_address,is_default_delivery,is_default_refund';
+ $order = '';
+
+ $search_model = $this->model->where([ ['id', '>', 0] ])->withSearch([ "mobile", "full_address" ], $where)->field($field)->order($order);
+ $list = $this->pageQuery($search_model);
+ return $list;
+ }
+
+ /**
+ * 获取商家地址库信息
+ * @param int $id
+ * @return array
+ */
+ public function getInfo(int $id)
+ {
+ $field = 'id,contact_name,mobile,province_id,city_id,district_id,address,full_address,lat,lng,is_delivery_address,is_refund_address,is_default_delivery,is_default_refund';
+
+ $info = $this->model->field($field)->where([ [ 'id', '=', $id ] ])->findOrEmpty()->toArray();
+ return $info;
+ }
+
+ /**
+ * 添加商家地址库
+ * @param array $param
+ * @return mixed
+ */
+ public function add(array $param)
+ {
+ $data = [
+ 'contact_name' => $param[ 'contact_name' ],
+ 'mobile' => $param[ 'mobile' ],
+ 'province_id' => $param[ 'province_id' ],
+ 'city_id' => $param[ 'city_id' ],
+ 'district_id' => $param[ 'district_id' ],
+ 'address' => $param[ 'address' ],
+ 'full_address' => $param[ 'full_address' ],
+ 'lat' => $param[ 'lat' ],
+ 'lng' => $param[ 'lng' ],
+ 'is_delivery_address' => $param[ 'is_delivery_address' ],
+ 'is_refund_address' => $param[ 'is_refund_address' ],
+ 'is_default_delivery' => $param[ 'is_delivery_address' ] ? $param[ 'is_default_delivery' ] : 0,
+ 'is_default_refund' => $param[ 'is_refund_address' ] ? $param[ 'is_default_refund' ] : 0
+ ];
+ if ($data[ 'is_default_delivery' ]) $this->model->update([ 'is_default_delivery' => 0 ], [ [ 'is_default_delivery', '>', 0 ] ]);
+ if ($data[ 'is_default_refund' ]) $this->model->update([ 'is_default_refund' => 0 ], [ [ 'is_default_refund', '>', 0 ] ]);
+ $res = $this->model->create($data);
+ return $res->id;
+
+ }
+
+ /**
+ * 商家地址库编辑
+ * @param int $id
+ * @param array $param
+ * @return bool
+ */
+ public function edit(int $id, array $param)
+ {
+ $data = [
+ 'contact_name' => $param[ 'contact_name' ],
+ 'mobile' => $param[ 'mobile' ],
+ 'province_id' => $param[ 'province_id' ],
+ 'city_id' => $param[ 'city_id' ],
+ 'district_id' => $param[ 'district_id' ],
+ 'address' => $param[ 'address' ],
+ 'full_address' => $param[ 'full_address' ],
+ 'lat' => $param[ 'lat' ],
+ 'lng' => $param[ 'lng' ],
+ 'is_delivery_address' => $param[ 'is_delivery_address' ],
+ 'is_refund_address' => $param[ 'is_refund_address' ],
+ 'is_default_delivery' => $param[ 'is_delivery_address' ] ? $param[ 'is_default_delivery' ] : 0,
+ 'is_default_refund' => $param[ 'is_refund_address' ] ? $param[ 'is_default_refund' ] : 0
+ ];
+ if ($data[ 'is_default_delivery' ]) $this->model->update([ 'is_default_delivery' => 0 ], [ [ 'is_default_delivery', '>', 0 ] ]);
+ if ($data[ 'is_default_refund' ]) $this->model->update([ 'is_default_refund' => 0 ], [ [ 'is_default_refund', '>', 0 ] ]);
+ $this->model->where([ [ 'id', '=', $id ] ])->update($data);
+ return true;
+ }
+
+ /**
+ * 删除商家地址库
+ * @param int $id
+ * @return bool
+ */
+ public function del(int $id)
+ {
+ $model = $this->model->where([ [ 'id', '=', $id ] ])->find();
+ $res = $model->delete();
+ return $res;
+ }
+
+ /**
+ * 获取默认发货地址
+ * @return array
+ * @throws \think\db\exception\DataNotFoundException
+ * @throws \think\db\exception\DbException
+ * @throws \think\db\exception\ModelNotFoundException
+ */
+ public function getDefaultDeliveryAddress()
+ {
+ $address = $this->model->where([ [ 'is_delivery_address', '=', 1 ], [ 'is_default_delivery', '=', 1 ] ])->findOrEmpty();
+ if (!$address->isEmpty()) return $address->toArray();
+ }
+
+ public function getList()
+ {
+ $field = 'id,contact_name,mobile,province_id,city_id,district_id,address,full_address,lat,lng,is_delivery_address,is_refund_address,is_default_delivery,is_default_refund';
+ $list = $this->model->where([['is_refund_address', '=', 1] ])->field($field)->select()->toArray();
+ return $list;
+ }
+}
diff --git a/niucloud/addon/shop/app/service/api/ConfigService.php b/niucloud/addon/shop/app/service/api/ConfigService.php
new file mode 100644
index 000000000..c67dc1d6d
--- /dev/null
+++ b/niucloud/addon/shop/app/service/api/ConfigService.php
@@ -0,0 +1,47 @@
+getConfigValue('SHOP_INVOICE');
+ if (empty($config)) {
+ $config = [
+ 'is_invoice' => '2',
+ 'invoice_type' => [],
+ 'invoice_content' => []
+ ];
+ }
+ return $config;
+ }
+
+ /**
+ * 获取评价设置
+ * @return array|int[]|mixed
+ */
+ public function getEvaluateConfig()
+ {
+ return (new CoreOrderConfigService())->getEvaluateConfig();
+ }
+}
diff --git a/niucloud/addon/shop/app/service/api/cart/CartService.php b/niucloud/addon/shop/app/service/api/cart/CartService.php
new file mode 100644
index 000000000..d14734142
--- /dev/null
+++ b/niucloud/addon/shop/app/service/api/cart/CartService.php
@@ -0,0 +1,388 @@
+model = new Cart();
+ }
+
+ /**
+ * 添加购物车
+ * @param $data
+ * @return mixed
+ */
+ public function add($data)
+ {
+ $member_info = ( new CoreMemberService() )->getInfoByMemberId($this->member_id, 'status');
+
+ if (empty($member_info)) throw new ApiException('SHOP_ORDER_BUYER_NOT_FOUND');//无效的账号
+ if ($member_info[ 'status' ] == MemberDict::OFF) throw new ApiException('SHOP_ORDER_BUYER_LOCKED');//账号被锁定
+
+ $data[ 'member_id' ] = $this->member_id;
+ $info = $this->model->where([
+ [ 'member_id', '=', $data[ 'member_id' ] ],
+ [ 'goods_id', '=', $data[ 'goods_id' ] ],
+ [ 'sku_id', '=', $data[ 'sku_id' ] ],
+ ])->field('id,num')->findOrEmpty()->toArray();
+
+// $other_sku_num = $this->model->where([
+// [ 'member_id', '=', $this->member_id ],
+// [ 'goods_id', '=', $data[ 'goods_id' ] ],
+// [ 'sku_id', '<>', $data[ 'sku_id' ] ]
+// ])->sum('num');
+
+ $goods_info = ( new Goods() )->where([
+ [ 'goods_id', '=', $data[ 'goods_id' ] ],
+ ])->field('goods_id,goods_name,stock,is_limit,limit_type,max_buy,min_buy')->findOrEmpty()->toArray();
+ if (empty($goods_info)) throw new ApiException("SHOP_GOODS_NOT_EXIST");
+ // 商品加入购物车统计
+ CoreGoodsStatService::addStat([ 'goods_id' => $data[ 'goods_id' ], 'cart_num' => $data[ 'num' ] ]);
+ ( new CoreGoodsCartNumService() )->inc([ 'goods_id' => $data[ 'goods_id' ], 'cart_num' => $data[ 'num' ] ]);
+
+// $core_goods_limit_buy_service = new CoreGoodsLimitBuyService();
+ if (!empty($info)) {
+ // 存在,更新数量
+ $update = [
+ 'num' => $info[ 'num' ] + $data[ 'num' ]
+ ];
+ // 检测限购
+// $goods_info[ 'num' ] = $other_sku_num + $update[ 'num' ];
+// $error = $core_goods_limit_buy_service->checkGoodsLimitBuy($this->member_id, [ $goods_info ]);
+// if (!empty($error)) throw new ApiException($error);
+ $this->model->where([ [ 'id', '=', $info[ 'id' ] ] ])->update($update);
+ return $info[ 'id' ];
+ } else {
+ // 检测限购
+// $goods_info[ 'num' ] = $other_sku_num + $data[ 'num' ];
+// $error = $core_goods_limit_buy_service->checkGoodsLimitBuy($this->member_id, [ $goods_info ]);
+// if (!empty($error)) throw new ApiException($error);
+ // 添加
+ $res = $this->model->create($data);
+ return $res->id;
+ }
+ }
+
+ /**
+ * 编辑购物车数量
+ * @param $data
+ * @return bool
+ */
+ public function edit($data)
+ {
+ $member_info = ( new CoreMemberService() )->getInfoByMemberId($this->member_id, 'status');
+
+ if (empty($member_info)) throw new ApiException('SHOP_ORDER_BUYER_NOT_FOUND');//无效的账号
+ if ($member_info[ 'status' ] == MemberDict::OFF) throw new ApiException('SHOP_ORDER_BUYER_LOCKED');//账号被锁定
+
+ $data[ 'member_id' ] = $this->member_id;
+ $info = $this->model->where([
+ [ 'id', '=', $data[ 'id' ] ],
+ [ 'member_id', '=', $data[ 'member_id' ] ],
+ ])->field('sku_id, goods_id, num')->findOrEmpty()->toArray();
+
+ if (empty($info)) return false;
+
+ $update = [
+ 'num' => $data[ 'num' ]
+ ];
+
+ if (!empty($data[ 'sku_id' ]) && $info[ 'sku_id' ] != $data[ 'sku_id' ]) {
+ $update[ 'sku_id' ] = $data[ 'sku_id' ];
+
+ $cart_info = $this->model->where([
+ [ 'sku_id', '=', $data[ 'sku_id' ] ],
+ [ 'member_id', '=', $this->member_id ],
+ ])->field('id')->findOrEmpty()->toArray();
+
+ if (!empty($cart_info)) {
+ $this->model->where([ [ 'id', '=', $cart_info[ 'id' ] ] ])->delete();
+ }
+ }
+
+ $goods_info = ( new Goods() )->where([
+ [ 'goods_id', '=', $info[ 'goods_id' ] ],
+ ])->field('goods_id,goods_name,stock,is_limit,limit_type,max_buy,min_buy')->findOrEmpty()->toArray();
+ if (empty($goods_info)) throw new ApiException("SHOP_GOODS_NOT_EXIST");
+
+// $other_sku_num = $this->model->where([
+// [ 'member_id', '=', $this->member_id ],
+// [ 'goods_id', '=', $info[ 'goods_id' ] ],
+// [ 'sku_id', '<>', $info[ 'sku_id' ] ]
+// ])->sum('num');
+
+ // 检测限购
+// if ($data[ 'num' ] > $info['num']) {
+// $goods_info[ 'num' ] = $other_sku_num + $update[ 'num' ];
+// $error = ( new CoreGoodsLimitBuyService() )->checkGoodsLimitBuy($this->member_id, [ $goods_info ]);
+// if (!empty($error)) throw new ApiException($error);
+// }
+
+ $this->model->where([ [ 'id', '=', $data[ 'id' ] ] ])->update($update);
+
+ // 商品加入购物车统计
+ CoreGoodsStatService::addStat([ 'goods_id' => $info[ 'goods_id' ], 'cart_num' => ( $data[ 'num' ] - $info[ 'num' ] ) ]);
+ ( new CoreGoodsCartNumService() )->inc([ 'goods_id' => $info[ 'goods_id' ], 'cart_num' => ( $data[ 'num' ] - $info[ 'num' ] ) ]);
+
+ return true;
+ }
+
+ /**
+ * 购物车删除,支持批量
+ * @param $data
+ * @return bool
+ */
+ public function del($data)
+ {
+ $this->model->where([ [ 'member_id', '=', $this->member_id ],[ 'id', 'in', $data[ 'ids' ] ] ])->delete();
+ return true;
+ }
+
+ /**
+ * 清空购物车
+ * @return bool
+ */
+ public function clear()
+ {
+ $this->model->where([ [ 'member_id', '=', $this->member_id ] ])->delete();
+ return true;
+ }
+
+ /**
+ * 获取购物车列表
+ * @param $data
+ * @return array
+ */
+ public function getList($data)
+ {
+ $data[ 'member_id' ] = $this->member_id;
+ $field = 'id, member_id, goods_id, sku_id, num, status, invalid_remark';
+ $order = "create_time desc";
+ $list = $this->model->where([ [ 'id', '>', 0 ] ])->withSearch([ "member_id" ], $data)->field($field)
+ ->with([
+ 'goods' => function ($query) {
+ $query->withField('goods_id, goods_name, goods_cover, unit, stock, status, delete_time, member_discount')
+ ->append([ 'goods_cover_thumb_mid' ]);
+ },
+ 'goodsSku' => function ($query) {
+ $query->withField('sku_id,goods_id, sku_name, sku_image, sku_spec_format, price, market_price, sale_price, member_price, stock')->append([ 'sku_image_thumb_mid' ]);
+ }
+ ])->order($order)->select()->toArray();
+
+ array_multisort(array_column($list, 'id'), SORT_ASC, $list);
+ $goods_active_price_service = ( new CoreGoodsActivePriceService() );
+ foreach ($list as $k => &$v) {
+ if (!empty($v[ 'goodsSku' ])) {
+ $v[ 'goodsSku' ][ 'member_discount' ] = $v[ 'goods' ][ 'member_discount' ] ?? '';
+ //获取展示活动价格
+ $show_price_data = $goods_active_price_service->getActivePrice($v[ 'goodsSku' ], $this->member_id);
+ $v[ 'goodsSku' ][ 'show_price' ] = $show_price_data[ 'show_price' ];
+ $v[ 'goodsSku' ][ 'show_type' ] = $show_price_data[ 'show_type' ];
+ }
+ if (!empty($v[ 'goods' ])) {
+ // 限购查询当前会员已购数量
+ $has_buy = ( new CoreGoodsLimitBuyService() )->getGoodsHasBuyNumber($this->member_id, $v[ 'goods' ][ 'goods_id' ]);
+ $v[ 'goods' ][ 'has_buy' ] = $has_buy;
+ }
+ }
+ array_multisort(array_column($list, 'id'), SORT_DESC, $list);
+ return $list;
+ }
+
+ /**
+ * 获取购物车商品列表
+ * @param $data
+ * @return array
+ */
+ public function getGoodsList($data)
+ {
+ $data[ 'member_id' ] = $this->member_id;
+ $field = 'id, goods_id, sku_id, num, status, invalid_remark';
+ $order = "create_time desc";
+ $list = $this->model->where([ [ 'id', '>', 0] ])->withSearch([ "member_id" ], $data)->field($field)
+ ->with([
+ 'goods' => function ($query) {
+ $query->withField('goods_id, goods_name, goods_cover, unit, stock, status, delete_time, label_ids, member_discount')
+ ->append([ 'goods_label_name', 'goods_cover_thumb_mid' ]);
+ },
+ 'goodsSku' => function ($query) {
+ $query->withField('sku_id,goods_id, sku_name, sku_image, sku_spec_format, price, market_price, sale_price, member_price, stock')->append([ 'sku_image_thumb_mid' ]);
+ },
+ ])->order($order)->select()->toArray();
+
+
+ array_multisort(array_column($list, 'id'), SORT_ASC, $list);
+ $goods_active_price_service = ( new CoreGoodsActivePriceService() );
+ $gift_goods = [];
+ foreach ($list as $k => &$v) {
+ if (!empty($v[ 'goodsSku' ])) {
+ $v[ 'goodsSku' ][ 'member_discount' ] = $v[ 'goods' ][ 'member_discount' ] ?? '';
+ //获取展示活动价格
+ $show_price_data = $goods_active_price_service->getActivePrice($v[ 'goodsSku' ], $this->member_id);
+ $v[ 'goodsSku' ][ 'show_price' ] = $show_price_data[ 'show_price' ];
+ $v[ 'goodsSku' ][ 'show_type' ] = $show_price_data[ 'show_type' ];
+ }
+ if (!empty($v[ 'goods' ])) {
+ // 限购查询当前会员已购数量
+ $has_buy = ( new CoreGoodsLimitBuyService() )->getGoodsHasBuyNumber($this->member_id, $v[ 'goods' ][ 'goods_id' ]);
+ $v[ 'goods' ][ 'has_buy' ] = $has_buy;
+ }
+
+ $manjian_info = ( new ManjianService() )->getManjianInfo([ 'goods_id' => $v[ 'goods_id' ], 'sku_id' => $v[ 'sku_id' ], 'gift_goods' => $gift_goods ]);
+ if (!empty($manjian_info[ 'gift_goods' ])) {
+ $gift_goods = array_merge($gift_goods, $manjian_info[ 'gift_goods' ]);
+ }
+ $v[ 'manjian_info' ] = $manjian_info;
+ }
+ array_multisort(array_column($list, 'id'), SORT_DESC, $list);
+ return $list;
+ }
+
+ /**
+ * 购物车计算
+ * @param $data
+ * @return array
+ */
+ public function calculate($data)
+ {
+ //获取商品信息
+ $data = $this->getSelectGoods($data);
+ //满减
+ $data = ( new CoreManjianService() )->manjianPromotion($data, $this->member_id);
+ $promotion_money = $data[ 'promotion_money' ] ?? 0;
+ $order_money = max($data[ 'goods_money' ] - $promotion_money, 0);
+ $data[ 'order_money' ] = $order_money;
+
+ $good_list = $data[ 'goods_list' ];
+ $match_list = [];
+ foreach ($good_list as $k => $v) {
+ $match_list[ $k ][ 'goods_id' ] = $v[ 'goods_id' ];
+ $match_list[ $k ][ 'sku_id' ] = $v[ 'sku_id' ];
+ foreach ($v[ 'promotion' ] as $kk => $vv) {
+// dd($vv);
+ switch ($kk) {
+ case 'manjian':
+ foreach ($vv as $item){
+ if ($item[ 'discount_array' ][ 'level' ] >= 0) {
+ $match_list[ $k ][$kk][] = [
+ 'manjian_id' => $item[ 'manjian_id' ],
+ 'level' => $item[ 'discount_array' ][ 'level' ]
+ ];
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ return [
+ 'goods_money' => $data[ 'goods_money' ],
+ 'promotion_money' => $promotion_money,
+ 'order_money' => $order_money,
+ 'match_list' => $match_list
+ ];
+ }
+
+ /**
+ * 获取购物车商品列表信息
+ * @param $data
+ * @return mixed
+ */
+ public function getSelectGoods($data)
+ {
+ $member_id = $this->member_id;
+
+ $sku_ids = $data[ 'sku_ids' ] ?? [];
+ $sku_id_list = array_column($sku_ids, 'sku_id');
+ $sku_num_list = array_column($sku_ids, 'num', 'sku_id');
+ //组装商品列表
+ $field = 'goodsSku.sku_id, goodsSku.sku_name, goodsSku.price, goodsSku.stock, goodsSku.goods_id, cart.id as cart_id,cart.num, goodsSku.member_price, goods.member_discount, goodsSku.sale_price';
+ $condition = [
+ [ 'goodsSku.sku_id', 'in', $sku_id_list ],
+ ];
+ $goods_list = ( new GoodsSku() )
+ ->alias('goodsSku')
+ ->field($field)
+ ->where($condition)
+ ->join('shop_cart cart', 'cart.sku_id = goodsSku.sku_id and cart.member_id = ' . $member_id)
+ ->join('shop_goods goods', 'goods.goods_id = goodsSku.goods_id')
+ ->with(['goods'])
+ ->select()
+ ->toArray();
+
+ $data[ 'goods_num' ] = 0;
+ $data[ 'goods_money' ] = 0;
+ $data[ 'goods_list' ] = [];
+ $data[ 'coupon_money' ] = 0; //优惠券金额
+ $data[ 'promotion_money' ] = 0; //优惠金额
+ $goods_active_price_service = ( new CoreGoodsActivePriceService() );
+ if (!empty($goods_list)) {
+ foreach ($goods_list as $k => $v) {
+ //获取展示活动价格
+ $v['member_discount'] = $v['goods']['member_discount'];
+ $show_price_data = $goods_active_price_service->getActivePrice($v, $this->member_id);
+ $v[ 'show_price' ] = $show_price_data[ 'show_price' ];
+ $v[ 'show_type' ] = $show_price_data[ 'show_type' ];
+ $item_num = $sku_num_list[ $v[ 'sku_id' ] ];
+ $price = $v[ 'show_price' ];
+ $v[ 'goods_money' ] = $price * $item_num;
+ $v[ 'real_goods_money' ] = $v[ 'goods_money' ];
+ $v[ 'promotion' ] = [];
+
+ $data[ 'goods_num' ] += $item_num;
+ $data[ 'goods_money' ] += $v[ 'goods_money' ];
+ $data[ 'goods_list' ][] = $v;
+ }
+ }
+ return $data;
+ }
+
+ /**
+ * 获取购物车数量
+ * @param $data
+ * @return float
+ */
+ public function getSum($data)
+ {
+ $condition = [
+ [ 'member_id', '=', $this->member_id ],
+ ];
+ if (!empty($data[ 'goods_id' ])) {
+ $condition[] = [ 'goods_id', '=', $data[ 'goods_id' ] ];
+ }
+ return $this->model->where($condition)->sum('num');
+ }
+
+}
diff --git a/niucloud/addon/shop/app/service/api/goods/AttrService.php b/niucloud/addon/shop/app/service/api/goods/AttrService.php
new file mode 100644
index 000000000..9f76f0cb3
--- /dev/null
+++ b/niucloud/addon/shop/app/service/api/goods/AttrService.php
@@ -0,0 +1,59 @@
+model = new Attr();
+ }
+
+ /**
+ * 获取商品参数列表
+ * @param array $where
+ * @return array
+ */
+ public function getPage(array $where = [])
+ {
+ $field = 'attr_id,attr_name,sort';
+ $order = '';
+
+ $search_model = $this->model->where([ [ 'attr_id', ">", 0 ] ])->withSearch([ "attr_id", "attr_name", "attr_value_format", "sort" ], $where)->field($field)->order($order);
+ $list = $this->pageQuery($search_model);
+ return $list;
+ }
+
+ /**
+ * 获取商品参数信息
+ * @param int $id
+ * @return array
+ */
+ public function getInfo(int $id)
+ {
+ $field = 'attr_id,attr_name,attr_value_format,sort';
+
+ $info = $this->model->field($field)->where([ [ 'attr_id', "=", $id ] ])->findOrEmpty()->toArray();
+ return $info;
+ }
+
+}
diff --git a/niucloud/addon/shop/app/service/api/goods/ConfigService.php b/niucloud/addon/shop/app/service/api/goods/ConfigService.php
new file mode 100644
index 000000000..476ed677f
--- /dev/null
+++ b/niucloud/addon/shop/app/service/api/goods/ConfigService.php
@@ -0,0 +1,41 @@
+core__goods_config_service = new CoreGoodsConfigService();
+ }
+
+ /**
+ * 获取商品搜索配置
+ * @return array
+ */
+ public function getSearchConfig()
+ {
+ return $this->core__goods_config_service->getSearchConfig();
+ }
+
+}
diff --git a/niucloud/addon/shop/app/service/api/goods/EvaluateService.php b/niucloud/addon/shop/app/service/api/goods/EvaluateService.php
new file mode 100644
index 000000000..aaccddfc1
--- /dev/null
+++ b/niucloud/addon/shop/app/service/api/goods/EvaluateService.php
@@ -0,0 +1,134 @@
+model = new Evaluate();
+ }
+
+ /**
+ * 获取商品评价列表
+ * @param array $where
+ * @return array
+ */
+ public function getPage(array $where = [])
+ {
+ $field = 'evaluate_id,order_id,order_goods_id,goods_id,member_id,member_name,member_head,content,images,is_anonymous,scores,is_audit,explain_first,create_time,topping,update_time';
+ $order = 'topping desc,update_time desc,create_time desc';
+ $search_model = $this->model->where([ [ 'is_audit', 'in', [ EvaluateDict::AUDIT_NO, EvaluateDict::AUDIT_ADOPT ] ] ])->withSearch([ "goods_id", "scores" ], $where)->field($field)->order($order)->append([ 'image_mid' ]);
+ $list = $this->pageQuery($search_model);
+ return $list;
+ }
+
+ /**
+ * 获取商品评价信息
+ * @param int $id
+ * @return array
+ */
+ public function getInfo(int $id)
+ {
+ $field = 'evaluate_id,order_id,order_goods_id,goods_id,member_id,member_name,member_head,content,images,is_anonymous,scores,is_audit,explain_first,create_time';
+ $info = $this->model->field($field)->where([ [ 'evaluate_id', '=', $id ] ])->append([ 'image_mid', 'image_big' ])->findOrEmpty()->toArray();
+ return $info;
+ }
+
+ /**
+ * 添加商品评价
+ * @param array $data
+ * @return mixed
+ */
+ public function add(array $data)
+ {
+
+ $member_info = ( new Member() )->where([ [ 'member_id', '=', $this->member_id ] ])->field('nickname, headimg')->findOrEmpty()->toArray();
+ if (empty($member_info)) throw new CommonException();
+
+ $config = ( new CoreOrderConfigService() )->getEvaluateConfig();
+
+ foreach ($data[ 'evaluate_array' ] as $key => $val) {
+ $params = $val;
+ $params[ 'member_id' ] = $this->member_id;
+ $params[ 'member_name' ] = $member_info[ 'nickname' ];
+ $params[ 'member_head' ] = $member_info[ 'headimg' ];
+ $params[ 'is_audit' ] = $config[ 'evaluate_is_to_examine' ] == 1 ? 1 : 0;
+ ( new CoreGoodsEvaluateService )->addEvaluate($params);
+ }
+
+ return true;
+ }
+
+ /**
+ * 获取商品评价统计
+ * @param $goods_id
+ * @return mixed
+ * @throws \think\db\exception\DbException
+ */
+ public function getCount($goods_id)
+ {
+ $data[ 'good_evaluate' ] = $this->model->where([ [ 'goods_id', '=', $goods_id ], [ 'scores', 'in', [ 4, 5 ] ], [ 'is_audit', 'in', [ EvaluateDict::AUDIT_NO, EvaluateDict::AUDIT_ADOPT ] ] ])->count();
+ $data[ 'centre_evaluate' ] = $this->model->where([ [ 'goods_id', '=', $goods_id ], [ 'scores', 'in', [ 2, 3 ] ], [ 'is_audit', 'in', [ EvaluateDict::AUDIT_NO, EvaluateDict::AUDIT_ADOPT ] ] ])->count();
+ $data[ 'wanting_centre_evaluate' ] = $this->model->where([ [ 'goods_id', '=', $goods_id ], [ 'scores', 'in', [ 1 ] ], [ 'is_audit', 'in', [ EvaluateDict::AUDIT_NO, EvaluateDict::AUDIT_ADOPT ] ] ])->count();
+ return $data;
+ }
+
+ /**
+ * 详情页展示评价
+ * @param $goods_id
+ * @return array
+ * @throws \think\db\exception\DataNotFoundException
+ * @throws \think\db\exception\DbException
+ * @throws \think\db\exception\ModelNotFoundException
+ */
+ public function getList($goods_id)
+ {
+ $data = [];
+ $field = 'evaluate_id,order_id,order_goods_id,goods_id,member_id,member_name,member_head,content,images,is_anonymous,scores,is_audit,explain_first,create_time,topping,update_time';
+ $order = 'topping desc,update_time desc,create_time desc';
+ $data[ 'list' ] = $this->model->field($field)->where([ [ 'goods_id', '=', $goods_id ], [ 'is_audit', 'in', [ EvaluateDict::AUDIT_NO, EvaluateDict::AUDIT_ADOPT ] ] ])->limit(3)->order($order)->append([ 'image_mid' ])->select()->toArray();
+ $data[ 'count' ] = $this->model->where([ [ 'goods_id', '=', $goods_id ], [ 'is_audit', 'in', [ EvaluateDict::AUDIT_NO, EvaluateDict::AUDIT_ADOPT ] ] ])->count();
+
+ return $data;
+ }
+
+ /**
+ * 获取评价详情
+ * @param $order_id
+ */
+ public function getDetail($order_id)
+ {
+ $field = 'evaluate_id,order_id,order_goods_id,goods_id,member_id,member_name,member_head,content,images,is_anonymous,scores,is_audit,explain_first,create_time';
+ $list = $this->model->field($field)->where([ [ 'order_id', '=', $order_id ] ])->with([
+ 'order_goods' => function($query) {
+ $query->field('order_goods_id, goods_name, sku_name, goods_image, num, price')->append([ 'goods_image_thumb_mid' ]);
+ }
+ ])->append([ 'image_mid', 'image_big' ])->select()->toArray();
+ return $list;
+ }
+}
diff --git a/niucloud/addon/shop/app/service/api/goods/GoodsBrowseService.php b/niucloud/addon/shop/app/service/api/goods/GoodsBrowseService.php
new file mode 100644
index 000000000..c5e59d41e
--- /dev/null
+++ b/niucloud/addon/shop/app/service/api/goods/GoodsBrowseService.php
@@ -0,0 +1,102 @@
+model = new Browse();
+ }
+
+ /**
+ * 查询足迹
+ * @param $data
+ * @return array
+ * @throws \think\db\exception\DbException
+ */
+ public function getMemberGoodsBrowse($data)
+ {
+ $field = 'member_id,browse_time,goods_id,sku_id';
+ $start_time = isset($data[ 'date' ][ 0 ]) ? strtotime($data[ 'date' ][ 0 ]) : 0;
+ $end_time = isset($data[ 'date' ][ 1 ]) ? strtotime($data[ 'date' ][ 1 ]) : time();
+
+ $search_model = $this->model->field($field)->where([ [ 'member_id', '=', $this->member_id ], [ 'goods.delete_time', '=', 0 ] ])
+ ->whereBetweenTime('browse_time', $start_time, $end_time)
+ ->withJoin([ 'goods' => [ 'goods_id', 'goods_name', 'goods_cover', 'sale_num', 'virtual_sale_num', 'status', 'member_discount' ] ])
+ ->with([ 'goodsSku' ])
+ ->order('browse_time desc');
+ $list = $this->pageQuery($search_model);
+ if (!empty($list[ 'data' ])) {
+ $goods_active_price_service = (new CoreGoodsActivePriceService());
+ foreach ($list[ 'data' ] as &$v) {
+ $v[ 'member_discount' ] = $v[ 'goods' ][ 'member_discount' ] ?? '';
+ //获取展示活动价格
+ $show_price_data = $goods_active_price_service->getActivePrice($v, $this->member_id);
+ $v[ 'show_price' ] = $show_price_data[ 'show_price' ];
+ $v[ 'show_type' ] = $show_price_data[ 'show_type' ];
+ $v[ 'browse_time_str' ] = strtotime($v[ 'browse_time' ]);
+ }
+ }
+
+ return $list;
+ }
+
+ /**
+ * 添加足迹
+ */
+ public function addGoodsBrowse($data)
+ {
+ $goods_info = ( new Goods() )->where([ [ 'goods_id', '=', $data[ 'goods_id' ] ], [ 'delete_time', '=', 0 ] ])->field('goods_id')->findOrEmpty()->toArray();
+ if (empty($goods_info)) throw new CommonException('SHOP_GOODS_NOT_EXIST');//商品不存在
+ $sku_id = ( new GoodsSku() )->where([ [ 'goods_id', '=', $data[ 'goods_id' ] ], [ 'is_default', '=', 1 ] ])->value('sku_id');
+ $data = array_merge($data, $goods_info);
+ $data[ 'member_id' ] = $this->member_id;
+ $data[ 'browse_time' ] = time();
+ $data[ 'sku_id' ] = $sku_id;
+ $info = $this->model->where([
+ [ 'member_id', '=', $data[ 'member_id' ] ],
+ [ 'goods_id', '=', $data[ 'goods_id' ] ],
+ ])->findOrEmpty();
+ if ($info->isEmpty()) {
+ $this->model->create($data);
+ CoreGoodsStatService::addStat([ 'goods_id' => $data[ 'goods_id' ], 'goods_visit_member_count' => 1 ]);
+ } else {
+ $info->save([
+ 'browse_time' => $data[ 'browse_time' ]
+ ]);
+ }
+ return true;
+ }
+
+ /**
+ * 删除足迹
+ */
+ public function deleteGoodsBrowse($data)
+ {
+ $this->model->where([ [ 'goods_id', 'in', $data[ 'goods_ids' ] ], [ 'member_id', '=', $this->member_id ] ])->delete();
+ return true;
+ }
+
+}
diff --git a/niucloud/addon/shop/app/service/api/goods/GoodsCategoryService.php b/niucloud/addon/shop/app/service/api/goods/GoodsCategoryService.php
new file mode 100644
index 000000000..201284430
--- /dev/null
+++ b/niucloud/addon/shop/app/service/api/goods/GoodsCategoryService.php
@@ -0,0 +1,61 @@
+model = new Category();
+ }
+
+ /**
+ * 查询商品分类树结构
+ * @param string $field
+ * @param string $order
+ * @return array
+ */
+ public function getTree()
+ {
+ return ( new CoreGoodsCategoryService() )->getTree([ [ 'is_show', '=', 1 ] ], 'category_id,category_name,image,level,pid,category_full_name');
+ }
+
+ /**
+ * 获取商品分类配置
+ * @return array
+ */
+ public function getGoodsCategoryConfig()
+ {
+ return ( new CoreGoodsCategoryService() )->getGoodsCategoryConfig();
+ }
+
+ /**
+ * 获取商品分类列表
+ * @param array $where
+ * @param string $field
+ * @return array
+ */
+ public function getList(array $where = [], $field = 'category_id,category_name,image,level,pid,category_full_name')
+ {
+ $order = 'sort desc,create_time desc';
+ return $this->model->where([ [ 'is_show', '=', 1 ] ])->withSearch([ "category_name", 'level', 'category_id', 'pid' ], $where)->field($field)->order($order)->select()->toArray();
+ }
+
+}
diff --git a/niucloud/addon/shop/app/service/api/goods/GoodsCollectService.php b/niucloud/addon/shop/app/service/api/goods/GoodsCollectService.php
new file mode 100644
index 000000000..b72ece9cd
--- /dev/null
+++ b/niucloud/addon/shop/app/service/api/goods/GoodsCollectService.php
@@ -0,0 +1,116 @@
+model = new GoodsCollect();
+ }
+
+ /**
+ * 商品收藏列表
+ */
+ public function getMemberGoodsCollectList()
+ {
+ $search_model = $this->model->where([ [ 'member_id', '=', $this->member_id ],['goods.delete_time','=',0] ])
+ ->withJoin(['goods'=> [ 'goods_id', 'goods_name', 'goods_cover', 'status', 'member_discount']])
+ ->with(['goodsSku' ])
+ ->append([ 'goods_cover_thumb_mid' ])
+ ->order('create_time desc');
+ $list = $this->pageQuery($search_model);
+
+ if (!empty($list['data'])){
+ $goods_active_price_service = (new CoreGoodsActivePriceService());
+ foreach ($list['data'] as &$v){
+ $v[ 'member_discount' ] = $v[ 'goods' ][ 'member_discount' ] ?? '';
+ //获取展示活动价格
+ $show_price_data = $goods_active_price_service->getActivePrice($v, $this->member_id);
+ $v[ 'show_price' ] = $show_price_data[ 'show_price' ];
+ $v[ 'show_type' ] = $show_price_data[ 'show_type' ];
+ }
+ }
+ return $list;
+ }
+
+ /**
+ * 商品添加收藏
+ */
+ public function addGoodsCollect($data)
+ {
+ $data[ 'member_id' ] = $this->member_id;
+ $info = $this->model->where([
+ [ 'member_id', '=', $data[ 'member_id' ] ],
+ [ 'goods_id', '=', $data[ 'goods_id' ] ],
+ ])->findOrEmpty()->toArray();
+
+ $goods_info = ( new Goods() )->where([
+ [ 'goods_id', '=', $data[ 'goods_id' ] ],
+ ])->findOrEmpty()->toArray();
+ if (empty($goods_info)) throw new ApiException("SHOP_GOODS_NOT_EXIST");
+
+ if (!empty($info)) {
+ throw new CommonException('MEMBER_ALREADY_COLLECT');//已收藏
+ } else {
+ // 添加
+ $data[ 'create_time' ] = time();
+ $res = $this->model->create($data);
+
+ // 商品收藏统计
+ CoreGoodsStatService::addStat([ 'goods_id' => $data[ 'goods_id' ], 'collect_num' => 1 ]);
+ ( new CoreGoodsCollectNumService() )->inc([ 'goods_id' => $data[ 'goods_id' ], 'collect_num' => 1 ]);
+ return $res->id;
+ }
+ }
+
+ /**
+ * 商品取消收藏
+ */
+ public function cancelGoodsCollect($data)
+ {
+ $res = $this->model->where([ [ 'goods_id', 'in', $data[ 'goods_ids' ] ], [ 'member_id', '=', $this->member_id ] ])->delete();
+ // 商品收藏统计
+ foreach ($data[ 'goods_ids' ] as $value) {
+ $goods_info = ( new Goods() )->where([
+ [ 'goods_id', '=', $value ]
+ ])->findOrEmpty()->toArray();
+ if (empty($goods_info)) continue;
+
+ $stat_data = [
+ 'date' => date('Y-m-d', time()),
+ 'date_time' => strtotime(date('Y-m-d', time())),
+ 'goods_id' => $value,
+ ];
+ $collect_num = ( new Stat() )->where($stat_data)->value('collect_num');
+ if ($collect_num > 0) {
+ CoreGoodsStatService::addStat([ 'goods_id' => $value, 'collect_num' => -1 ]);
+ }
+ ( new CoreGoodsCollectNumService() )->inc([ 'goods_id' => $value, 'collect_num' => -1 ]);
+ }
+ return $res;
+ }
+}
diff --git a/niucloud/addon/shop/app/service/api/goods/GoodsService.php b/niucloud/addon/shop/app/service/api/goods/GoodsService.php
new file mode 100644
index 000000000..2c9b19a66
--- /dev/null
+++ b/niucloud/addon/shop/app/service/api/goods/GoodsService.php
@@ -0,0 +1,645 @@
+model = new Goods();
+ }
+
+ /**
+ * 获取商品列表
+ * @param array $where
+ * @return array
+ */
+ public function getPage(array $where = [])
+ {
+ $field = 'goods_id,goods_name,sub_title,goods_type,goods_cover,unit,sale_num + goods.virtual_sale_num as sale_num,is_limit,limit_type,max_buy,min_buy,member_discount,virtual_receive_type,label_ids,brand_id,stock';
+
+ $sku_where = [
+ [ 'goodsSku.is_default', '=', 1 ],
+ [ 'goods.is_gift', '=', GoodsDict::NOT_IS_GIFT ],
+ [ 'status', '=', 1 ]
+ ];
+
+ if (!empty($where[ 'keyword' ])) {
+ $sku_where[] = [ 'goods_name|sub_title', 'like', '%' . $where[ 'keyword' ] . '%' ];
+ }
+
+ if (!empty($where[ 'start_price' ]) && !empty($where[ 'end_price' ])) {
+ $money = [ $where[ 'start_price' ], $where[ 'end_price' ] ];
+ sort($money);
+ $sku_where[] = [ 'goodsSku.price', 'between', $money ];
+ } else if (!empty($where[ 'start_price' ])) {
+ $sku_where[] = [ 'goodsSku.price', '>=', $where[ 'start_price' ] ];
+ } else if (!empty($where[ 'end_price' ])) {
+ $sku_where[] = [ 'goodsSku.price', '<=', $where[ 'end_price' ] ];
+ }
+
+ // 查询优惠券包括的id
+ if (!empty($where[ 'coupon_id' ])) {
+ $coupon_goods_model = new CouponGoods();
+ $coupon_list = $coupon_goods_model->where([
+ [ 'coupon_id', '=', $where[ 'coupon_id' ] ]
+ ])->field('goods_id,category_id')->select()->toArray();
+ if (!empty($coupon_list)) {
+ $goods_ids = array_values(array_filter(array_column($coupon_list, 'goods_id')));
+ $category_ids = array_values(array_filter(array_column($coupon_list, 'category_id')));
+ if (!empty($goods_ids)) {
+ $sku_where[] = [ 'goods.goods_id', 'in', $goods_ids ];
+ } elseif (!empty($category_ids)) {
+ $like_arr = [];
+ foreach ($category_ids as $k => $v) {
+ $like_arr[] = "%" . $v . "%";
+ }
+ $sku_where[] = [ 'goods_category', "like", $like_arr, 'or' ];
+ }
+ }
+ }
+
+ // 参数过滤
+ if (!empty($where[ 'order' ]) && in_array($where[ 'order' ], [ 'sale_num', 'price' ])) {
+ $order = $where[ 'order' ] . ' ' . $where[ 'sort' ];
+ } else {
+ $sort_config = ( new CoreGoodsConfigService() )->getSortConfig();
+ if ($sort_config[ 'sort_column' ] == 'sale_price') {
+ $sort_config[ 'sort_column' ] = 'goodsSku.sale_price';
+ }
+ $order = $sort_config[ 'sort_column' ] . ' ' . $sort_config[ 'sort_type' ];
+ }
+
+ $search_model = $this->model
+ ->withSearch([ "brand_id", "goods_category", "label_ids", 'service_ids' ], $where)
+ ->field($field)
+ ->withJoin([
+ 'goodsSku' => [ 'sku_id', 'sku_name', 'sku_image', 'sku_no', 'goods_id', 'sku_spec_format', 'price', 'market_price', 'sale_price', 'stock', 'weight', 'volume', 'member_price' ]
+ ])
+ ->where($sku_where)->order($order)->append([ 'goods_cover_thumb_small','goods_cover_thumb_mid', 'goods_label_name', 'goods_brand' ]);
+ $list = $this->pageQuery($search_model);
+ $goods_active_price_service = ( new CoreGoodsActivePriceService() );
+ foreach ($list[ 'data' ] as $k => &$v) {
+ if (!empty($v[ 'goodsSku' ])) {
+ $v[ 'goodsSku' ][ 'member_discount' ] = $v[ 'member_discount' ];
+ $list_show_price = $goods_active_price_service->getShowPrice($v[ 'goodsSku' ],$this->member_id);
+ $v[ 'goodsSku' ][ 'show_price' ] = $list_show_price[ 'show_price' ];
+ $v[ 'goodsSku' ][ 'show_type' ] = $list_show_price[ 'show_type' ];
+ }
+ // 限购查询当前会员已购数量
+ $has_buy = ( new CoreGoodsLimitBuyService() )->getGoodsHasBuyNumber($this->member_id, $v[ 'goods_id' ]);
+ $v[ 'has_buy' ] = $has_buy;
+ }
+ return $list;
+ }
+
+ /**
+ * 常规调用获取商品列表
+ * @param array $where
+ * @return array
+ */
+ public function getGoodsList(array $where = [])
+ {
+ $field = 'goods_id,goods_name,sub_title,goods_category,goods_type,goods_cover,unit,status,sale_num + goods.virtual_sale_num as sale_num,member_discount,is_discount';
+
+ $sku_where = [
+ [ 'goodsSku.is_default', '=', 1 ],
+ [ 'goods.is_gift', '=', GoodsDict::NOT_IS_GIFT ],
+ [ 'status', '=', 1 ]
+ ];
+
+ if (!empty($where[ 'goods_ids' ])) {
+ $sku_where[] = [ 'goods.goods_id', 'in', $where[ 'goods_ids' ] ];
+ }
+
+ // 参数过滤
+ if (!empty($where[ 'order' ]) && in_array($where[ 'order' ], [ 'sale_num', 'price' ])) {
+ $order = $where[ 'order' ] . ' desc';
+ } else {
+ $order = 'sort desc,create_time desc';
+ }
+
+ $list = $this->model
+ ->withSearch([ 'goods_category', 'label_ids', 'service_ids' ], $where)
+ ->field($field)
+ ->withJoin([ 'goodsSku' ])
+ ->where($sku_where)->order($order)->append([ 'goods_type_name', 'goods_cover_thumb_small', 'goods_cover_thumb_mid' ])
+ ->select()->toArray();
+
+ if (!empty($list)){
+ $goods_active_price_service = (new CoreGoodsActivePriceService());
+ foreach ($list as $k => &$v) {
+ if (!empty($v[ 'goodsSku' ])) {
+ $v[ 'goodsSku' ][ 'member_discount' ] = $v[ 'member_discount' ];
+ $list_show_price = $goods_active_price_service->getShowPrice($v[ 'goodsSku' ], $this->member_id);
+ $v[ 'goodsSku' ][ 'show_price' ] = $list_show_price[ 'show_price' ];
+ $v[ 'goodsSku' ][ 'show_type' ] = $list_show_price[ 'show_type' ];
+ }
+ }
+ }
+
+ return $list;
+ }
+
+ /**
+ * 获取商品详情
+ * @param array $data
+ * @return array
+ */
+ public function getDetail(array $data)
+ {
+ $sku_id = $data[ 'sku_id' ];
+ $goods_id = $data[ 'goods_id' ];
+ if (!empty($goods_id)) {
+ $goods_info = ( new Goods() )->where([[ 'goods_id', '=', $goods_id ], [ 'delete_time', '=', 0 ] ])->count();
+ if (empty($goods_info)) throw new CommonException('SHOP_GOODS_NOT_EXIST');//商品不存在
+ }
+
+ $goods_sku_model = new GoodsSku();
+
+ if (empty($sku_id) && !empty($goods_id)) {
+ // 查询默认规格项
+ $default_sku_info = $goods_sku_model->where([ [ 'goods_id', '=', $goods_id ], [ 'is_default', '=', 1 ] ], 'sku_id')
+ ->field('sku_id')->findOrEmpty()->toArray();
+ if (!empty($default_sku_info)) {
+ $sku_id = $default_sku_info[ 'sku_id' ];
+ }
+ }
+
+ $field = 'sku_id, sku_name, sku_image, sku_no, goods_id, sku_spec_format, price, market_price, sale_price, stock, weight, volume, sale_num, is_default,member_price';
+
+ $info = $goods_sku_model->where([ [ 'sku_id', '=', $sku_id ] ])
+ ->field($field)
+ ->with([
+ 'goods' => function ($query) {
+ $query->withField('goods_id, goods_name, goods_type, sub_title, goods_cover, goods_category, goods_image,goods_video,goods_desc,brand_id,label_ids,service_ids, unit, stock, sale_num + virtual_sale_num as sale_num, is_limit,limit_type,max_buy,min_buy,status,delivery_type,attr_ids,attr_format,member_discount,is_discount,poster_id,virtual_receive_type,is_gift,form_id,diy_detail_id')
+ ->append([ 'goods_type_name', 'goods_cover_thumb_mid', 'delivery_type_list', 'goods_image_thumb_small', 'goods_image_thumb_mid', 'goods_image_thumb_big', 'goods_brand' ]);
+ },
+ // 商品规格列表
+ 'skuList' => function ($query) {
+ $query->field('sku_id, sku_name, sku_image, sku_no, goods_id, sku_spec_format, price, market_price, sale_price, stock, weight, volume, is_default,member_price');
+ },
+ // 商品规格项/规格值列表
+ 'goodsSpec' => function ($query) {
+ $query->field('spec_id, goods_id, spec_name, spec_values');
+ },
+ ])
+ ->append([ 'sku_image_thumb_small', 'sku_image_thumb_mid', 'sku_image_thumb_big' ])
+ ->findOrEmpty()->toArray();
+ if (!empty($info) && !empty($info[ 'goods' ])) {
+ $info[ 'type' ] = $data[ 'type' ] ?? '';
+
+ $goods_active_price_service = ( new CoreGoodsActivePriceService() );
+ //获取展示信息(价格 标签)
+ $info[ 'member_discount' ] = $info[ 'goods' ][ 'member_discount' ] ?? '';
+ $detail_show_price = $goods_active_price_service->getShowPrice($info, $this->member_id);
+ $info[ 'show_price' ] = $detail_show_price[ 'show_price' ];
+ $info[ 'show_type' ] = $detail_show_price[ 'show_type' ];
+ //组装数据
+ if (!empty($info[ 'skuList' ])) {
+ foreach ($info[ 'skuList' ] as &$value) {
+ $value[ 'type' ] = $data[ 'type' ] ?? '';
+ $value[ 'member_discount' ] = $info[ 'goods' ][ 'member_discount' ] ?? '';
+ $list_show_price = $goods_active_price_service->getShowPrice($value, $this->member_id);
+ $value[ 'show_price' ] = $list_show_price[ 'show_price' ];
+ $value[ 'show_type' ] = $list_show_price[ 'show_type' ];
+ }
+ }
+
+ if (!empty($info[ 'goods' ][ 'service_ids' ])) {
+ // 商品服务
+ $info[ 'service' ] = $this->getGoodsService($info[ 'goods' ][ 'service_ids' ]);
+ }
+ if (!empty($info[ 'goods' ][ 'label_ids' ])) {
+ // 商品标签
+ $info[ 'label_info' ] = $this->getGoodsLabel($info[ 'goods' ][ 'label_ids' ]);
+ }
+// if ($info[ 'show_type' ] == GoodsDict::DISCOUNT_PRICE) {
+ // 参与限时折扣,查询活动信息
+ if ($info[ 'goods' ][ 'is_discount' ] == 1) {
+ $discount_service = new DiscountService();
+ $info[ 'discount_info' ] = $discount_service->getInfoByGoods($info[ 'goods_id' ]);
+ if (!empty($info[ 'discount_info' ])) {
+ $info[ 'discount_info' ][ 'active' ][ 'start_time' ] = strtotime($info[ 'discount_info' ][ 'active' ][ 'start_time' ]);
+ $info[ 'discount_info' ][ 'active' ][ 'end_time' ] = strtotime($info[ 'discount_info' ][ 'active' ][ 'end_time' ]);
+ $info[ 'type' ] = ActiveDict::DISCOUNT;
+ }
+ } else {
+ $info[ 'type' ] = '';
+ $info[ 'type_name' ] = '';
+ }
+// }
+
+ //新人价
+ if (!empty($data[ 'type' ]) && $data[ 'type' ] == ActiveDict::NEWCOMER_DISCOUNT) {
+ // 查询新人价
+ $newcomer_service = new NewcomerService();
+ if ($newcomer_service->checkIfNewcomer()) {
+ $newcomer_info = $newcomer_service->getNewcomerInfo($info[ 'goods_id' ], $info[ 'sku_id' ]);
+ if (!empty($newcomer_info)) {
+ $info[ 'newcomer_price' ] = $newcomer_info[ 'newcomer_price' ];
+ $info[ 'newcomer_desc' ] = $newcomer_info[ 'newcomer_desc' ];
+ $info[ 'is_newcomer' ] = 1;
+ $info[ 'type' ] = ActiveDict::NEWCOMER_DISCOUNT;
+ }
+ $newcomer_service->getNewcomerPriceByList($info[ 'skuList' ]);
+ } else {
+ $info[ 'is_newcomer' ] = 0;
+ $info[ 'type' ] = '';
+ $info[ 'type_name' ] = '';
+ }
+ }
+
+ if (!empty($this->member_id)) {
+ $info[ 'goods' ][ 'is_collect' ] = $this->getGoodsIsCollect($info[ 'goods_id' ]);
+ // 限购查询当前会员已购数量
+ $has_buy = ( new CoreGoodsLimitBuyService() )->getGoodsHasBuyNumber( $this->member_id, $info[ 'goods' ][ 'goods_id' ]);
+ $info[ 'goods' ][ 'has_buy' ] = $has_buy;
+ } else {
+ $info[ 'goods' ][ 'has_buy' ] = 0;
+ $info[ 'goods' ][ 'is_collect' ] = 0;
+ }
+
+ $info[ 'type_name' ] = '';
+ if (!empty($info[ 'type' ])) {
+ $info[ 'type_name' ] = ActiveDict::getClass($info[ 'type' ]); // 查询来源活动类型
+ }
+
+ //查询评价设置是否显示
+ $core_order_config_service = new CoreOrderConfigService();
+ $evaluate_config = $core_order_config_service->getEvaluateConfig();
+ $info[ 'evaluate_is_show' ] = $evaluate_config[ 'evaluate_is_show' ];
+
+ // 商品统计-浏览次数
+ CoreGoodsStatService::addStat([ 'goods_id' => $info[ 'goods' ][ 'goods_id' ], 'access_num' => 1 ]);
+ ( new CoreGoodsAccessNumService() )->inc([ 'goods_id' => $info[ 'goods' ][ 'goods_id' ], 'access_num' => 1 ]);
+
+ // 种草秀数据查询
+ $info[ 'sow_show_list' ] = event('SowShowData', [ 'relate_id' => $info[ 'goods_id' ], 'relate_type' => 'shop', 'limit' => 3 ])[ 0 ] ?? [];
+
+ //自定义详情模版
+ $info[ 'diy_detail_info' ] = ( new DiyService() )->getInfo([ 'id' => $info[ 'goods' ][ 'diy_detail_id' ], 'name' => 'DIY_SHOP_GOODS_DETAIL' ]);
+
+ //获取商品主图第一张图片宽高
+ $first_goods_image = explode(',',$info['goods']['goods_image'])[0] ?? '';
+ $info['goods']['image_size'] = ['width' => '', 'height' => ''];
+ if (!empty($first_goods_image)){
+ $goods_image_size = getimagesize(get_file_url($first_goods_image));
+ $info['goods']['image_size']['width'] = $goods_image_size[0] ?? '';
+ $info['goods']['image_size']['height'] = $goods_image_size[1] ?? '';
+ }
+ }
+
+ return $info;
+ }
+
+ public function getGoodsService($service_ids) : array
+ {
+ $service = ( new Service() )
+ ->where([
+ [ 'service_id', 'in', $service_ids ]
+ ])
+ ->field('service_id, service_name, image, desc')
+ ->select()
+ ->toArray();
+ return $service;
+ }
+
+
+ public function getGoodsLabel($label_ids) : array
+ {
+ $goods_label_model = new Label();
+ $label_info = $goods_label_model
+ ->where([
+ [ 'label_id', 'in', $label_ids ],
+ [ 'status', '=', 1 ]
+ ])
+ ->field('label_id, label_name, memo,style_type,color_json,icon')
+ ->order('sort desc,label_id desc')
+ ->select()
+ ->toArray();
+ return $label_info;
+ }
+
+ public function getGoodsIsCollect($goods_id) : int
+ {
+ $goods_collect_model = new GoodsCollect();
+ $collect_info = $goods_collect_model
+ ->where([ [ 'member_id', '=', $this->member_id ], [ 'goods_id', '=', $goods_id ] ])
+ ->findOrEmpty()
+ ->toArray();
+ if (!empty($collect_info)) {
+ return 1;
+ } else {
+ return 0;
+ }
+ }
+
+ /**
+ * 获取商品规格信息,切换规格
+ * @param int $sku_id
+ * @return array
+ */
+ public function getSku(int $sku_id)
+ {
+ $field = 'sku_id, sku_name, sku_image, goods_id, sku_spec_format, price, market_price, sale_price, stock, member_price';
+
+ $goods_sku_model = new GoodsSku();
+
+ $info = $goods_sku_model->where([ [ 'sku_id', '=', $sku_id ] ])
+ ->field($field)
+ ->with([
+ // 商品主表
+ 'goodsSingle' => function ($query) {
+ $query->withField('goods_id, goods_name, goods_cover, unit, member_discount,is_discount')
+ ->append([ 'goods_cover_thumb_mid' ]);
+ },
+ // 商品规格列表
+ 'skuList' => function ($query) {
+ $query->field('sku_id, sku_name, sku_image, goods_id, sku_spec_format, price, market_price, sale_price, stock,member_price')
+ ->append([ 'sku_image_thumb_mid' ]);
+ },
+ // 商品规格项/规格值列表
+ 'goodsSpec' => function ($query) {
+ $query->field('spec_id, goods_id, spec_name, spec_values');
+ },
+ ])
+ ->append([ 'sku_image_thumb_mid' ])
+ ->findOrEmpty()->toArray();
+
+
+ if (!empty($info)) {
+ $info[ 'goods' ] = $info[ 'goodsSingle' ];
+ unset($info[ 'goodsSingle' ]);
+ if (!empty($this->member_id)) {
+ // 限购查询当前会员已购数量
+ $has_buy = ( new CoreGoodsLimitBuyService() )->getGoodsHasBuyNumber( $this->member_id, $info[ 'goods_id' ]);
+ $info[ 'has_buy' ] = $has_buy;
+ }
+ $goods_active_price_service = new CoreGoodsActivePriceService();
+ //获取展示信息(价格 标签)
+ $info[ 'member_discount' ] = $info[ 'goods' ][ 'member_discount' ] ?? '';
+ $detail_show_price = $goods_active_price_service->getShowPrice($info, $this->member_id);
+ $info[ 'show_price' ] = $detail_show_price[ 'show_price' ];
+ $info[ 'show_type' ] = $detail_show_price[ 'show_type' ];
+ //组装数据
+ if (!empty($info[ 'skuList' ])) {
+ foreach ($info[ 'skuList' ] as &$value) {
+ $value[ 'member_discount' ] = $info[ 'goods' ][ 'member_discount' ] ?? '';
+ $list_show_price = $goods_active_price_service->getShowPrice($value, $this->member_id);
+ $value[ 'show_price' ] = $list_show_price[ 'show_price' ];
+ $value[ 'show_type' ] = $list_show_price[ 'show_type' ];
+ }
+ }
+ }
+
+ return $info;
+ }
+
+ /**
+ * 获取商品列表供组件调用
+ * @param array $where
+ * @return array
+ */
+ public function getGoodsComponents(array $where = [])
+ {
+ $field = 'goods_id,goods_name,sub_title,goods_type,goods_cover,unit,sale_num + goods.virtual_sale_num as sale_num,member_discount,label_ids,brand_id,is_limit,limit_type,max_buy,min_buy';
+
+ $sku_where = [
+ [ 'goodsSku.is_default', '=', 1 ],
+ [ 'goods.is_gift', '=', GoodsDict::NOT_IS_GIFT ],
+ [ 'status', '=', 1 ]
+ ];
+
+ if (!empty($where[ 'goods_ids' ])) {
+ $sku_where[] = [ 'goods.goods_id', 'in', $where[ 'goods_ids' ] ];
+ }
+
+ // 参数过滤
+ if (!empty($where[ 'order' ]) && in_array($where[ 'order' ], [ 'sale_num', 'price' ])) {
+ $order = $where[ 'order' ] . ' desc';
+ } else {
+ $sort_config = ( new CoreGoodsConfigService() )->getSortConfig();
+ if ($sort_config[ 'sort_column' ] == 'sale_price') {
+ $sort_config[ 'sort_column' ] = 'goodsSku.sale_price';
+ }
+ $order = $sort_config[ 'sort_column' ] . ' ' . $sort_config[ 'sort_type' ];
+ }
+
+ $list = $this->model
+ ->withSearch([ "goods_category", "label_ids", 'service_ids' ], $where)
+ ->field($field)
+ ->withJoin([
+ 'goodsSku' => [ 'sku_id', 'sku_name', 'sku_image', 'sku_no', 'goods_id', 'sku_spec_format', 'price', 'market_price', 'sale_price', 'stock', 'weight', 'volume', 'member_price' ]
+ ])
+ ->where($sku_where)->order($order)->append([ 'goods_cover_thumb_small','goods_cover_thumb_mid', 'goods_label_name', 'goods_brand' ])
+ ->limit($where[ 'num' ])
+ ->select()->toArray();
+ $goods_active_price_service = ( new CoreGoodsActivePriceService() );
+ foreach ($list as $k => &$v) {
+ if (!empty($v[ 'goodsSku' ])) {
+ $v[ 'goodsSku' ][ 'member_discount' ] = $v[ 'member_discount' ];
+ $list_show_price = $goods_active_price_service->getShowPrice($v[ 'goodsSku' ], $this->member_id);
+ $v[ 'goodsSku' ][ 'show_price' ] = $list_show_price[ 'show_price' ];
+ $v[ 'goodsSku' ][ 'show_type' ] = $list_show_price[ 'show_type' ];
+ }
+ }
+ return $list;
+ }
+
+ public function getMemberInfo()
+ {
+ $member_model = new Member();
+ $member_field = 'member_level';
+ $member_info = $member_model->where([
+ [ 'member_id', '=', $this->member_id ]
+ ])->field($member_field)
+ ->with([
+ // 会员等级
+ 'memberLevelData' => function ($query) {
+ $query->field('level_id, level_name, status, level_benefits, level_gifts');
+ },
+ ])
+ ->findOrEmpty()->toArray();
+ return $member_info;
+ }
+
+ /**
+ * 查询商品的会员价
+ * @param $member_info
+ * @param string $member_discount 会员等级折扣,不参与:空,会员折扣:discount,指定会员价:fixed_price
+ * @param string $member_price 会员价,json格式,指定会员价,数据结构为:{"level_12":"92.00","level_13":"72.00","level_14":"66.00","level_15":"45.00"}
+ * @param $price
+ * @return int|string
+ */
+ public function getMemberPrice($member_info, $member_discount, $member_price, $price)
+ {
+ if (empty($member_discount)) {
+ return $price;
+ }
+
+ // 未找到会员,排除
+ if (empty($member_info)) {
+ return $price;
+ }
+
+ // 没有会员等级,排除
+ if (!empty($member_info) && empty($member_info[ 'member_level' ])) {
+ return $price;
+ }
+
+ if ($member_discount == 'discount') {
+ // 按照会员等级折扣计算
+
+ // 默认按会员享受折扣计算
+ if (!empty($member_info[ 'memberLevelData' ][ 'level_benefits' ])
+ && !empty($member_info[ 'memberLevelData' ][ 'level_benefits' ][ 'discount' ])
+ && !empty($member_info[ 'memberLevelData' ][ 'level_benefits' ][ 'discount' ][ 'is_use' ])) {
+
+ $price = number_format($price * $member_info[ 'memberLevelData' ][ 'level_benefits' ][ 'discount' ][ 'discount' ] / 10, 2, '.', '');
+ }
+
+ } elseif ($member_discount == 'fixed_price') {
+ // 指定会员价
+ if (!empty($member_price)) {
+ $member_price = json_decode($member_price, true);
+ if (!empty($member_price[ 'level_' . $member_info[ 'member_level' ] ])) {
+ $member_level_price = $member_price[ 'level_' . $member_info[ 'member_level' ] ];
+ $price = number_format($member_level_price, 2, '.', '');
+ }
+ }
+ }
+
+ return $price;
+ }
+
+ /**
+ * 查询商品的会员价
+ * @param $member_info
+ * @param string $member_discount 会员等级折扣,不参与:空,会员折扣:discount,指定会员价:fixed_price
+ * @param $sku_list
+ * @return int
+ */
+ public function getMemberPriceByList($member_info, $member_discount, &$sku_list)
+ {
+
+ // 是否按照原价返回
+ $is_default = false;
+
+ if (empty($member_discount)) {
+ $is_default = true;
+ }
+
+ // 未找到会员,排除
+ if (empty($member_info)) {
+ $is_default = true;
+ }
+
+ // 没有会员等级,排除
+ if (!empty($member_info) && empty($member_info[ 'member_level' ])) {
+ $is_default = true;
+ }
+
+ foreach ($sku_list as $k => &$v) {
+
+ if ($is_default) {
+ $v[ 'member_price' ] = $v[ 'price' ];
+ } else {
+ if ($member_discount == 'discount') {
+ // 按照会员等级折扣计算
+
+ // 默认按会员享受折扣计算
+ if (!empty($member_info[ 'memberLevelData' ][ 'level_benefits' ])
+ && !empty($member_info[ 'memberLevelData' ][ 'level_benefits' ][ 'discount' ])
+ && !empty($member_info[ 'memberLevelData' ][ 'level_benefits' ][ 'discount' ][ 'is_use' ])) {
+ $v[ 'member_price' ] = number_format($v[ 'price' ] * $member_info[ 'memberLevelData' ][ 'level_benefits' ][ 'discount' ][ 'discount' ] / 10, 2, '.', '');
+ } else {
+ $v[ 'member_price' ] = $v[ 'price' ];
+ }
+
+ } elseif ($member_discount == 'fixed_price') {
+ // 指定会员价
+ if (!empty($v[ 'member_price' ])) {
+ $member_price = json_decode($v[ 'member_price' ], true); // 会员价,json格式,指定会员价
+ if (!empty($member_price[ 'level_' . $member_info[ 'member_level' ] ])) {
+ $member_level_price = $member_price[ 'level_' . $member_info[ 'member_level' ] ];
+ $v[ 'member_price' ] = number_format($member_level_price, 2, '.', '');
+ } else {
+ $v[ 'member_price' ] = $v[ 'price' ];
+ }
+ }
+ }
+ }
+ }
+
+ return $sku_list;
+
+ }
+
+ /**
+ * 猜你喜欢
+ * @return void|array
+ */
+ public function getRecommend()
+ {
+ $field = 'goods_id,goods_name,sub_title,goods_category,goods_type,goods_cover,unit,status,sale_num + goods.virtual_sale_num as sale_num,member_discount,is_discount,virtual_receive_type';
+ $order = 'sale_num desc';
+
+ $where['goods_sku_is_default'] = 1;
+ $where['status'] = 1;
+ $search_model = $this->model
+ ->withSearch([ 'status' ], $where)
+ ->field($field)
+ ->withJoin([ 'goodsSku' ])
+ ->order($order)->append([ 'goods_type_name', 'goods_cover_thumb_small', 'goods_cover_thumb_mid' ]);
+ $list = $this->pageQuery($search_model);
+ if (!empty($list['data'])){
+ $goods_active_price_service = (new CoreGoodsActivePriceService());
+ foreach ($list[ 'data' ] as $k => &$v) {
+ $v[ 'goodsSku' ][ 'member_discount' ] = $v[ 'goods' ][ 'member_discount' ] ?? '';
+ //获取展示活动价格
+ $show_price_data = $goods_active_price_service->getShowPrice($v[ 'goodsSku' ], $this->member_id);
+ $v[ 'goodsSku' ][ 'show_price' ] = $show_price_data[ 'show_price' ];
+ $v[ 'goodsSku' ][ 'show_type' ] = $show_price_data[ 'show_type' ];
+ }
+ }
+
+ return $list;
+
+ }
+
+}
diff --git a/niucloud/addon/shop/app/service/api/goods/GoodsServiceService.php b/niucloud/addon/shop/app/service/api/goods/GoodsServiceService.php
new file mode 100644
index 000000000..641deade9
--- /dev/null
+++ b/niucloud/addon/shop/app/service/api/goods/GoodsServiceService.php
@@ -0,0 +1,38 @@
+model = new Service();
+ }
+
+ /**
+ * 商品服务列表
+ */
+ public function getAll($data)
+ {
+ $limit = !empty($data[ 'limit' ]) ? $data[ 'limit' ] : 4;
+ $field = 'service_id, service_name, image, desc';
+ return $this->model->field($field)->order('create_time desc')->limit($limit)->select()->toArray();
+ }
+
+}
diff --git a/niucloud/addon/shop/app/service/api/goods/RankService.php b/niucloud/addon/shop/app/service/api/goods/RankService.php
new file mode 100644
index 000000000..688df5574
--- /dev/null
+++ b/niucloud/addon/shop/app/service/api/goods/RankService.php
@@ -0,0 +1,340 @@
+model = new Rank();
+ $this->goodsStatModel = new Stat();
+ $this->goodsModel = new Goods();
+ }
+
+ /**
+ * 获取商品排行榜配置
+ * @return array
+ */
+ public function getGoodsRankConfig()
+ {
+ return ( new CoreGoodsRankConfigService() )->getGoodsRankConfig();
+ }
+
+ /**
+ * 获取商品榜单列表
+ * @param array $where
+ * @return array
+ */
+ public function getPage(array $where = [])
+ {
+ $field = 'rank_id,name,goods_source';
+ $order = 'sort desc,create_time desc';
+ $list = $this->model->where([ [ 'status', '=', RankDict::ON ] ])->withSearch([ "name" ], $where)->field($field)->order($order)->select()->toArray();
+
+ return $list;
+ }
+
+ /**
+ * 获取商品榜单列表
+ * @param array $data
+ * @return array
+ */
+ public function getGoodsPage($data)
+ {
+ $rank_id = $data[ 'rank_id' ];
+ $rank_info = $this->model->field('rank_id,name,rank_type,rule_type,goods_source,goods_json,category_ids,brand_ids,label_ids')->where([ [ 'rank_id', '>', 0 ] ])->find($rank_id);
+ $list = [];
+ if ($rank_info) {
+ $list = $this->getGoodsList($rank_info, 0, $data);
+ }
+ return $list;
+ }
+
+ /**
+ * 获取商品榜单组件列表
+ * @param array $data
+ * @return array
+ */
+ public function getRankComponents($data)
+ {
+ $rank_id = $data[ 'rank_id' ];
+ $limit = $data[ 'limit' ];
+ $where[] = [
+ [ 'status', '=', RankDict::ON ]
+ ];
+ $order = '';
+ if ($rank_id > 0) {
+ $where[] = [ 'rank_id', '=', $rank_id ];
+ $order = 'sort desc,create_time desc';
+ }else{
+ $where[] = [ 'rank_id', '>', 0 ];
+ }
+
+ $rank_info = $this->model->field('rank_id,name,rank_type,rule_type,goods_source,goods_json,category_ids,brand_ids,label_ids')->where($where)->order($order)->findOrEmpty()->toArray();
+ $data = [];
+ if (!empty($rank_info)) {
+ $data[ 'rank_id' ] = $rank_info[ 'rank_id' ];
+ $data[ 'name' ] = $rank_info[ 'name' ];
+ $data[ 'goods_list' ] = $this->getGoodsList($rank_info, $limit);
+ }
+ return $data;
+ }
+
+ /**
+ * 根据榜单设置条件查询对应的商品信息
+ * @param $rank_info
+ * @param int $limit
+ * @param array $data
+ * @return array
+ * @throws \think\db\exception\DbException
+ */
+ protected function getGoodsList($rank_info, $limit = 0, $data = [])
+ {
+ // 根据排行周期 获取时间区间
+ $date_end = strtotime(date('Y-m-d 23:59:59'));
+ switch ($rank_info[ 'rank_type' ]) {
+ case RankDict::DAY:
+ $day = 1;
+ break;
+ case RankDict::WEEK:
+ $day = 7;
+ break;
+ case RankDict::MONTH:
+ $day = 30;
+ break;
+ case RankDict::QUARTER:
+ $day = 90;
+ break;
+ }
+ $date_start = $date_end - 86400 * $day + 1;
+ $field = 'goods.goods_id,goods_name,goods_cover,unit,goods.sale_num + goods.virtual_sale_num as sale_num,member_discount,sum(stat.sale_num)+ goods.virtual_sale_num as stat_sale_num,sum(stat.collect_num) as stat_collect_num,sum(stat.evaluate_num) as stat_evaluate_num,sum(stat.access_num) as stat_access_num,goods.create_time,goods.sort as goods_sort';
+ $where[] = [
+ [ 'goods.is_gift', '=', GoodsDict::NOT_IS_GIFT ],
+ [ 'goods.status', '=', 1 ],
+ [ 'goods.delete_time', '=', 0 ],
+ ];
+ $order = 'stat_' . $rank_info[ 'rule_type' ] . '_num desc,goods_sort desc,create_time desc';
+ // 来源类型 goods=指定商品,category=指定分类,brand=指定品牌, label=指定标签
+ if ($rank_info[ 'goods_source' ] == RankDict::GOODS) {
+ // 根据配置的排行周期查询对应的商品
+ $goods_json = $rank_info[ 'goods_json' ];
+ $config_goods_ids = array_column($goods_json, 'goods_id');
+ $list = $this->goodsModel
+ ->alias('goods')
+ ->field($field)
+ ->where([ [ 'goods.goods_id', 'in', $config_goods_ids ], [ 'goods.is_gift', '=', GoodsDict::NOT_IS_GIFT ], [ 'goods.status', '=', 1 ], [ 'goods.delete_time', '=', 0 ] ])
+ ->whereBetweenTime('date_time', $date_start, $date_end)
+ ->join('shop_goods_stat stat', 'goods.goods_id = stat.goods_id', 'left')
+ ->group('goods.goods_id')
+ ->append([ 'goods_cover_thumb_small', 'goods_cover_thumb_mid' ])
+ ->select()
+ ->toArray();
+ $sort_goods_json = array_column($goods_json, null, 'goods_id');
+ foreach ($list as &$item) {
+ $item[ 'sort' ] = $sort_goods_json[ $item[ 'goods_id' ] ][ 'sort' ] ?? 0;
+ }
+
+ usort($list, function ($list_one, $list_two) use ($rank_info) {
+ // 按 排序号 排序
+ if ($list_one[ 'sort' ] != $list_two[ 'sort' ]) {
+ return $list_two[ 'sort' ] <=> $list_one[ 'sort' ];
+ }
+ // 如果 排序号 相等,则按 排序规则 排序
+ if ($list_one[ 'stat_' . $rank_info[ 'rule_type' ] . '_num' ] != $list_two[ 'stat_' . $rank_info[ 'rule_type' ] . '_num' ]) {
+ return $list_two[ 'stat_' . $rank_info[ 'rule_type' ] . '_num' ] <=> $list_one[ 'stat_' . $rank_info[ 'rule_type' ] . '_num' ];
+ }
+ //如果 排序规则 相等,则按 商品排序号 排序
+ if ($list_one[ 'goods_sort' ] != $list_two[ 'goods_sort' ]) {
+ return $list_two[ 'goods_sort' ] <=> $list_one[ 'goods_sort' ];
+ }
+
+ // 如果 商品排序号 也相等,则按 创建时间 排序
+ return $list_two[ 'create_time' ] <=> $list_one[ 'create_time' ];
+ });
+
+ if ($limit == 0) {
+ $goods_list = [
+ 'total' => count($list),
+ 'per_page' => 1,
+ 'current_page' => 1,
+ 'last_page' => 1,
+ 'data' => $list,
+ ];
+ } else {
+ $goods_list = array_slice($list, 0, $limit);
+ }
+
+ } elseif ($rank_info[ 'goods_source' ] == RankDict::CATEGORY) {
+ $category_ids = $rank_info[ 'category_ids' ];
+ $query = $this->goodsModel
+ ->alias('goods')
+ ->field($field)
+ ->where($where)
+ ->whereBetweenTime('date_time', $date_start, $date_end)
+ ->withSearch([ 'goods_category' ], [ 'goods_category' => $category_ids ])
+ ->join('shop_goods_stat stat', 'goods.goods_id = stat.goods_id', 'left')
+ ->group('goods.goods_id')
+ ->limit($limit)
+ ->order($order)
+ ->append([ 'goods_cover_thumb_small', 'goods_cover_thumb_mid', 'goods_label_name', 'goods_brand' ]);
+ if ($limit == 0) {
+ $goods_list = $this->pageQuery($query);
+ } else {
+ $goods_list = $query->select()->toArray();
+ }
+ } elseif ($rank_info[ 'goods_source' ] == RankDict::BRAND) {
+ $brand_ids = $rank_info[ 'brand_ids' ];
+ $query = $this->goodsModel
+ ->alias('goods')
+ ->field($field)
+ ->where($where)
+ ->whereBetweenTime('date_time', $date_start, $date_end)
+ ->whereIn('goods.brand_id', $brand_ids)
+ ->join('shop_goods_stat stat', 'goods.goods_id = stat.goods_id', 'left')
+ ->group('goods.goods_id')
+ ->limit($limit)
+ ->order($order)
+ ->append([ 'goods_cover_thumb_small', 'goods_cover_thumb_mid', 'goods_label_name', 'goods_brand' ]);
+ if ($limit == 0) {
+ $goods_list = $this->pageQuery($query);
+ } else {
+ $goods_list = $query->select()->toArray();
+ }
+ } elseif ($rank_info[ 'goods_source' ] == RankDict::LABEL) {
+ $label_ids = $rank_info[ 'label_ids' ];
+ $query = $this->goodsModel
+ ->alias('goods')
+ ->field($field)
+ ->where($where)
+ ->whereBetweenTime('date_time', $date_start, $date_end)
+ ->withSearch([ 'label_ids' ], [ 'label_ids' => $label_ids ])
+ ->join('shop_goods_stat stat', 'goods.goods_id = stat.goods_id', 'left')
+ ->group('goods.goods_id')
+ ->limit($limit)
+ ->order($order)
+ ->append([ 'goods_cover_thumb_small', 'goods_cover_thumb_mid', 'goods_label_name', 'goods_brand' ]);
+ if ($limit == 0) {
+ $goods_list = $this->pageQuery($query);
+ } else {
+ $goods_list = $query->select()->toArray();
+ }
+ } else {
+ $query = $this->goodsModel
+ ->alias('goods')
+ ->field($field)
+ ->where($where)
+ ->whereBetweenTime('date_time', $date_start, $date_end)
+ ->join('shop_goods_stat stat', 'goods.goods_id = stat.goods_id', 'left')
+ ->group('goods.goods_id')
+ ->limit($limit)
+ ->order($order)
+ ->append([ 'goods_cover_thumb_small', 'goods_cover_thumb_mid', 'goods_label_name', 'goods_brand' ]);
+ if ($limit == 0) {
+ $goods_list = $this->pageQuery($query);
+ } else {
+ $goods_list = $query->select()->toArray();
+ }
+ }
+ //获取商品SKU、会员价格信息
+ $goods_active_price_service = ( new CoreGoodsActivePriceService() );
+ if (isset($goods_list[ 'data' ])) {
+ if (!empty($goods_list[ 'data' ])) {
+ foreach ($goods_list[ 'data' ] as $key => &$item) {
+ $item[ 'rank_num' ] = $key + 1;
+ $item[ 'goodsSku' ] = $this->getGoodsSku($item);
+ if (!empty($item[ 'goodsSku' ])) {
+ $item[ 'goodsSku' ][ 'member_discount' ] = $item[ 'member_discount' ];
+ $show_price = $goods_active_price_service->getShowPrice($item[ 'goodsSku' ],$this->member_id);
+ $item[ 'goodsSku' ][ 'show_price' ] = $show_price[ 'show_price' ];
+ $item[ 'goodsSku' ][ 'show_type' ] = $show_price[ 'show_type' ];
+ }
+ }
+ }
+ } else {
+ if (!empty($goods_list)) {
+ foreach ($goods_list as $key => &$item) {
+ $item[ 'rank_num' ] = $key + 1;
+ $item[ 'goodsSku' ] = $this->getGoodsSku($item);
+ if (!empty($item[ 'goodsSku' ])) {
+ $item[ 'goodsSku' ][ 'member_discount' ] = $item[ 'member_discount' ];
+ $show_price = $goods_active_price_service->getShowPrice($item[ 'goodsSku' ], $this->member_id);
+ $item[ 'goodsSku' ][ 'show_price' ] = $show_price[ 'show_price' ];
+ $item[ 'goodsSku' ][ 'show_type' ] = $show_price[ 'show_type' ];
+ }
+ }
+ }
+ }
+ return $goods_list;
+ }
+
+ /**
+ * 根据排行周期查询商品统计数据
+ */
+ protected function getGoodsIds($data)
+ {
+ $rank_type = $data[ 'rank_type' ];
+ $date_end = strtotime(date('Y-m-d 23:59:59'));
+ switch ($rank_type) {
+ case RankDict::DAY:
+ $day = 1;
+ break;
+ case RankDict::WEEK:
+ $day = 7;
+ break;
+ case RankDict::MONTH:
+ $day = 30;
+ break;
+ case RankDict::QUARTER:
+ $day = 90;
+ break;
+ }
+ $date_start = $date_end - 86400 * $day + 1;
+ $goods_ids = $this->goodsStatModel->where([ [ 'id', '>', 0 ] ])->whereBetweenTime('date_time', $date_start, $date_end)->column('goods_id');
+ return $goods_ids;
+ }
+
+ /**
+ * 获取商品SKU
+ * @param $data
+ * @return mixed
+ */
+ protected function getGoodsSku($data)
+ {
+ $goods_sku_info = ( new GoodsSku() )->field('sku_id,sku_name,sku_image,goods_id,price,sku_spec_format,sale_price,stock,member_price')
+ ->where([
+ [ 'goods_id', '=', $data[ 'goods_id' ] ]
+ ])
+ ->find();
+ return $goods_sku_info;
+ }
+
+}
diff --git a/niucloud/addon/shop/app/service/api/marketing/CouponService.php b/niucloud/addon/shop/app/service/api/marketing/CouponService.php
new file mode 100644
index 000000000..d70895313
--- /dev/null
+++ b/niucloud/addon/shop/app/service/api/marketing/CouponService.php
@@ -0,0 +1,478 @@
+model = new Coupon();
+ }
+
+ /**
+ * 获取优惠券列表
+ * @return array
+ */
+ public function getPage($data)
+ {
+ $goods_coupon_id = [];
+ if ($data[ 'goods_id' ] != '') {
+ $coupon_goods_model = new CouponGoods();
+ $goods_coupon_list = $coupon_goods_model->where([ [ 'goods_id', '=', $data[ 'goods_id' ] ] ])->select()->toArray();
+ if (!empty($goods_coupon_list)) {
+ $goods_coupon_id = array_column($goods_coupon_list, 'coupon_id');
+ } else {
+ $goods_coupon_id = [ -1 ];
+ }
+ }
+
+ $category_coupon_id = [];
+ if (!empty($data[ 'category_id' ])) {
+ $coupon_goods_model = new CouponGoods();
+ $category_coupon_list = $coupon_goods_model->where([ [ 'category_id', 'in', $data[ 'category_id' ] ] ])->select()->toArray();
+ if (!empty($category_coupon_list)) {
+ $category_coupon_id = array_column($category_coupon_list, 'coupon_id');
+ } else {
+ $category_coupon_id = [ -1 ];
+ }
+ }
+ $field = 'id,title,start_time,end_time,remain_count,receive_count,limit_count,status,price,min_condition_money,type
+ ,receive_type,valid_type,length,valid_start_time,valid_end_time,sort';
+
+ // 参数过滤
+ if (!empty($data[ 'order' ]) && in_array($data[ 'order' ], [ 'create_time', 'price' ])) {
+ $order = $data[ 'order' ] . ' ' . $data[ 'sort' ];
+ } else {
+ $order = 'id desc';
+ }
+
+ $where[] = [ 'status', '=', CouponDict::NORMAL ];
+ $where[] = [ 'receive_type', '=', CouponDict::USER ];
+ $where[] = function ($query) {
+ $query->where([ [ 'remain_count', '=', '-1' ] ])->whereOr([ [ 'remain_count', '>', 0 ] ]);
+ };
+
+ $time_where = function($query) {
+ $nowtime = time();
+ $time_where = [
+ [
+ [ 'start_time', '<=', $nowtime ],
+ [ 'end_time', '>=', $nowtime ],
+ ],
+ [
+ [ 'start_time', '=', 0 ],
+ [ 'end_time', '=', 0 ],
+ ]
+ ];
+ $query->whereOr($time_where);
+ };
+ if (!empty($category_coupon_id) || !empty($goods_coupon_id)) {
+ $category_where = [];
+ if (!empty($category_coupon_id)) {
+// $category_where = function ($query) use($category_coupon_id, $time_where){
+// $query->where([
+// ['id', 'in', $category_coupon_id],
+// ['type', '=', CouponDict::CATEGORY]
+// ]);
+// };
+ $category_where = [
+ [ 'id', 'in', $category_coupon_id ],
+ [ 'type', '=', CouponDict::CATEGORY ]
+ ];
+ }
+ $goods_where = [];
+ if (!empty($goods_coupon_id)) {
+ $goods_where = [
+ [ 'id', 'in', $goods_coupon_id ],
+ [ 'type', '=', CouponDict::GOODS ]
+ ];
+ }
+ $all_where = [
+ [ 'type', '=', CouponDict::ALL ]
+ ];
+
+ $common_where = function($query) use ($category_where, $goods_where, $all_where) {
+ $temp_where = [ $all_where ];
+ if ($category_where) {
+ $temp_where[] = $category_where;
+ }
+ if ($goods_where) {
+ $temp_where[] = $goods_where;
+ }
+ $query->whereOr($temp_where);
+ };
+
+ $search_model = $this->model
+ ->field($field)
+ ->where($where)
+ ->where($common_where)
+ ->where($time_where)
+ ->order($order)
+ ->append([ 'coupon_price', 'coupon_min_price', 'receive_type_name', 'type_name' ]);
+ } else {
+ $type_where = [];
+ if (!empty($data[ 'type' ])) {
+ $type_where = [
+ [ 'type', '=', $data[ 'type' ] ]
+ ];
+ }
+
+ $search_model = $this->model
+ ->field($field)
+ ->where($where)
+ ->where($type_where)
+ ->where($time_where)
+ ->order($order)
+ ->append([ 'coupon_price', 'coupon_min_price', 'receive_type_name', 'type_name' ]);
+ }
+ $list = $this->pageQuery($search_model);
+ $coupon_member = new CouponMember();
+ $member_info = ( new Member() )->where([ [ 'member_id', '=', $this->member_id ] ])->field('member_id')->findOrEmpty()->toArray();
+ foreach ($list[ 'data' ] as $k => &$v) {
+ if ($v[ 'remain_count' ] != '-1') {
+ $v[ 'sum_count' ] = $v[ 'remain_count' ] + $v[ 'receive_count' ];
+ } else {
+ $v[ 'sum_count' ] = '-1';
+ }
+
+ if ($member_info) {
+ $coupon_member_count = $coupon_member->where([ [ 'member_id', '=', $this->member_id ], [ 'coupon_id', '=', $v[ 'id' ] ], [ 'receive_type', '=', 'receive' ] ])->count();
+ if ($coupon_member_count) {
+ $v[ 'is_receive' ] = 1;
+ $v[ 'member_receive_count' ] = $coupon_member_count;
+ } else {
+ $v[ 'is_receive' ] = 0;
+ $v[ 'member_receive_count' ] = 0;
+ }
+ } else {
+ $v[ 'member_receive_count' ] = 0;
+ $v[ 'is_receive' ] = 0;
+ }
+ }
+ return $list;
+ }
+
+ /**
+ * 查询优惠券详情
+ */
+ public function getDetail($id)
+ {
+ $info = $this->model->where([ [ 'id', '=', $id ] ])->append([ 'coupon_price', 'coupon_min_price' ])->findOrEmpty()->toArray();
+
+ if (empty($info)) {
+ throw new CommonException('COUPON_NOT_EXIST');
+ }
+ if ($info[ 'remain_count' ] != '-1') {
+ $info[ 'sum_count' ] = $info[ 'remain_count' ] + $info[ 'receive_count' ];
+ } else {
+ $info[ 'sum_count' ] = '-1';
+ }
+ $coupon_member = new CouponMember();
+ $member_info = ( new Member() )->where([ [ 'member_id', '=', $this->member_id ] ])->field('member_id')->findOrEmpty()->toArray();
+
+ if ($member_info) {
+ $coupon_member_count = $coupon_member->where([ [ 'member_id', '=', $this->member_id ], [ 'coupon_id', '=', $id ], [ 'receive_type', '=', 'receive' ] ])->count();
+ if ($coupon_member_count) {
+ $info[ 'is_receive' ] = 1;
+ $info[ 'member_receive_count' ] = $coupon_member_count;
+ } else {
+ $info[ 'is_receive' ] = 0;
+ $info[ 'member_receive_count' ] = 0;
+ }
+ } else {
+ $info[ 'is_receive' ] = 0;
+ $info[ 'member_receive_count' ] = 0;
+ }
+
+ return $info;
+ }
+
+ /**
+ * 优惠券领取
+ */
+ public function receive($data)
+ {
+ $member_id = $this->member_id;
+ $coupon_id = $data[ 'coupon_id' ];
+ $number = $data[ 'number' ];
+ $type = $data[ 'type' ];
+ $coupon_member_model = new CouponMember();
+ Db::startTrans();
+ try {
+ //判断是否符合设置的领取方式
+ $receive_type = $this->getReceiveType();
+ if (!in_array($type, $receive_type)) {
+ throw new CommonException('COUPON_RECEIVE_TYPE_NOT_EXIST');
+ }
+ //判断是否已经领取过
+ $member_coupon_count = $coupon_member_model->where([ [ 'coupon_id', '=', $coupon_id ], [ 'member_id', '=', $member_id ], [ 'receive_type', '=', 'receive' ] ])->count();
+ //判断优惠券数量是否充足
+ $info = $this->model->where([ [ 'id', '=', $coupon_id ] ])->findOrEmpty()->toArray();
+ if (empty($info)) {
+ throw new CommonException('COUPON_NOT_EXIST');
+ }
+
+ if($info['status'] != CouponDict::NORMAL){
+ throw new CommonException('COUPON_INVALID');//优惠券已失效
+ }
+
+ if($info['receive_type'] != CouponDict::USER) {
+ throw new CommonException('COUPON_CAN_NOT_MANUAL_RECEIVE');//该优惠券不可手动领取
+ }
+
+ if ($member_coupon_count == $info[ 'limit_count' ]) {
+ throw new CommonException('COUPON_RECEIVE_EXCESS');//领取超过可领取数量
+ }
+
+ if ($info[ 'remain_count' ] != '-1' && $info[ 'remain_count' ] == 0) {
+ throw new CommonException('COUPON_STOCK_INSUFFICIENT');//优惠券已被领完
+ }
+ if (strtotime($info[ 'start_time' ]) > 0) {
+ $time = time();
+ if ($time < strtotime($info[ 'start_time' ])) {
+ throw new CommonException('COUPON_RECEIVE_NOT_TIME');//优惠券不在领取时间范围内
+ }
+ if ($time > strtotime($info[ 'end_time' ])) {
+ throw new CommonException('COUPON_RECEIVE_NOT_TIME');//优惠券不在领取时间范围内
+ }
+ }
+
+ if ($info[ 'remain_count' ] != -1) {
+ $coupon_data = [
+ 'remain_count' => $info[ 'remain_count' ] - $number,
+ 'receive_count' => $info[ 'receive_count' ] + $number,
+ ];
+ } else {
+ $coupon_data = [
+ 'receive_count' => $info[ 'receive_count' ] + $number,
+ ];
+ }
+
+ if ($info[ 'valid_type' ] == 1) {
+ $expire_time = 86400 * $info[ 'length' ] + time();
+ } else {
+ $expire_time = $info[ 'valid_end_time' ];
+ }
+ $member_coupon_data = [
+ 'coupon_id' => $coupon_id,
+ 'member_id' => $member_id,
+ 'create_time' => time(),
+ 'expire_time' => $expire_time,
+ 'receive_type' => $type,
+ 'type' => $info[ 'type' ],
+ 'title' => $info[ 'title' ],
+ 'price' => $info[ 'price' ],
+ 'status' => CouponMemberDict::WAIT_USE,
+ 'min_condition_money' => $info[ 'min_condition_money' ]
+ ];
+ $this->model->where([ [ 'id', '=', $coupon_id ] ])->update($coupon_data);
+ $coupon_member_model->create($member_coupon_data);
+ Db::commit();
+ return true;
+ } catch (\Exception $e) {
+ Db::rollback();
+ throw new CommonException($e->getMessage());
+ }
+
+ }
+
+ /**
+ * 会员优惠券领取记录
+ */
+ public function getMemberPage($data)
+ {
+ if (!empty($data[ 'status' ])) {
+ $where[] = [ 'status', '=', $data[ 'status' ] ];
+ }
+ if (in_array($data[ 'type' ], [CouponDict::ALL, CouponDict::CATEGORY, CouponDict::GOODS])) {
+ $where[] = [ 'type', '=', $data[ 'type' ] ];
+ }
+// elseif ($data[ 'type' ] == -1){
+// $where[] = [ 'expire_time', '>', time() + 86400 * 3 ];
+// }
+ $where[] = [ 'member_id', '=', $this->member_id ];
+ $coupon_member_model = new CouponMember();
+ $search_model = $coupon_member_model
+ ->where($where)
+ ->order([ 'id desc' ])
+ ->append([ 'coupon_price', 'coupon_min_price', 'receive_type_name', 'type_name' ]);
+ $list = $this->pageQuery($search_model);
+ return $list;
+ }
+
+ /**
+ * 会员优惠券按状态查询数量
+ * @param $data
+ * @return mixed
+ */
+ public function getCouponCountByStatus()
+ {
+ $count_list = [];
+ $status_array = array_keys(CouponMemberDict::getStatus());
+ foreach ($status_array as $v) {
+ $coupon_member_model = new CouponMember();
+ $count = $coupon_member_model->where([[ 'member_id', '=', $this->member_id ], [ 'status', '=', $v]])->count();
+ $count_list[] = [
+ 'status' => $v,
+ 'status_name' => CouponMemberDict::getStatus($v),
+ 'count' => $count
+ ];
+ }
+ return $count_list;
+ }
+
+ /**
+ * 会员已领取优惠券数量
+ * @param $data
+ * @return mixed
+ */
+ public function getMemberCount($data)
+ {
+ if (!empty($data[ 'status' ])) {
+ $where[] = [ 'status', '=', $data[ 'status' ] ];
+ }
+ $where[] = [ 'member_id', '=', $this->member_id ];
+// $where[] = [ 'expire_time', '>', time() ];
+ $coupon_member_model = new CouponMember();
+ $count = $search_model = $coupon_member_model
+ ->where($where)
+ ->count();
+ return $count;
+ }
+
+ //获取优惠券领取方式
+ public function getReceiveType()
+ {
+ $data = event('CouponReceiveType', []);
+ if (empty($data)) {
+ return [];
+ }
+ foreach ($data as &$value) {
+ foreach ($value as $v) {
+ $type[] = $v[ 'name' ];
+
+ }
+ }
+ return $type;
+ }
+
+ /**
+ * 获取优惠券类型
+ * @return array
+ */
+ public function getCouponType()
+ {
+// $list[] = [
+// 'label' => '快过期',
+// 'value' => '-1'
+// ];
+ $type = CouponDict::getType();
+ foreach ($type as $k => $v) {
+ $list[] = [
+ 'label' => $v,
+ 'value' => $k,
+ ];
+ }
+ return $list;
+ }
+
+ /**
+ * 获取优惠券列表供组件调用
+ * @return array
+ */
+ public function getCouponComponents($data)
+ {
+ $field = 'id,title,start_time,end_time,remain_count,receive_count,limit_count,status,price,min_condition_money,type
+ ,receive_type,valid_type,length,valid_start_time,valid_end_time,sort';
+ $order = 'id desc';
+
+ $where[] = ['status', '=', CouponDict::NORMAL];
+ $where[] = [ 'receive_type', '=', CouponDict::USER ];
+ if (!empty($data[ 'coupon_ids' ])) {
+ $where[] = [ 'id', 'in', $data[ 'coupon_ids' ] ];
+ }
+
+ $time_where = function($query) {
+ $nowtime = time();
+ $time_where = [
+ [
+ [ 'start_time', '<=', $nowtime ],
+ [ 'end_time', '>=', $nowtime ]
+ ],
+ [
+ [ 'start_time', '=', 0 ],
+ [ 'end_time', '=', 0 ]
+ ]
+ ];
+ $query->whereOr($time_where);
+ };
+ $list = $this->model
+ ->field($field)
+ ->where($where)
+ ->where($time_where)
+ ->order($order)
+ ->limit($data[ 'num' ])
+ ->append([ 'coupon_price', 'coupon_min_price', 'receive_type_name', 'type_name' ])
+ ->select()->toArray();
+
+ return $list;
+ }
+
+ /**
+ * 查询优惠券二维码
+ * @param $id
+ * @return string
+ */
+ public function getQrcode($id)
+ {
+ $info = $this->model->where([ [ 'id', '=', $id ] ])->findOrEmpty()->toArray();
+
+ if (empty($info)) {
+ throw new CommonException('COUPON_NOT_EXIST');
+ }
+
+ $url = ( new CoreSysConfigService() )->getSceneDomain()[ 'wap_url' ];
+ $page = 'addon/shop/pages/coupon/detail';
+
+ $data = [
+ [
+ 'key' => 'mid',
+ 'value' => $this->member_id
+ ],
+ [
+ 'key' => 'coupon_id',
+ 'value' => $id
+ ]
+ ];
+ $dir = 'upload/shop_coupon_qrcode';
+ $channel = 'weapp';
+
+ $path = qrcode($url, $page, $data,$dir, $channel);
+ return $path;
+ }
+}
diff --git a/niucloud/addon/shop/app/service/api/marketing/DiscountService.php b/niucloud/addon/shop/app/service/api/marketing/DiscountService.php
new file mode 100644
index 000000000..9862c29fb
--- /dev/null
+++ b/niucloud/addon/shop/app/service/api/marketing/DiscountService.php
@@ -0,0 +1,165 @@
+model = new Discount();
+ }
+
+ /**
+ * 查询商品正在参与的限时折扣活动
+ * @param $goods_id
+ * @return mixed
+ */
+ public function getInfoByGoods($goods_id)
+ {
+ $active_goods_model = new DiscountGoods();
+
+ $field = 'discount_goods_id as active_goods_id,discount_id';
+
+ $info = $active_goods_model->where([
+ [ 'status', '=', 'active' ],
+ [ 'goods_id', '=', $goods_id ]
+ ])->field($field)
+ ->with([
+ 'discount' => function($query) {
+ $query->withField('discount_id,name as active_name, remark as active_desc, start_time, end_time');
+ }
+ ])
+ ->findOrEmpty()->toArray();
+ if(!empty($info)) {
+ $info[ 'active_id' ] = $info[ 'discount_id' ];
+ $info[ 'discount' ][ 'active_id' ] = $info[ 'active_id' ];
+ $info[ 'active' ] = $info[ 'discount' ];
+ unset($info[ 'discount' ]);
+ }
+ return $info;
+
+ }
+
+ /**
+ * 折扣页面轮播图配置
+ */
+ public function getDiscountBannerConfig()
+ {
+ $data = ( new CoreConfigService() )->getConfigValue('SHOP_DISCOUNT_BANNER_CONFIG');
+ if (empty($data)) {
+ $data = [];
+ }
+ return $data;
+ }
+
+
+ /**
+ * 获取商品列表
+ * @param array $where
+ * @return array
+ */
+ public function getGoodsPage(array $where = [])
+ {
+ $field = 'goods_id,label_ids,goods_name,sub_title,goods_category,goods_type,goods_cover,unit,status,sale_num + virtual_sale_num as sale_num,member_discount,is_discount';
+
+ $sku_where = [
+ [ 'goods.status', '=', 1 ],
+ ];
+
+ if (!empty($where[ 'keyword' ])) {
+ $sku_where[] = [ 'goods_name|sub_title', 'like', '%' . $where[ 'keyword' ] . '%' ];
+ }
+
+ // 参数过滤
+ if (!empty($where[ 'order' ]) && in_array($where[ 'order' ], [ 'sale_num', 'sale_price' ])) {
+ $order = $where[ 'order' ] . ' ' . $where[ 'sort' ];
+ } else {
+ $order = 'sort desc,create_time desc';
+ }
+ $search_model = ( new Goods() )
+ ->alias('goods')
+ ->withSearch([ "brand_id", "goods_category", "label_ids", 'service_ids' ], $where)
+ ->field($field)
+ ->with([ 'skuList'])
+ ->withJoin([ 'discountGoods' => function($query) use ($where) {
+ $discount_where = [ [ 'discountGoods.status', 'in', [ DiscountDict::ACTIVE, DiscountDict::NOT_ACTIVE ] ] ];
+ if ($where[ 'discount_id' ]) $discount_where[] = [ 'discount_id', '=', $where[ 'discount_id' ] ];
+ $query->field('discount_id,discountGoods.status as discount_status')->where($discount_where);
+ } ], 'left')
+ ->group('goods.goods_id')
+ ->where($sku_where)->order($order)->hidden(['discountGoods'])->append([ 'goods_type_name', 'goods_cover_thumb_mid', 'goods_label_name', 'discount_status_name' ]);
+ $list = $this->pageQuery($search_model);
+
+ $discount_model = (new DiscountGoods());
+
+ if (!empty($list[ 'data' ])){
+ foreach ($list[ 'data' ] as $key => $item) {
+ $sku_list = $item[ 'skuList' ] ?? [];
+ $sku_list = array_column($sku_list, null, 'sku_id');
+ $discount_goods_value = $discount_model->where([['discount_id','=',$item['discount_id']],['goods_id','=',$item['goods_id']]])->column('*','sku_id');
+ foreach ($discount_goods_value as $k => $v) {
+ if (!empty($v[ 'is_enabled' ])) {
+ $goods_sku = $sku_list[ $v[ 'sku_id' ] ] ?? [];
+ $discount_price = $v[ 'discount_price' ] ?? $goods_sku[ 'price' ];
+
+ if (( !empty($item[ 'goodsSku' ]) && $item[ 'goodsSku' ][ 'discount_price' ] > $discount_price ) || empty($item[ 'goodsSku' ])) {
+ $item[ 'goodsSku' ] = $goods_sku;
+ $item[ 'goodsSku' ][ 'discount_type' ] = $v[ 'type' ] ?? '';
+ $item[ 'goodsSku' ][ 'discount_rate' ] = $v[ 'rate' ] ?? '111';
+ $item[ 'goodsSku' ][ 'discount_price' ] = $discount_price;
+ $item[ 'goodsSku' ][ 'reduce_money' ] = $v[ 'reduce_money' ] ?? 0;
+ }
+
+ }
+ }
+ if (empty($item[ 'goodsSku' ])) {
+ $item[ 'goodsSku' ] = $item[ 'skuList' ][ 0 ] ?? [];
+ $item[ 'goodsSku' ][ 'discount_type' ] = 'discount';
+ $item[ 'goodsSku' ][ 'discount_rate' ] = '10';
+ $item[ 'goodsSku' ][ 'discount_price' ] = $item[ 'goodsSku' ][ 'price' ] ?? '0';
+ $item[ 'goodsSku' ][ 'reduce_money' ] = 0;
+
+ }
+ $list[ 'data' ][ $key ] = $item;
+ }
+ }
+
+ return $list;
+ }
+
+ public function getList(array $where)
+ {
+ $field = 'discount_id,name,remark,start_time,end_time,status,create_time,update_time';
+
+ $order = Db::raw('FIELD(status, "' . DiscountDict::ACTIVE . '","' . DiscountDict::NOT_ACTIVE . '"), start_time asc');
+
+ return $this->model->where([
+ [ 'status', 'in', [ DiscountDict::ACTIVE, DiscountDict::NOT_ACTIVE ] ],
+ ])->withSearch([ "name" ], $where)->append([ 'status_name' ])->field($field)->limit($where[ 'limit' ])->order($order)->select()->toArray();
+
+ }
+
+}
diff --git a/niucloud/addon/shop/app/service/api/marketing/ManjianService.php b/niucloud/addon/shop/app/service/api/marketing/ManjianService.php
new file mode 100644
index 000000000..7948e8c14
--- /dev/null
+++ b/niucloud/addon/shop/app/service/api/marketing/ManjianService.php
@@ -0,0 +1,48 @@
+model = new Manjian();
+ }
+
+ /**
+ * 获取满减信息
+ * @return array
+ */
+ public function getManjianInfo($data)
+ {
+ $data[ 'member_id' ] = $this->member_id;
+ return ( new CoreManjianService() )->getManjianInfo($data);
+ }
+
+}
diff --git a/niucloud/addon/shop/app/service/api/marketing/NewcomerService.php b/niucloud/addon/shop/app/service/api/marketing/NewcomerService.php
new file mode 100644
index 000000000..30cb00159
--- /dev/null
+++ b/niucloud/addon/shop/app/service/api/marketing/NewcomerService.php
@@ -0,0 +1,241 @@
+model = new Active();
+ }
+
+ /**
+ * 新人专享商品列表
+ * @param array $where
+ * @return array
+ */
+ public function getGoodsPage(array $where = [])
+ {
+ $active_goods_model = new ActiveGoods();
+ $active_goods = $active_goods_model->field('goods_id,sku_id,active_goods_value')->where([
+ [ 'active_class', '=', ActiveDict::NEWCOMER_DISCOUNT ],
+ [ 'active_goods_status', '=', ActiveDict::ACTIVE ]
+ ])->select()->toArray();
+ $active_goods_ids = array_unique(array_column($active_goods, 'goods_id'));
+ $active_sku_ids = array_column($active_goods, 'sku_id');
+ $active_goods = array_column($active_goods, null, 'sku_id');
+
+ $field = 'goods_id,goods_name,goods_type,goods_cover,unit,sale_num + goods.virtual_sale_num as sale_num';
+
+ $sku_where = [
+ [ 'status', '=', 1 ],
+ [ 'goodsSku.is_default', '=', 1 ],
+ [ 'goods.goods_id', 'in', $active_goods_ids ]
+ ];
+
+ if (!empty($where[ 'keyword' ])) {
+ $sku_where[] = [ 'goods_name|sub_title', 'like', '%' . $where[ 'keyword' ] . '%' ];
+ }
+
+ // 参数过滤
+ if (!empty($where[ 'order' ]) && in_array($where[ 'order' ], [ 'sale_num', 'sale_price' ])) {
+ $order = $where[ 'order' ] . ' ' . $where[ 'sort' ];
+ } else {
+ $order = 'sort desc,create_time desc';
+ }
+
+ $search_model = ( new Goods() )
+ ->withSearch([ "brand_id", "goods_category" ], $where)
+ ->field($field)
+ ->withJoin([
+ 'goodsSku' => [ 'sku_id', 'sku_name', 'sku_image', 'goods_id', 'sku_spec_format', 'price', 'sale_price' ]
+ ])
+ ->with([
+ 'skuList' => function(Query $query) use ($active_sku_ids) {
+ $query->where([ [ 'sku_id', 'in', $active_sku_ids ] ]);
+ }
+ ])
+ ->where($sku_where)->order($order)->append([ 'goods_cover_thumb_mid' ]);
+ $list = $this->pageQuery($search_model);
+
+ foreach ($list[ 'data' ] as &$item) {
+ if (!empty($item[ 'skuList' ]) && !empty($active_goods) && !empty($active_sku_ids)) {
+ foreach ($item[ 'skuList' ] as &$sku_item) {
+ $active_goods_value = json_decode($active_goods[ $sku_item[ 'sku_id' ] ][ 'active_goods_value' ], true);
+ $sku_item[ 'newcomer_price' ] = $active_goods_value[ 'newcomer_price' ] ?? 0;
+ }
+ if (!empty($item[ 'goodsSku' ])) {
+ if (in_array($item[ 'goodsSku' ][ 'sku_id' ], $active_sku_ids)) {
+ $active_goods_value = json_decode($active_goods[ $item[ 'goodsSku' ][ 'sku_id' ] ][ 'active_goods_value' ], true);
+ $item[ 'goodsSku' ][ 'newcomer_price' ] = $active_goods_value[ 'newcomer_price' ] ?? 0;
+ } else {
+ $item[ 'goodsSku' ] = $item[ 'skuList' ][ 0 ];
+ }
+ }
+ }
+ }
+
+ $newcomerRecords = ( new NewcomerRecords() )->field('validity_time,is_join')->where([ [ 'member_id', '=', $this->member_id ] ])->findOrEmpty()->toArray();
+ $list[ 'validity_time' ] = !empty($newcomerRecords) ? $newcomerRecords[ 'validity_time' ] : 0;
+ $list[ 'is_join' ] = !empty($newcomerRecords) ? $newcomerRecords[ 'is_join' ] : 0; // 是否参与过新人专享活动
+
+ return $list;
+ }
+
+ public function getComponentsList($data)
+ {
+ $active_goods_model = new ActiveGoods();
+ $active_goods = $active_goods_model->field('goods_id,sku_id,active_goods_value')->where([
+ [ 'active_class', '=', ActiveDict::NEWCOMER_DISCOUNT ],
+ [ 'active_goods_status', '=', ActiveDict::ACTIVE ]
+ ])->select()->toArray();
+
+ if (!empty($active_goods)) {
+ $active_sku_ids = array_unique(array_column($active_goods, 'sku_id'));
+ $active_goods = array_column($active_goods, null, 'sku_id');
+
+ if (!empty($data[ 'sku_ids' ])) {
+ $sku_ids = $data[ 'sku_ids' ];
+ } else {
+ $sku_ids = $active_sku_ids;
+ }
+ $limit = $data[ 'limit' ] ?? 0;
+
+ foreach ($sku_ids as $sku_id) {
+ if (!in_array($sku_id, $active_sku_ids)) unset($sku_id);
+ }
+ $sku_ids = array_values($sku_ids);
+
+ $field = 'sku_id,goods_id,sku_name,sku_image,price,sale_price';
+ $sku_where = [
+ [ 'goods.status', '=', 1 ],
+ [ 'goods_sku.sku_id', 'in', $sku_ids ]
+ ];
+ $order = 'goods_sku.sale_num desc,goods_sku.stock desc';
+
+ $list = ( new GoodsSku() )->field($field)->withJoin([ 'goods' => [ 'goods_name' ] ])->where($sku_where)->limit($limit)->order($order)->select()->toArray();
+ foreach ($list as &$item) {
+ $active_goods_value = json_decode($active_goods[ $item[ 'sku_id' ] ][ 'active_goods_value' ], true);
+ $item[ 'newcomer_price' ] = $active_goods_value[ 'newcomer_price' ] ?? 0;
+ }
+
+ $newcomerRecords = ( new NewcomerRecords() )->field('validity_time,is_join')->where([ [ 'member_id', '=', $this->member_id ] ])->findOrEmpty()->toArray();
+ $validity_time = !empty($newcomerRecords) ? $newcomerRecords[ 'validity_time' ] : 0;
+ $is_join = !empty($newcomerRecords) ? $newcomerRecords[ 'is_join' ] : 0; // 是否参与过新人专享活动
+
+ return [
+ 'goods_list' => $list,
+ 'validity_time' => $validity_time,
+ 'is_join' => $is_join
+ ];
+ } else {
+ return [
+ 'goods_list' => [],
+ 'validity_time' => 0,
+ 'is_join' => 0
+ ];
+ }
+ }
+
+ /**
+ * 查询商品详情新人专享信息
+ * @param $goods_id
+ * @param $sku_id
+ * @return array
+ */
+ public function getNewcomerInfo($goods_id, $sku_id)
+ {
+ $active_goods_model = new ActiveGoods();
+ $active_goods = $active_goods_model->field('active_id,active_goods_value')->where([
+ [ 'active_goods_status', '=', ActiveDict::ACTIVE ],
+ [ 'active_goods_type', '=', ActiveDict::GOODS_SINGLE ],
+ [ 'active_class', '=', ActiveDict::NEWCOMER_DISCOUNT ],
+ [ 'goods_id', '=', $goods_id ],
+ [ 'sku_id', '=', $sku_id ]
+ ])->with([
+ 'active' => function($query) {
+ $query->field('active_id,active_desc,active_value');
+ }
+ ])->findOrEmpty()->toArray();
+
+ if (empty($active_goods)) return [];
+
+ $info[ 'newcomer_price' ] = json_decode($active_goods[ 'active_goods_value' ], true)[ 'newcomer_price' ] ?? 0;
+ $info[ 'newcomer_desc' ] = $active_goods[ 'active' ][ 'active_desc' ] ?? '';
+ $info[ 'limit_num' ] = $active_goods[ 'active' ][ 'active_value' ][ 'limit_num' ] ?? '';
+ return $info;
+
+ }
+
+ /**
+ * 查询商品规格的新人价
+ * @param $sku_list
+ * @return array
+ */
+ public function getNewcomerPriceByList(&$sku_list)
+ {
+ $active_goods_model = new ActiveGoods();
+ foreach ($sku_list as &$v) {
+ $active_goods = $active_goods_model->field('active_goods_value')->where([
+ [ 'active_goods_status', '=', ActiveDict::ACTIVE ],
+ [ 'active_goods_type', '=', ActiveDict::GOODS_SINGLE ],
+ [ 'active_class', '=', ActiveDict::NEWCOMER_DISCOUNT ],
+ [ 'goods_id', '=', $v[ 'goods_id' ] ],
+ [ 'sku_id', '=', $v[ 'sku_id' ] ]
+ ])->findOrEmpty()->toArray();
+
+ if (empty($active_goods)) {
+ $v[ 'newcomer_price' ] = $v[ 'price' ];
+ $v[ 'is_newcomer' ] = 0;
+ } else {
+ $v[ 'newcomer_price' ] = json_decode($active_goods[ 'active_goods_value' ], true)[ 'newcomer_price' ] ?? 0;
+ $v[ 'is_newcomer' ] = 1;
+ }
+ }
+ return $sku_list;
+ }
+
+ /**
+ * 检测当前会员是否满足新人专享活动条件
+ * @return bool
+ */
+ public function checkIfNewcomer()
+ {
+ return ( new CoreNewcomerService() )->checkIfNewcomer($this->member_id);
+ }
+
+ /**
+ * 获取新人专享活动配置
+ * @return array
+ */
+ public function getConfig()
+ {
+ return ( new CoreNewcomerService() )->getConfig();
+ }
+
+}
diff --git a/niucloud/addon/shop/app/service/api/marketing/pointexchange/ExchangeService.php b/niucloud/addon/shop/app/service/api/marketing/pointexchange/ExchangeService.php
new file mode 100644
index 000000000..aa9b86a59
--- /dev/null
+++ b/niucloud/addon/shop/app/service/api/marketing/pointexchange/ExchangeService.php
@@ -0,0 +1,170 @@
+model = new Exchange();
+ }
+
+ /**
+ * 获取积分商城列表
+ * @param array $where
+ * @return array
+ */
+ public function getPage(array $where = [])
+ {
+ $field = 'status,total_exchange_num,stock,id,type,names,title,image,status,product_detail,point,price,limit_num,content,sort,total_point_num,total_price_num,total_order_num,total_member_num,update_time,create_time';
+ if (!empty($where[ 'order' ]) && in_array($where[ 'order' ], [ 'total_order_num', 'total_exchange_num', 'price' ])) {
+ $order = $where[ 'order' ] . ' ' . $where[ 'sort' ];
+ } else {
+ $order = 'total_order_num desc,sort desc';
+ }
+ $search_model = $this->model->where([ [ 'id', '>', 0 ] ])->withSearch([ 'names', 'status', 'create_time' ], $where)
+ ->append([ 'type_name', 'status_name', 'goods_cover_thumb_small', 'goods_cover_thumb_mid', 'goods_label', 'goods_brand' ])->field($field)->order($order);
+ $list = $this->pageQuery($search_model);
+ return $list;
+ }
+
+ /**
+ * 获取积分商城详情
+ * @param int $id
+ * @return array
+ */
+ public function getDetail(int $id)
+ {
+
+ $field = 'total_exchange_num,id,type,names,title,image,status,product_detail,point,price,limit_num,content,sort,total_point_num,total_price_num,total_order_num,total_member_num,update_time,create_time';
+ $info = $this->model->where([ [ 'id', '=', $id ] ])->append([ 'type_name', 'goods_cover_thumb_mid', 'goods_image_thumb_small', 'goods_image_thumb_mid', 'goods_image_thumb_big' ])->field($field)->findOrEmpty()->toArray();
+ if (!empty($info)) {
+ $goods_id = 0;
+ foreach ($info[ 'product_detail' ] as $k => $v) {
+ if (!empty($v[ 'goods_id' ])) {
+ $goods_id = $v[ 'goods_id' ];
+ }
+ }
+ $goods_info = ( new GoodsService() )->getDetail([ 'goods_id' => $goods_id, 'sku_id' => $info[ 'product_detail' ][ 0 ][ 'sku_id' ] ]);
+
+ $goods_info[ 'goods' ][ 'goods_desc' ] = $info[ 'content' ];
+ $goods_info[ 'sale_num' ] = $info[ 'total_exchange_num' ];
+ $goods_info[ 'goods' ][ 'goods_name' ] = $info[ 'names' ];
+ $goods_info[ 'goods' ][ 'goods_image' ] = $info[ 'image' ];
+ $goods_info[ 'goods' ][ 'goods_image_thumb_big' ] = $info[ 'goods_image_thumb_big' ];
+ $goods_info[ 'goods' ][ 'goods_cover_thumb_mid' ] = $info[ 'goods_cover_thumb_mid' ];
+ $goods_info[ 'goods' ][ 'sub_title' ] = $info[ 'title' ];
+ $product_detail_array = $info[ 'product_detail' ];
+ $product_detail_array = array_column($product_detail_array, null, 'sku_id');
+ $sku_ids = array_keys($product_detail_array);
+ $reset_sku_id = reset($product_detail_array)[ 'sku_id' ];
+ $goods_info[ 'price' ] = $product_detail_array[ $reset_sku_id ][ 'price' ];
+// $goods_info[ 'market_price' ] = $product_detail_array[ $reset_sku_id ][ 'price' ];
+ $goods_info[ 'sale_price' ] = $product_detail_array[ $reset_sku_id ][ 'price' ];
+ $goods_info[ 'stock' ] = min($goods_info[ 'stock' ], $product_detail_array[ $reset_sku_id ][ 'stock' ]);
+ $goods_info[ 'point' ] = $product_detail_array[ $reset_sku_id ][ 'point' ];
+ $goods_info[ 'exchange_id' ] = $id;
+ if (!empty($goods_info[ 'skuList' ])) {
+ foreach ($goods_info[ 'skuList' ] as $k => &$item) {
+ $item[ 'limit_num' ] = 0;
+ $item[ 'is_join_exchange' ] = 1;
+ if (!in_array($item[ 'sku_id' ], $sku_ids)) {
+ $item[ 'is_join_exchange' ] = 0;
+ unset($goods_info[ 'skuList' ][ $k ]);
+ }
+ $item[ 'point' ] = 0;
+ $item[ 'is_default' ] = $reset_sku_id == $item[ 'sku_id' ] ? 1 : 0;
+ if (isset($product_detail_array[ $item[ 'sku_id' ] ])) {
+ $item[ 'price' ] = $product_detail_array[ $item[ 'sku_id' ] ][ 'price' ];
+// $item[ 'market_price' ] = $product_detail_array[ $item[ 'sku_id' ] ][ 'price' ];
+ $item[ 'sale_price' ] = $product_detail_array[ $item[ 'sku_id' ] ][ 'price' ];
+ $item[ 'stock' ] = min($item[ 'stock' ], $product_detail_array[ $item[ 'sku_id' ] ][ 'stock' ]);
+ $item[ 'point' ] = $product_detail_array[ $item[ 'sku_id' ] ][ 'point' ];
+ $item[ 'limit_num' ] = $product_detail_array[ $item[ 'sku_id' ] ][ 'limit_num' ];
+ }
+ }
+ $goods_info[ 'skuList' ] = array_values($goods_info[ 'skuList' ]);
+ }
+ }
+ return $goods_info ?? [];
+ }
+
+ /**
+ * 获取积分商城详情
+ * @param $where
+ * @return mixed
+ */
+ public function getInfo($where)
+ {
+ $field = 'stock,total_exchange_num,id,type,names,title,image,status,product_detail,point,price,limit_num,content,sort,total_point_num,total_price_num,total_order_num,total_member_num,update_time,create_time';
+ $info = $this->model->where([ [ 'id', '>', 0 ] ])->withSearch([ 'names', 'status', 'create_time', 'product_detail', 'sku_id', 'goods_id' ], $where)->append([ 'type_name' ])->field($field)->findOrEmpty()->toArray();
+ return $info;
+ }
+
+ /**********************************************************组件调用***************************************************************************************/
+
+
+ /**
+ * 获取商品列表供组件调用
+ * @param array $where
+ * @return array
+ */
+ public function getGoodsComponents(array $where = [])
+ {
+ $field = 'total_exchange_num,stock,id,type,names,title,image,product_detail,point,price,limit_num,total_point_num,total_price_num,total_order_num,total_member_num';
+// $goods_where[] = [ 'stock', '>', 0 ];
+ $goods_where[] = [ 'status', '=', 1 ];
+ if (!empty($where[ 'order' ]) && in_array($where[ 'order' ], [ 'total_order_num', 'total_exchange_num', 'price' ])) {
+ $order = $where[ 'order' ] . ' ' . $where[ 'sort' ];
+ } else {
+ $order = 'total_order_num desc,sort desc';
+ }
+ $list = $this->model->where($goods_where)->withSearch([ 'names', 'ids' ], $where)
+ ->append([ 'type_name', 'goods_cover_thumb_small','goods_cover_thumb_mid', 'goods_label', 'goods_brand' ])
+ ->field($field)->order($order)->limit($where[ 'num' ])->select()->toArray();
+ return $list;
+ }
+
+ /**
+ * 获取组件调用 会员当前积分数+今日积分数
+ * @return array
+ */
+ public function getPointInfo()
+ {
+ $point_data = ( new Member() )->where([ [ 'member_id', '=', $this->member_id ] ])->field('point')->findOrEmpty()->toArray();
+ $condition = [
+ [ 'account_type', '=', MemberAccountTypeDict::POINT ],
+ [ 'account_data', '>', 0 ],
+ [ 'member_id', '=', $this->member_id ],
+ ];
+ $today_point = ( new MemberAccountLog() )->where($condition)->whereBetweenTime('create_time', strtotime("today"), strtotime("today") + 86400)->sum('account_data');
+ $point_data[ 'today_point' ] = $today_point;
+ return $point_data;
+ }
+
+}
diff --git a/niucloud/addon/shop/app/service/api/marketing/pointexchange/OrderCreateService.php b/niucloud/addon/shop/app/service/api/marketing/pointexchange/OrderCreateService.php
new file mode 100644
index 000000000..328d0471c
--- /dev/null
+++ b/niucloud/addon/shop/app/service/api/marketing/pointexchange/OrderCreateService.php
@@ -0,0 +1,82 @@
+model = new Order();
+ }
+
+ /**
+ * 计算
+ * @param array $data
+ * @return array
+ * @throws \Exception
+ */
+ public function calculate(array $data)
+ {
+ $data['member_id'] = $this->member_id;
+ $data['order_from'] = $this->channel;
+ return (new CoreOrderCreateService())->calculate($data);
+ }
+
+ /**
+ * 订单创建
+ * @param array $data
+ * @return array
+ */
+ public function create(array $data)
+ {
+ $data['member_id'] = $this->member_id;
+ $data['order_from'] = $this->channel;
+ $data['main_type'] = OrderLogDict::MEMBER;
+ $data['main_id'] = $this->member_id;
+ return (new CoreOrderCreateService())->create($data);
+ }
+
+ /**
+ * @return void
+ * @todo 获取配送信息(待定)
+ */
+ public function getDelivery(array $data)
+ {
+ $data['member_id'] = $this->member_id;
+ }
+
+ /**
+ * 查询自提点
+ * @param array $data
+ * @return array
+ * @throws DataNotFoundException
+ * @throws DbException
+ * @throws ModelNotFoundException
+ */
+ public function getStore(array $data)
+ {
+ return (new CoreStoreService())->getStoreList($data);
+ }
+}
diff --git a/niucloud/addon/shop/app/service/api/order/ConfigService.php b/niucloud/addon/shop/app/service/api/order/ConfigService.php
new file mode 100644
index 000000000..07abb342e
--- /dev/null
+++ b/niucloud/addon/shop/app/service/api/order/ConfigService.php
@@ -0,0 +1,43 @@
+order_config_service = new CoreOrderConfigService();
+ }
+
+ /**
+ * 获取交易设置
+ * @return array
+ */
+ public function getConfig()
+ {
+ return $this->order_config_service->getConfig();
+ }
+
+}
diff --git a/niucloud/addon/shop/app/service/api/order/InvoiceService.php b/niucloud/addon/shop/app/service/api/order/InvoiceService.php
new file mode 100644
index 000000000..a848f4f21
--- /dev/null
+++ b/niucloud/addon/shop/app/service/api/order/InvoiceService.php
@@ -0,0 +1,183 @@
+model = new Invoice();
+ }
+
+ public function pages($data)
+ {
+ $where[] = ['member_id', '=', $this->member_id];
+ if ($data['status'] != '') {
+ if ($data['status'] == InvoiceDict::WAIT_INVOICE) {//未开票为待开票和待审核
+ $where[] = ['is_invoice', 'in', [InvoiceDict::WAIT_AUDIT, InvoiceDict::WAIT_INVOICE]];
+ } else {
+ $where[] = ['is_invoice', '=', $data['status']];
+ }
+ }
+ $query = $this->model->field('id,member_id,header_type,header_name,type,name,tax_number,mobile,email,telephone,address,bank_name,bank_card_number,money,is_invoice,invoice_number,invoice_voucher,remark,create_time,invoice_time,pay_voucher')
+ ->where($where)
+ ->with([
+ 'member' => function ($q) {
+ $q->field('member_id,nickname,headimg');
+ }
+ ])
+ ->append(['header_type_name', 'type_name', 'invoice_type_name', 'pay_voucher_thumb_mid', 'pay_voucher_thumb_small', 'pay_voucher_thumb_big', 'invoice_voucher_thumb_mid', 'invoice_voucher_thumb_small', 'invoice_voucher_thumb_big'])
+ ->order('create_time desc');
+ return $this->pageQuery($query);
+ }
+
+ public function detail($id)
+ {
+ $where[] = ['member_id', '=', $this->member_id];
+ $where[] = ['id', '=', $id];
+ $info = $this->model->field('id,member_id,header_type,header_name,type,name,tax_number,mobile,email,telephone,address,bank_name,bank_card_number,money,is_invoice,invoice_number,invoice_voucher,remark,create_time,invoice_time,pay_voucher')->where($where)->with(['member' => function ($q) {
+ $q->field('member_id,nickname,headimg');
+ }])->with([
+ 'order_list' => function ($q) {
+ $q->field('invoice_id,order_id,order_no,order_money')->with([
+ 'order_goods' => function ($query) {
+ $query->field('extend,order_goods_id, order_id, member_id, goods_id, sku_id, goods_name, sku_name, goods_image, sku_image, price, num, goods_money, is_enable_refund, delivery_id,is_enable_refund, status, is_gift')
+ ->with([
+ 'order_delivery' => function ($query) {
+ $query->field('id, express_company_id, express_number')->with('company');
+ }
+ ])
+ ->append(['goods_image_thumb_small']);
+ },
+ ]);
+ }
+ ])
+ ->append(['header_type_name', 'type_name', 'invoice_type_name', 'pay_voucher_thumb_mid', 'pay_voucher_thumb_small', 'pay_voucher_thumb_big', 'invoice_voucher_thumb_mid', 'invoice_voucher_thumb_small', 'invoice_voucher_thumb_big'])
+ ->findOrEmpty();
+ if ($info->isEmpty()) {
+ throw new ApiException('INVOICE_NOT_EXIST');
+ }
+ return $info->toArray();
+ }
+
+ /**
+ * 用户申请补开发票
+ * @param $data
+ * @return void
+ */
+ public function apply($data)
+ {
+ $trade_ids = implode(',', $data['trade_ids']);
+ $is_apply = $this->model->where([
+ 'member_id' => $this->member_id,
+ 'trade_type' => InvoiceDict::TYPE,
+ ])->whereIn('trade_id',$trade_ids)->count() > 0;
+ if ($is_apply) {
+ throw new ApiException('INVOICE_HAS_ORDER_APPLY');
+ }
+ $member_id = $this->member_id;
+ $insert = [
+ 'member_id' => $member_id,
+ 'trade_type' => InvoiceDict::TYPE,
+ 'trade_id' => $trade_ids,
+ 'pay_voucher' => $data['pay_voucher'],
+ 'header_type' => $data['header_type'],
+ 'header_name' => $data['header_name'],
+ 'type' => $data['type'],
+ 'name' => $data['name'],
+ 'tax_number' => $data['tax_number'],
+ 'mobile' => $data['mobile'],
+ 'email' => $data['email'],
+ 'telephone' => $data['telephone'],
+ 'address' => $data['address'],
+ 'bank_name' => $data['bank_name'],
+ 'bank_card_number' => $data['bank_card_number'],
+ 'money' => $data['money'],
+ 'create_time' => time(),
+ 'status' => InvoiceDict::OPEN,//生效
+ 'is_invoice' => InvoiceDict::WAIT_AUDIT,//待审核
+ ];
+ $invoice_id = (new CoreInvoiceService())->add($insert);
+ (new CoreOrderService())->setInvoiceIdByOrderId(explode(',', $trade_ids), $invoice_id);
+ }
+
+ /**
+ * 取消发票申请
+ * @param $id
+ * @return void
+ */
+ public function cancel($id)
+ {
+ $info = $this->model->where(['id' => $id, 'member_id' => $this->member_id])->findOrEmpty();
+ if ($info->isEmpty()) {
+ throw new ApiException('INVOICE_NOT_EXIST');
+ }
+ if ($info->is_invoice == InvoiceDict::INVOICED) {
+ throw new ApiException('INVOICED');
+ }
+ Db::startTrans();
+ try {
+ $this->model->where(['id' => $id, 'member_id' => $this->member_id])->delete();
+ (new CoreOrderService())->cancelInvoiceId($id);
+ Db::commit();
+ } catch (ApiException $e) {
+ Db::rollback();
+ throw new ApiException('INVOICE_CANCEL_ERROR');
+ }
+ }
+
+ /**
+ * 编辑发票信息
+ * @param $data
+ * @return void
+ */
+ public function edit($data)
+ {
+ $id = $data['id'];
+ $invoice_info = $this->model->where(['id' => $id, 'member_id' => $this->member_id])->findOrEmpty();
+ if ($invoice_info->isEmpty()) {
+ throw new ApiException('INVOICE_NOT_EXIST');
+ }
+ if ($invoice_info->is_invoice == InvoiceDict::INVOICED) {
+ throw new ApiException('INVOICED');
+ }
+ $this->model->where(['id' => $id, 'member_id' => $this->member_id])->update([
+ 'trade_type' => InvoiceDict::TYPE,
+ 'pay_voucher' => $data['pay_voucher'],
+ 'header_type' => $data['header_type'],
+ 'header_name' => $data['header_name'],
+ 'type' => $data['type'],
+ 'name' => $data['name'],
+ 'tax_number' => $data['tax_number'],
+ 'mobile' => $data['mobile'],
+ 'email' => $data['email'],
+ 'telephone' => $data['telephone'],
+ 'address' => $data['address'],
+ 'bank_name' => $data['bank_name'],
+ 'bank_card_number' => $data['bank_card_number'],
+ 'money' => $data['money'],
+ ]);
+ }
+
+}
diff --git a/niucloud/addon/shop/app/service/api/order/OrderCreateService.php b/niucloud/addon/shop/app/service/api/order/OrderCreateService.php
new file mode 100644
index 000000000..5a748be66
--- /dev/null
+++ b/niucloud/addon/shop/app/service/api/order/OrderCreateService.php
@@ -0,0 +1,109 @@
+model = new Order();
+ }
+
+ /**
+ * 订单创建
+ * @param array $data
+ * @return array
+ */
+ public function create(array $data)
+ {
+ $data['member_id'] = $this->member_id;
+ $data['order_from'] = $this->channel;
+ $data['main_type'] = OrderLogDict::MEMBER;
+ $data['main_id'] = $this->member_id;
+ return (new CoreOrderCreateService())->create($data);
+ }
+
+ /**
+ * 计算
+ * @param array $data
+ * @return void|null
+ */
+ public function calculate(array $data)
+ {
+ $data['member_id'] = $this->member_id;
+ $data['order_from'] = $this->channel;
+ return (new CoreOrderCreateService())->calculate($data);
+ }
+
+ /**
+ * 确认订单数据
+ * @param array $data
+ * @return void
+ */
+// public function confirm(array $data)
+// {
+// $data['member_id'] = $this->member_id;
+// return (new CoreOrderCreateService())->confirm($data);
+// }
+
+ /**
+ * 获取优惠券列表
+ * @param array $data
+ * @return void|null
+ */
+ public function getCoupon(array $data)
+ {
+ $data['member_id'] = $this->member_id;
+ return (new CoreOrderCreateService())->getCoupon($data);
+ }
+
+ /**
+ * @return void
+ * @todo 获取配送信息(待定)
+ */
+ public function getDelivery(array $data)
+ {
+ $data['member_id'] = $this->member_id;
+ }
+
+ /**
+ * 查询自提点
+ * @param array $data
+ * @return array
+ * @throws DataNotFoundException
+ * @throws DbException
+ * @throws ModelNotFoundException
+ */
+ public function getStore(array $data)
+ {
+ return (new CoreStoreService())->getStoreList($data);
+ }
+
+ public function getLocalDeliveryConfig()
+ {
+ return (new Local())->where([['local_id', '>', 0]])->findOrEmpty()->toArray();
+ }
+}
diff --git a/niucloud/addon/shop/app/service/api/order/OrderPayService.php b/niucloud/addon/shop/app/service/api/order/OrderPayService.php
new file mode 100644
index 000000000..badb99fe0
--- /dev/null
+++ b/niucloud/addon/shop/app/service/api/order/OrderPayService.php
@@ -0,0 +1,28 @@
+model = new Order();
+ }
+
+}
diff --git a/niucloud/addon/shop/app/service/api/order/OrderService.php b/niucloud/addon/shop/app/service/api/order/OrderService.php
new file mode 100644
index 000000000..cb90d9944
--- /dev/null
+++ b/niucloud/addon/shop/app/service/api/order/OrderService.php
@@ -0,0 +1,418 @@
+model = new Order();
+ }
+
+ /**
+ * 分页列表
+ * @param array $where
+ * @return array
+ */
+ public function getPage(array $where)
+ {
+ $field = 'point,activity_type,order_id,order_no,close_type,order_type,order_from,out_trade_no,status,member_id,ip,goods_money,delivery_money,order_money,create_time,pay_time,delivery_type,taker_name,taker_mobile,taker_full_address,take_store_id,is_enable_refund,member_remark,shop_remark,close_remark,pay_money,is_evaluate,invoice_id';
+ $order = 'create_time desc';
+ $search_model = $this->model
+ ->where([['member_id', '=', $this->member_id]])
+ ->withSearch(['order_no', 'status', 'activity_type','body'], $where)
+ ->field($field)
+ ->with(
+ [
+ 'invoice' => function ($query) {
+ $query->field('id');
+ },
+ 'order_goods' => function ($query) {
+ $query->field('extend,order_goods_id, order_id, member_id, goods_id, sku_id, goods_name, sku_name, goods_image, sku_image, price, num, goods_money, is_enable_refund, delivery_id,is_enable_refund, status, is_gift')
+ ->with([
+ 'order_delivery' => function ($query) {
+ $query->field('id, express_company_id, express_number')->with('company');
+ }
+ ])
+ ->append(['goods_image_thumb_small']);
+ },
+ 'store' => function ($query) {
+ $query->field('store_id, store_name, store_mobile');
+ }
+ ]
+ )->order($order)->append(['order_from_name', 'order_type_name', 'activity_type_name', 'status_name', 'delivery_type_name']);
+ $order_status_list = OrderDict::getStatus();
+ $order_close_list = OrderDict::getCloseType();
+ $list = $this->pageQuery($search_model, function ($item, $key) use ($order_status_list, $order_close_list) {
+ $item['close_type_name'] = $order_close_list[$item['close_type']] ?? "";
+ $item['order_status_data'] = $order_status_list[$item['status']] ?? [];
+ });
+ $config = (new CoreOrderConfigService())->getConfig();
+ $close_length = $config['close_order_info']['close_length'];
+ foreach ($list['data'] as $k => $v) {
+
+ $list['data'][$k]['now_time'] = time();
+ $list['data'][$k]['expire_time'] = strtotime($v['create_time']) + 60 * $close_length;
+ if ($v['out_trade_no']) {
+ $list['data'][$k]['pay'] = (new Pay())->where([['out_trade_no', '=', $v['out_trade_no']]])
+ ->field('type, pay_time')->append(['type_name'])
+ ->findOrEmpty()->toArray();
+ }
+ if ($v['order_goods']) {
+ foreach ($v['order_goods'] as $kk => $vv) {
+ $goods_info = (new Goods())->field('unit')->where([['goods_id', '=', $vv['goods_id']]])->findOrEmpty()->toArray();
+ if (!empty($goods_info)) {
+ $v['order_goods'][$kk]['unit'] = $goods_info['unit'];
+ } else {
+ $v['order_goods'][$kk]['unit'] = '件';
+ }
+ }
+ $list['data'][$k]['order_goods'] = $v['order_goods'];
+ }
+ $list['data'][$k]['is_can_invoice'] = 1;
+ if (!empty($v['invoice']) || !in_array($v['status'], [OrderDict::WAIT_DELIVERY, OrderDict::WAIT_TAKE, OrderDict::FINISH]) || ($v['order_money'] == 0)) {
+ $list['data'][$k]['is_can_invoice'] = 0;
+ }
+ }
+
+ // 查询小程序是否已开通发货信息管理服务
+ try {
+ $list['mch_id'] = '';
+ $result_is_trade_managed = (new WeappDeliveryService())->getIsTradeManaged();
+ if ($result_is_trade_managed) {
+
+ $list['is_trade_managed'] = true;
+ $pay_service = new PayChannelService();
+ $pay_config = $pay_service->getInfo([
+ 'type' => PayDict::WECHATPAY,
+ 'channel' => ChannelDict::WEAPP
+ ]);
+
+ $mch_id = '';
+ if (!empty($pay_config)) {
+ $mch_id = $pay_config['config']['mch_id'];
+ }
+
+ $list['mch_id'] = $mch_id;
+ } else {
+ $list['is_trade_managed'] = false;
+ }
+ } catch (\Exception $e) {
+ $list['is_trade_managed'] = false;
+ }
+ return $list;
+ }
+
+ /**
+ * 详情
+ * @param $order_id
+ * @return array
+ */
+ public function getDetail($order_id)
+ {
+ $field = 'buyer_ask_delivery_time,relate_id,activity_type,point,order_id,order_no,order_type,order_from,out_trade_no,status,member_id,ip,goods_money,delivery_money,order_money,invoice_id,create_time,pay_time,delivery_time,take_time,finish_time,close_time,delivery_type,taker_name,taker_mobile,taker_province,taker_city,taker_district,taker_address,taker_full_address,taker_longitude,taker_latitude,take_store_id,is_enable_refund,member_remark,shop_remark,close_remark,discount_money,is_evaluate,form_record_id';
+ $info = $this->model->where([['order_id|out_trade_no', '=', $order_id], ['member_id', '=', $this->member_id]])->field($field)
+ ->with(
+ [
+ 'order_goods' => function ($query) {
+ $query->field('extend,order_goods_id, order_id, member_id, goods_id, sku_id, goods_name, sku_name, goods_image, sku_image, price, num, goods_money, discount_money, is_enable_refund, status, order_refund_no, delivery_status, verify_count, verify_expire_time, is_verify, goods_type, is_gift,form_record_id')->append(['goods_image_thumb_small']);
+ },
+ 'order_discount' => function ($query) {
+ $query->field('order_id,discount_type,money');
+ },
+ 'invoice' => function ($query) {
+ $query->field('id');
+ }
+ ]
+ )->append(['order_from_name', 'order_type_name', 'status_name', 'delivery_type_name'])->findOrEmpty()->toArray();
+ if (!empty($info)) {
+ $info['is_can_invoice'] = 1;
+ //已开票或者未支付 或已关闭订单不允许补开发票
+ if (!empty($info['invoice']) || ($info['order_money'] == 0) || !in_array($info['status'], [OrderDict::WAIT_DELIVERY, OrderDict::WAIT_TAKE, OrderDict::FINISH])) {
+ $info['is_can_invoice'] = 0;
+ }
+ $info['order_status_data'] = $order_status_list[$info['status']] ?? [];
+
+ if ($info['delivery_type'] == DeliveryDict::STORE) {
+ $info['store'] = (new Store())->where([['store_id', '=', $info['take_store_id']]])
+ ->field('store_id, store_name, store_mobile, store_logo, trade_time, longitude, latitude, full_address')
+ ->findOrEmpty()->toArray();
+ }
+
+ if ($info['out_trade_no']) {
+ $info['pay'] = (new Pay())->where([['out_trade_no', '=', $info['out_trade_no']]])
+ ->field('main_id, out_trade_no, type, pay_time, status')->append(['type_name'])
+ ->findOrEmpty()->toArray();
+ if (!empty($info['pay'])) {
+ if ($info['member_id'] != $info['pay']['main_id']) {
+ $member_info = (new Member())->field('nickname,headimg')->where([['member_id', '=', $info['pay']['main_id']]])->findOrEmpty()->toArray();
+ if (!empty($member_info)) {
+ $info['pay']['pay_member'] = $member_info['nickname'];
+ $info['pay']['pay_member_headimg'] = $member_info['headimg'];
+ }
+ }
+ }
+ }
+
+ if ($info['delivery_type'] == DeliveryDict::EXPRESS || $info['delivery_type'] == DeliveryDict::LOCAL_DELIVERY) {
+ $info['order_delivery'] = (new OrderDelivery())
+ ->where([['order_id', '=', $info['order_id']]])
+ ->field('id, order_id, name, delivery_type, sub_delivery_type,express_company_id, express_number, create_time,third_delivery')
+ ->append(['third_delivery_name'])
+ ->select()->toArray();
+ if ($info['delivery_type'] == DeliveryDict::LOCAL_DELIVERY) {
+ $third_party_config = (new CoreLocalDeliveryService())->getConfig();
+ foreach ($info['order_delivery'] as $k => $item) {
+ if (!empty($item['third_delivery'])) {
+ $third_delivery = $item['third_delivery'];
+ $loader = new ThirdDeliveryLoader($third_delivery, $third_party_config[$third_delivery]);
+ //三方配送下单
+ $info['order_delivery'][$k]['third_delivery_info'] = $loader->queryOrderInfo(['order_no' => $info['order_no']]);
+ }
+ }
+ }
+
+ }
+
+ if ($info['order_goods']) {
+ foreach ($info['order_goods'] as $k => &$v) {
+ $goods_info = (new Goods())->field('unit')->where([['goods_id', '=', $v['goods_id']]])->findOrEmpty()->toArray();
+ if (!empty($goods_info)) {
+ $v['unit'] = $goods_info['unit'];
+ } else {
+ $v['unit'] = '件';
+ }
+ if (isset($v['extend']['is_impulse_buy']) == 1) {
+ $impulse_buy_num = $v['extend']['impulse_buy_goods_num'] ?? 0;//5
+ $impulse_buy_price_total = $v['extend']['impulse_buy_price'] ?? 0;
+ if ($impulse_buy_num > 0) {
+ $impulse_buy_price = $impulse_buy_price_total / $impulse_buy_num;
+ if ($impulse_buy_num == 1) {
+ $impulse_buy_tips = '第1' . $v['unit'] . $impulse_buy_price . '元';
+ } else {
+ $impulse_buy_tips = '第1-' . $impulse_buy_num . $v['unit'] . $impulse_buy_price . '元';
+ if ($v['num'] > $impulse_buy_num) {
+ if ($impulse_buy_num + 1 == $v['num']) {
+ $impulse_buy_tips .= ' 第' . ($impulse_buy_num + 1) . $v['unit'] . $v['price'] . '元';
+ } else {
+ $impulse_buy_tips .= ' 第' . ($impulse_buy_num + 1) . '-' . $v['num'] . $v['unit'] . $v['price'] . '元';
+ }
+ }
+ }
+ } else {//全原价
+ $impulse_buy_tips = '第1-' . $v['num'] . $v['unit'] . $v['price'] . '元';
+ }
+ }
+ $v['impulse_buy_tips'] = $impulse_buy_tips ?? "";
+ (new CoreManjianService())->getOrderGoodsGiveInfo($v, $info['order_goods'], $this->member_id);
+ }
+ }
+
+ $coupon_money = 0;
+ $manjian_discount_money = 0;
+ if ($info['order_discount']) {
+ foreach ($info['order_discount'] as $item) {
+ if ($item['discount_type'] == 'coupon') {
+ $coupon_money += $item['money'];
+ }
+ if ($item['discount_type'] == 'manjian') {
+ $manjian_discount_money += $item['money'];
+ }
+ }
+ }
+ $info['coupon_money'] = number_format($coupon_money, 2, '.', '');
+ $info['manjian_discount_money'] = number_format($manjian_discount_money, 2, '.', '');
+
+ // 查询小程序是否已开通发货信息管理服务
+ try {
+ $info['mch_id'] = '';
+ $result_is_trade_managed = (new WeappDeliveryService())->getIsTradeManaged();
+ if ($result_is_trade_managed) {
+ $info['is_trade_managed'] = true;
+
+ $pay_service = new PayChannelService();
+ $pay_config = $pay_service->getInfo([
+ 'type' => PayDict::WECHATPAY,
+ 'channel' => ChannelDict::WEAPP
+ ]);
+
+ $mch_id = '';
+ if (!empty($pay_config)) {
+ $mch_id = $pay_config['config']['mch_id'];
+ }
+
+ $info['mch_id'] = $mch_id;
+ } else {
+ $info['is_trade_managed'] = false;
+ }
+ } catch (\Exception $e) {
+ $info['is_trade_managed'] = false;
+ }
+
+ $config = (new CoreOrderConfigService())->getConfig();
+ $close_length = $config['close_order_info']['close_length'];
+
+ $info['now_time'] = time();
+ $info['expire_time'] = strtotime($info['create_time']) + 60 * $close_length;
+
+ }
+ return $info;
+ }
+
+
+ /**
+ * 订单关闭
+ * @param int $order_id
+ * @return true
+ */
+ public function close(int $order_id)
+ {
+ $data['main_type'] = OrderLogDict::MEMBER;
+ $data['main_id'] = $this->member_id;
+ $data['close_type'] = OrderDict::BUYER_CLOSE;
+ $data['order_id'] = $order_id;
+ (new CoreOrderCloseService())->close($data);
+ return true;
+ }
+
+
+ /**
+ * 订单收货
+ * @param $order_id
+ * @return true
+ */
+ public function finish($order_id)
+ {
+ $data = [];
+ $data['order_id'] = $order_id;
+ $data['main_type'] = OrderLogDict::MEMBER;
+ $data['main_id'] = $this->member_id;
+ //查询订单
+ $where = array(
+ ['order_id', '=', $order_id],
+ );
+ $order = $this->model->where($where)->findOrEmpty()->toArray();
+ if (empty($order)) throw new ApiException('SHOP_ORDER_NOT_FOUND');//订单不存在
+ if ($order['status'] != OrderDict::WAIT_TAKE) throw new ApiException('SHOP_ONLY_WAIT_TAKE_CAN_BE_TAKE');//只有待收货的订单才可以收货
+ (new CoreOrderFinishService())->finish($data);
+ return true;
+ }
+
+ /**
+ * 物流信息
+ * @param $data
+ * @return array|mixed
+ */
+ public function getDeliveryPackage($data)
+ {
+ $field = 'id, order_id, name, delivery_type, sub_delivery_type, express_company_id, express_number, local_deliver_id, status, create_time';
+ $info = (new OrderDelivery())->where([['id', '=', $data['id']]])->with([
+ 'company' => function ($query) {
+ $query->field('company_id, company_name, express_no');
+ },
+ 'order_goods' => function ($query) {
+ $query->field('goods_name, sku_name, goods_image, delivery_id, num, price')->append(['goods_image_thumb_small']);
+ }
+ ])->field($field)->findOrEmpty()->toArray();
+
+ if (!empty($info) && $info['delivery_type'] == OrderDeliveryDict::EXPRESS && $info['sub_delivery_type'] != OrderDeliveryDict::NONE_EXPRESS) {
+ $info['mobile'] = $data['mobile'];
+ $info = (new CoreOrderService())->deliverySearch($info);
+ return $info;
+ }
+ return $info;
+ }
+
+ public function num()
+ {
+
+ $data['wait_pay'] = $this->model->where([
+ ['member_id', '=', $this->member_id],
+ ['status', '=', OrderDict::WAIT_PAY],
+ ])->count() ?? 0;
+
+ $data['wait_shipping'] = $this->model->where([
+ ['member_id', '=', $this->member_id],
+ ['status', '=', OrderDict::WAIT_DELIVERY],
+ ])->count() ?? 0;
+
+ $data['wait_take'] = $this->model->where([
+ ['member_id', '=', $this->member_id],
+ ['status', '=', OrderDict::WAIT_TAKE],
+ ])->count() ?? 0;
+
+ $data['evaluate'] = $this->model->where([
+ ['member_id', '=', $this->member_id],
+ ['status', '=', OrderDict::FINISH],
+ ['is_evaluate', '=', 0],
+ ])->count() ?? 0;
+
+ $data['refund'] = (new OrderRefund())->where([
+ ['member_id', '=', $this->member_id],
+ ['status', 'in', [
+ OrderRefundDict::BUYER_APPLY_WAIT_STORE,
+ OrderRefundDict::STORE_AGREE_REFUND_GOODS_APPLY_WAIT_BUYER,
+ OrderRefundDict::STORE_REFUSE_REFUND_GOODS_APPLY_WAIT_BUYER,
+ OrderRefundDict::BUYER_REFUND_GOODS_WAIT_STORE,
+ OrderRefundDict::STORE_REFUSE_TAKE_REFUND_GOODS_WAIT_BUYER,
+ OrderRefundDict::STORE_AGREE_REFUND_WAIT_TRANSFER,
+ OrderRefundDict::STORE_REFUND_TRANSFERING
+ ]]
+ ])->count() ?? 0;
+
+ return $data;
+ }
+
+ public function calculateInvoiceMoney($ids)
+ {
+ $order_money = $this->model->whereIn('order_id', $ids)->where('invoice_id',0)->sum('order_money');
+ return [
+ 'invoice_money' => $order_money,
+ ];
+ }
+}
diff --git a/niucloud/addon/shop/app/service/api/refund/RefundActionService.php b/niucloud/addon/shop/app/service/api/refund/RefundActionService.php
new file mode 100644
index 000000000..c6302ca1f
--- /dev/null
+++ b/niucloud/addon/shop/app/service/api/refund/RefundActionService.php
@@ -0,0 +1,363 @@
+model = new OrderRefund();
+ }
+
+ /**
+ * 退款申请
+ * @param $data
+ * @return true
+ */
+ public function apply($data)
+ {
+ $order_goods_id = $data['order_goods_id'];
+ //查询订单项信息
+ $order_goods_model = new OrderGoods();
+ $order_goods_info = $order_goods_model->where([
+ ['order_goods_id', '=', $order_goods_id],
+ ['member_id', '=', $this->member_id]
+ ])->findOrEmpty();
+ if ($order_goods_info->isEmpty()) throw new ApiException('SHOP_ORDER_IS_INVALID');//订单已失效
+ if(!$order_goods_info['is_enable_refund']) throw new ApiException('SHOP_ORDER_IS_NOT_ENABLE_REFUND');//订单不允许退款
+ //查询有没有正没有关闭的退款
+ if ($order_goods_info['status'] != OrderGoodsDict::NORMAL) throw new ApiException('SHOP_ORDER_REFUND_IS_REFUND_FINISH');//订单已退款或存在未完成的退款
+ $order_id = $order_goods_info['order_id'];//订单id
+ $order = (new Order())->where([['order_id', '=', $order_id]])->findOrEmpty();
+ if ($order->isEmpty()) throw new ApiException('SHOP_ORDER_IS_INVALID');//订单已失效
+ $order_refund_no = create_no();
+ $refund_type = $data['refund_type'];
+ //只有已发货,才能退货退款
+ if($refund_type == OrderRefundDict::RETURN_AND_REFUND_GOODS && $order_goods_info['delivery_status'] == OrderDeliveryDict::WAIT_DELIVERY) throw new ApiException('SHOP_ORDER_REFUND_DELIVERY_NOT_ALLOW_REFUND_GOODS');
+ $apply_money = $data['apply_money'];
+
+ //查询是否是最后一笔退款且还没有退运费
+ $order_goods_count = $order_goods_model->where([['order_id', '=', $order_id], ['is_gift', '=', 0]])->count();
+ $refund_count = $this->model->where([['order_id', '=', $order_id]])->whereNotIn(
+ 'status', [OrderRefundDict::CLOSE, OrderRefundDict::SHOP_ACTIVE_CLOSE_REFUND]
+ )->count();
+ //是否包含运费
+ $is_refund_delivery = 0;
+ if(($refund_count + 1) >= $order_goods_count){//最后一笔退款
+ //判断是否已经退过运费
+ $refund_delivery_count = $this->model->where([['order_id', '=', $order_id], ['is_refund_delivery', '=', 1]])->whereNotIn(
+ 'status', [OrderRefundDict::CLOSE, OrderRefundDict::SHOP_ACTIVE_CLOSE_REFUND]
+ )->count();
+ if($refund_delivery_count == 0){//已经退过运费的,就不需要重复再退了
+ $is_refund_delivery = 1;
+ }
+ }
+ //当前订单项最大可退金额
+ $max_refund_money = $order_goods_info['goods_money'] - $order_goods_info['discount_money'];//可退金额
+ if($is_refund_delivery == 1){
+ $max_refund_money += $order['delivery_money'];
+ }
+ //退款金额不能大于可退款总额
+ $comparison = bccomp(bcsub($apply_money, $max_refund_money), 0);//浮点数直接进行比较会出现精度问题
+ if ($comparison > 0) throw new ApiException('SHOP_ORDER_REFUND_MONEY_GT_ORDER_MONEY');//退款金额不能大于可退款总额
+ $reason = $data['reason'];
+ $insert_data = [
+ 'order_id' => $order_goods_info['order_id'],
+ 'order_goods_id' => $order_goods_id,
+ 'order_refund_no' => $order_refund_no,
+ 'refund_type' => $refund_type,
+ 'reason' => $reason,
+ 'member_id' => $this->member_id,
+ 'apply_money' => $apply_money,
+ 'status' => OrderRefundDict::BUYER_APPLY_WAIT_STORE,
+ 'remark' => $data['remark'],
+ 'voucher' => $data['voucher'],
+ 'source' => OrderRefundDict::APPLY,
+ 'is_refund_delivery' => $is_refund_delivery ?? 0,
+ ];
+ $this->model->create($insert_data);
+
+ //将订单项的退款单号覆盖
+ $order_goods_info->save([
+ 'order_refund_no' => $order_refund_no,
+ 'status' => OrderGoodsDict::REFUNDING
+ ]);
+ //订单申请退款后事件
+ event('AfterShopOrderRefundApply', ['order_refund_no' => $order_refund_no, 'refund_data' => $insert_data]);
+ return true;
+ }
+
+ /**
+ * 售后
+ * @param $data
+ * @return true
+ */
+ public function edit($data)
+ {
+ $order_refund_no = $data['order_refund_no'];
+ //查询订单项信息
+ $order_refund_info = $this->model->where([
+ ['order_refund_no', '=', $order_refund_no],
+ ['member_id', '=', $this->member_id]
+ ])->findOrEmpty();
+ if ($order_refund_info->isEmpty()) throw new ApiException('SHOP_ORDER_IS_INVALID');//退款已失效
+ if (!in_array($order_refund_info['status'], [OrderRefundDict::BUYER_APPLY_WAIT_STORE, OrderRefundDict::STORE_REFUSE_REFUND_GOODS_APPLY_WAIT_BUYER])) throw new ApiException('SHOP_ORDER_IS_INVALID');//退款已失效(只有被拒绝的请求才可以修改退款)
+ $refund_type = $data['refund_type'];
+ $apply_money = $data['apply_money'];
+
+ $order_goods_id = $order_refund_info['order_goods_id'];
+ //查询订单项信息
+ $order_goods_info = (new OrderGoods())->where([
+ ['order_goods_id', '=', $order_goods_id],
+ ['member_id', '=', $this->member_id]
+ ])->findOrEmpty();
+ if ($order_goods_info->isEmpty()) throw new ApiException('SHOP_ORDER_REFUND_IS_INVALID');//订单已失效
+
+ $order_id = $order_goods_info['order_id'];//订单id
+ $order = (new Order())->where([['order_id', '=', $order_id]])->findOrEmpty();
+ if ($order->isEmpty()) throw new ApiException('SHOP_ORDER_IS_INVALID');//订单已失效
+
+ //是否包含运费
+ $is_refund_delivery = $order_refund_info['is_refund_delivery'];
+ //当前订单项最大可退金额
+ $max_refund_money = $order_goods_info['goods_money'] - $order_goods_info['discount_money'];//可退金额
+ if($is_refund_delivery == 1){
+ $max_refund_money += $order['delivery_money'];
+ }
+
+ //退款金额不能大于可退款总额
+ $comparison = bccomp(bcsub($apply_money, $max_refund_money), 0);//浮点数直接进行比较会出现精度问题
+ if ($comparison > 0) throw new ApiException('SHOP_ORDER_REFUND_MONEY_GT_ORDER_MONEY');//退款金额不能大于可退款总额
+ $reason = $data['reason'];
+ $update_data = [
+ 'refund_type' => $refund_type,
+ 'reason' => $reason,
+ 'apply_money' => $apply_money,
+ 'status' => OrderRefundDict::BUYER_APPLY_WAIT_STORE,
+ 'remark' => $data['remark'],
+ 'voucher' => $data['voucher'],
+ 'source' => OrderRefundDict::APPLY,
+ 'shop_reason'=>'' // 再次申请退款,清空拒绝理由
+ ];
+ $order_refund_info->save($update_data);
+ //订单申请退款后事件
+ event('AfterShopOrderRefundEdit', [ 'order_refund_no' => $order_refund_no, 'refund_data' => array_merge($order_refund_info->toArray(), $update_data)]);
+ return true;
+ }
+
+ /**
+ * 退款关闭
+ * @param $data
+ * @return true
+ */
+ public function close($data)
+ {
+ $data[ 'main_type' ] = OrderRefundLogDict::MEMBER;
+ $data[ 'main_id' ] = $this->member_id;
+ (new CoreRefundActionService())->close($data);
+ return true;
+ }
+
+ /**
+ * 退款发货
+ * @param $data
+ * @return true
+ */
+ public function delivery($data)
+ {
+ $order_refund_no = $data['order_refund_no'];
+ //查询订单项信息
+ $order_refund_info = $this->model->where([
+ ['order_refund_no', '=', $order_refund_no],
+ ['member_id', '=', $this->member_id]
+ ])->findOrEmpty();
+ if ($order_refund_info->isEmpty()) throw new ApiException('SHOP_ORDER_REFUND_IS_INVALID');//退款已失效
+ if ($order_refund_info['status'] != OrderRefundDict::STORE_AGREE_REFUND_GOODS_APPLY_WAIT_BUYER) throw new ApiException('SHOP_ORDER_REFUND_STATUS_NOT_SUPPORT_ACTION');//退款已失效(只有被拒绝的请求才可以修改退货)
+
+ $order_goods_id = $order_refund_info['order_goods_id'];
+ //查询订单项信息
+ $order_goods_info = (new OrderGoods())->where([
+ ['order_goods_id', '=', $order_goods_id],
+ ['member_id', '=', $this->member_id]
+ ])->findOrEmpty();
+ if ($order_goods_info->isEmpty()) throw new ApiException('SHOP_ORDER_REFUND_IS_INVALID');//订单已失效
+ //todo 配送信息增加
+ $delivery_param = $data['delivery'];
+ $delivery = array(
+ 'express_number' => $delivery_param['express_number'],
+ 'express_company' => $delivery_param['express_company'],
+ 'remark' => $delivery_param['remark'],
+ );
+ $update_data = [
+ 'delivery' => $delivery,
+ 'status' => OrderRefundDict::BUYER_REFUND_GOODS_WAIT_STORE,
+ ];
+ $order_refund_info->save($update_data);
+ //订单申请退款后事件
+ event('AfterShopOrderRefundDelivery', ['main_type' => OrderRefundLogDict::MEMBER, 'main_id' => $this->member_id, 'order_refund_no' => $order_refund_no, 'refund_data' => array_merge($order_refund_info->toArray(), $update_data)]);
+ return true;
+ }
+
+ /**
+ * 修改发货信息
+ * @param $data
+ * @return true
+ */
+ public function editDelivery($data)
+ {
+ $order_refund_no = $data['order_refund_no'];
+ //查询订单项信息
+ $order_refund_info = $this->model->where([
+ ['order_refund_no', '=', $order_refund_no],
+ ['member_id', '=', $this->member_id]
+ ])->findOrEmpty();
+ if ($order_refund_info->isEmpty()) throw new ApiException('SHOP_ORDER_REFUND_IS_INVALID');//退款已失效
+ if (!in_array($order_refund_info['status'], [OrderRefundDict::STORE_REFUSE_TAKE_REFUND_GOODS_WAIT_BUYER, OrderRefundDict::BUYER_REFUND_GOODS_WAIT_STORE])) throw new ApiException('SHOP_ORDER_REFUND_STATUS_NOT_SUPPORT_ACTION');//退款已失效(只有被拒绝的请求才可以修改退款)
+ $order_goods_id = $order_refund_info['order_goods_id'];
+ //查询订单项信息
+ $order_goods_info = (new OrderGoods())->where([
+ ['order_goods_id', '=', $order_goods_id],
+ ['member_id', '=', $this->member_id]
+ ])->findOrEmpty();
+ if ($order_goods_info->isEmpty()) throw new ApiException('SHOP_ORDER_IS_INVALID');//订单已失效
+ //todo 配送信息增加
+ $delivery_param = $data['delivery'];
+ $delivery = array(
+ 'express_number' => $delivery_param['express_number'],
+ 'express_company' => $delivery_param['express_company'],
+ 'remark' => $delivery_param['remark'],
+ );
+ $update_data = [
+ 'delivery' => $delivery,
+ 'status' => OrderRefundDict::BUYER_REFUND_GOODS_WAIT_STORE,
+ ];
+ $order_refund_info->save($update_data);
+ //订单申请退款后事件
+ event('AfterShopOrderRefundEditDelivery', ['main_type' => OrderRefundLogDict::MEMBER, 'main_id' => $this->member_id, 'order_refund_no' => $order_refund_no, 'refund_data' => array_merge($order_refund_info->toArray(), $update_data)]);
+ return true;
+ }
+
+ /**
+ *
+ * @return array
+ */
+ public function getRefundReason()
+ {
+ return OrderRefundDict::getRefundReason();
+ }
+
+ /**
+ * 获取订单项可退款属性
+ * @param $data
+ * @return void
+ */
+ public function getRefundData($data){
+ $order_goods_id = $data['order_goods_id'];
+ //查询订单项信息
+ $order_goods_model = new OrderGoods();
+ $order_goods_info = $order_goods_model->where([
+ ['order_goods_id', '=', $order_goods_id],
+ ['member_id', '=', $this->member_id]
+ ])->findOrEmpty();
+ if ($order_goods_info->isEmpty()) throw new ApiException('SHOP_ORDER_IS_INVALID');//订单已失效
+// if(!$order_goods_info['is_enable_refund']) throw new ApiException('SHOP_ORDER_IS_NOT_ENABLE_REFUND');//订单不允许退款
+ //查询有没有正没有关闭的退款
+// if ($order_goods_info['status'] != OrderGoodsDict::NORMAL) throw new ApiException('SHOP_ORDER_REFUND_IS_REFUND_FINISH');//订单已退款或存在未完成的退款
+ $order_id = $order_goods_info['order_id'];//订单id
+ $order = (new Order())->where([['order_id', '=', $order_id]])->findOrEmpty();
+ if ($order->isEmpty()) throw new ApiException('SHOP_ORDER_IS_INVALID');//订单已失效
+
+ //查询是否是最后一笔退款且还没有退运费
+ $order_goods_count = $order_goods_model->where([['order_id', '=', $order_id], ['is_gift', '=', 0]])->count();
+ $refund_count = $this->model->where([['order_id', '=', $order_id]])->whereNotIn(
+ 'status', [OrderRefundDict::CLOSE, OrderRefundDict::SHOP_ACTIVE_CLOSE_REFUND]
+ )->count();
+ $is_refund_delivery = 0;
+ if(($refund_count + 1) >= $order_goods_count){//最后一笔退款
+ //判断是否已经退过运费
+ $refund_delivery_count = $this->model->where([['order_id', '=', $order_id], ['is_refund_delivery', '=', 1]])->whereNotIn(
+ 'status', [OrderRefundDict::CLOSE, OrderRefundDict::SHOP_ACTIVE_CLOSE_REFUND]
+ )->count();
+ if($refund_delivery_count == 0){//已经退过运费的,就不需要重复再退了
+// $refund_delivery_money = $order['delivery_money'];
+ $is_refund_delivery = 1;
+ }
+ }
+ $refund_data = [
+ 'refund_money' => $order_goods_info['order_goods_money'],
+ 'is_refund_delivery' => $is_refund_delivery,
+ 'refund_order_goods_money' => $order_goods_info['order_goods_money']
+ ];
+ if($is_refund_delivery){
+ $refund_data['refund_money'] += $order['delivery_money'];
+ $refund_data['refund_delivery_money'] = $order['delivery_money'];
+ }
+ return $refund_data;
+ }
+
+ /**
+ * 通过退款单号获取退款信息
+ * @param array $data
+ * @return void
+ */
+ public function getRefundDataByOrderRefundNo($data)
+ {
+ $order_refund_no = $data['order_refund_no'];
+
+ $order_refund_info = $this->model->where([
+ ['order_refund_no', '=', $order_refund_no],
+ ['member_id', '=', $this->member_id]
+ ])->findOrEmpty();
+ if ($order_refund_info->isEmpty()) throw new ApiException('SHOP_ORDER_IS_INVALID');//退款已失效
+ $order_goods_id = $order_refund_info['order_goods_id'];//订单id
+ $order_id = $order_refund_info['order_id'];//订单id
+ //查询订单项信息
+ $order_goods_model = new OrderGoods();
+ $order_goods_info = $order_goods_model->where([
+ ['order_goods_id', '=', $order_goods_id],
+ ['member_id', '=', $this->member_id]
+ ])->findOrEmpty();
+ if ($order_goods_info->isEmpty()) throw new ApiException('SHOP_ORDER_IS_INVALID');//订单已失效
+
+ $order = (new Order())->where([['order_id', '=', $order_id]])->findOrEmpty();
+ if ($order->isEmpty()) throw new ApiException('SHOP_ORDER_IS_INVALID');//订单已失效
+
+ //判断是否已经退过运费
+ $is_refund_delivery = $order_refund_info['is_refund_delivery'];
+ $refund_data = [
+ 'refund_money' => $order_goods_info['order_goods_money'],
+ 'is_refund_delivery' => $is_refund_delivery,
+ 'refund_order_goods_money' => $order_goods_info['order_goods_money']
+ ];
+ if($is_refund_delivery){
+ $refund_data['refund_money'] += $order['delivery_money'];
+ $refund_data['refund_delivery_money'] = $order['delivery_money'];
+ }
+ return $refund_data;
+ }
+
+}
diff --git a/niucloud/addon/shop/app/service/api/refund/RefundService.php b/niucloud/addon/shop/app/service/api/refund/RefundService.php
new file mode 100644
index 000000000..5256900eb
--- /dev/null
+++ b/niucloud/addon/shop/app/service/api/refund/RefundService.php
@@ -0,0 +1,72 @@
+model = new OrderRefund();
+ }
+
+ /**
+ * 分页列表
+ * @param array $where
+ * @return array
+ */
+ public function getPage(array $where)
+ {
+ $field = 'refund_id, order_id, order_goods_id, order_refund_no, refund_type, reason, member_id, apply_money, money, status, create_time, transfer_time, remark, voucher, source, timeout, refund_no, delivery, shop_reason, refund_address';
+ $order = 'create_time desc';
+
+ $search_model = $this->model
+ ->where([ [ 'member_id', '=', $this->member_id ] ])
+ ->withSearch([ 'status' ], $where)
+ ->field($field)
+ ->with(
+ [
+ 'order_goods' => function($query) {
+ $query->field('order_goods_id, order_id, member_id, goods_id, sku_id, goods_name, sku_name, goods_image, sku_image, price, num, goods_money,discount_money, is_enable_refund, goods_type, order_goods_money, discount_money')->append([ 'goods_image_thumb_small' ]);
+ },
+ ])->order($order)->append([ 'status_name', 'refund_type_name' ]);
+ $list = $this->pageQuery($search_model);
+ return $list;
+ }
+
+ /**
+ * 详情
+ * @param string $order_refund_no
+ * @return array
+ */
+ public function getDetail(string $order_refund_no)
+ {
+ $field = 'refund_id, order_id, order_goods_id, order_refund_no, refund_type, reason, member_id, apply_money, money, status, create_time, transfer_time, remark, voucher, source, timeout, refund_no, delivery, shop_reason, refund_address';
+ $info = $this->model->where([ [ 'order_refund_no', '=', $order_refund_no ], [ 'member_id', '=', $this->member_id ] ])->field($field)
+ ->with([
+ 'order_goods' => function($query) {
+ $query->field('extend,order_goods_id, order_id, member_id, goods_id, sku_id, goods_name, sku_name, goods_image, sku_image, price, num, goods_money, discount_money, is_enable_refund, status, order_refund_no, delivery_status, verify_count, verify_expire_time, is_verify, goods_type')->append([ 'goods_image_thumb_small' ]);
+ },
+ 'refund_log' => function($query) {
+ $query->field('order_refund_no, content, main_type, create_time ,main_id,type')->order("create_time desc, id desc")->append([ 'main_name', 'main_type_name', 'type_name' ]);
+ }
+ ])->append([ 'status_name', 'refund_type_name' ])->findOrEmpty()->toArray();
+
+ return $info;
+ }
+}
diff --git a/niucloud/addon/shop/app/service/core/CoreStatService.php b/niucloud/addon/shop/app/service/core/CoreStatService.php
new file mode 100644
index 000000000..b0f2a7f80
--- /dev/null
+++ b/niucloud/addon/shop/app/service/core/CoreStatService.php
@@ -0,0 +1,170 @@
+ date('Y-m-d', time()),
+ 'date_time' => strtotime(date('Y-m-d', time()))
+ ];
+ $stat = ( new ShopStat() )->where($stat_data)->findOrEmpty();
+ if ($stat->isEmpty()) {
+ $stat->allowField(array_merge(array_keys($stat_data), self::STAT_FIELD))->save(array_merge($stat_data, $data));
+ } else {
+ foreach ($data as $key => $value) {
+ $stat->$key = Db::raw("{$key} + {$value}");
+ }
+ $stat->allowField(self::STAT_FIELD)->save();
+ }
+ return true;
+ }
+
+ /**
+ * 累减统计数据
+ * @param $data
+ * @return true
+ */
+ public static function decStat($data = [])
+ {
+ $time = strtotime($data['time']);
+ // 更新天统计
+ $stat_data = [
+ 'date' => date('Y-m-d', $time),
+ 'date_time' => strtotime(date('Y-m-d', $time))
+ ];
+
+ $stat = ( new ShopStat() )->where($stat_data)->findOrEmpty();
+ if (!$stat->isEmpty()) {
+ unset($data[ 'time' ]);
+ foreach ($data as $key => $value) {
+ $stat->$key = Db::raw("CASE WHEN {$key} - {$value} >= 0 THEN {$key} - {$value} ELSE 0 END");
+ }
+ $stat->allowField(self::STAT_FIELD)->save();
+ }
+ return true;
+ }
+
+ /**
+ * 获取时间区间内天统计数据
+ * @param string $start_date
+ * @param string $end_date
+ * @return void
+ */
+ public function getStatData(string $start_date, string $end_date)
+ {
+ $start_date = strtotime($start_date);
+ $end_date = strtotime($end_date);
+
+ $field = implode(',', array_merge(self::STAT_FIELD, [ 'date' ]));
+ $stat_data = ( new ShopStat() )->where([ [ 'date_time', '>=', $start_date ], [ 'date_time', '<=', $end_date ] ])->field($field)->select()->toArray();
+ $stat_data = !empty($stat_data) ? array_column($stat_data, null, 'date') : [];
+
+ $data = [];
+ $day = ceil(( $end_date - $start_date ) / 86400);
+ foreach (self::STAT_FIELD as $field) {
+ $value = [];
+ $time = [];
+ for ($i = 0; $i < $day; $i++) {
+ $date = date('Y-m-d', $start_date + $i * 86400);
+ $time[] = $date;
+
+ $value[] = isset($stat_data[ $date ]) && isset($stat_data[ $date ][ $field ]) ? $stat_data[ $date ][ $field ] : 0;
+ }
+ $data[ $field ] = $value;
+ $data[ 'time' ] = $time;
+ }
+
+ return $data;
+ }
+
+ /**
+ * 获取时间区间内小时统计数据
+ * @param string $date
+ * @return array
+ */
+ public function getHourStatData( string $date)
+ {
+ $field = implode(',', array_merge(self::STAT_FIELD, [ 'hour' ]));
+ $stat_data = ( new ShopStat() )->where([ [ 'date_time', '=', strtotime($date) ] ])->field($field)->select()->toArray();
+ $stat_data = !empty($stat_data) ? array_column($stat_data, null, 'hour') : [];
+
+ $data = [];
+ foreach (self::STAT_FIELD as $field) {
+ $value = [];
+ for ($i = 0; $i < 24; $i++) {
+ $value[ $i ] = isset($stat_data[ $i ]) && isset($stat_data[ $i ][ $field ]) ? $stat_data[ $i ][ $field ] : 0;
+ }
+ $data[ $field ] = $value;
+ }
+ $data[ 'time' ] = array_map(function($value) {
+ return $value . '时';
+ }, range(0, 23, 1));
+
+ return $data;
+ }
+
+ /**
+ * 查询统计总和
+ * @param string $start_date
+ * @param string $end_date
+ * @return array
+ */
+ public function getStat( string $start_date = '', string $end_date = '')
+ {
+ $condition = [
+ [ 'id', '>', 0 ]
+ ];
+
+ if (!empty($start_date) && !empty($end_date)) {
+ $condition[] = [ 'date_time', '>=', strtotime($start_date) ];
+ $condition[] = [ 'date_time', '<=', strtotime($end_date) ];
+ } else if (!empty($start_date)) {
+ $condition[] = [ 'date_time', '=', strtotime($start_date) ];
+ }
+
+ $field = array_map(function($field) {
+ return "IFNULL(sum({$field}), 0) as {$field}";
+ }, self::STAT_FIELD);
+
+ if ($start_date == '' && $end_date == '') {
+ $condition[] = [ 'date_time', '>', 0 ];
+ }
+
+ $stat_data = ( new ShopStat() )->where($condition)->field(implode(',', $field))->findOrEmpty()->toArray();
+
+ return $stat_data;
+ }
+}
diff --git a/niucloud/addon/shop/app/service/core/cart/CoreCartService.php b/niucloud/addon/shop/app/service/core/cart/CoreCartService.php
new file mode 100644
index 000000000..4a53477a9
--- /dev/null
+++ b/niucloud/addon/shop/app/service/core/cart/CoreCartService.php
@@ -0,0 +1,40 @@
+model = new Cart();
+ }
+
+ /**
+ * 删除购物车(专用于订单)
+ * @param $cart_ids
+ * @return bool
+ */
+ public function deleteByCartIds($cart_ids)
+ {
+ $this->model->where([ [ 'id', 'in', $cart_ids ] ])->delete();
+ return true;
+ }
+
+}
diff --git a/niucloud/addon/shop/app/service/core/coupon/CoreCouponMemberService.php b/niucloud/addon/shop/app/service/core/coupon/CoreCouponMemberService.php
new file mode 100644
index 000000000..ad01e0fc7
--- /dev/null
+++ b/niucloud/addon/shop/app/service/core/coupon/CoreCouponMemberService.php
@@ -0,0 +1,267 @@
+model = new CouponMember();
+ }
+
+ /**
+ * 通过会员id查询会员有效可用的优惠券
+ * @param $member_id
+ * @return mixed
+ */
+ public function getUseCouponListByMemberId($member_id)
+ {
+ $where = array(
+ ['member_id', '=', $member_id],
+ ['status', '=', CouponMemberDict::WAIT_USE],
+ ['expire_time', '>', time()]
+ );
+ $field = 'id, coupon_id, member_id, create_time, expire_time, use_time, type, status, price, min_condition_money, title';
+ return $this->model->where($where)->field($field)->with([
+ 'goods'
+ ])->select()->toArray();
+ }
+
+ /**
+ * 查询会员优惠券
+ * @param $id
+ * @return array
+ * @throws \think\db\exception\DataNotFoundException
+ * @throws \think\db\exception\DbException
+ * @throws \think\db\exception\ModelNotFoundException
+ */
+ public function getUseCouponById($id)
+ {
+ $where = array(
+ ['id', '=', $id],
+ ['status', '=', CouponMemberDict::WAIT_USE]
+ );
+ $field = 'id, coupon_id, member_id, create_time, expire_time, use_time, type, status, price, min_condition_money, title';
+ return $this->model->where($where)->field($field)->with([
+ 'goods'
+ ])->findOrEmpty()->toArray();
+ }
+
+ /**
+ * 恢复(只单个恢复)
+ * @return void
+ */
+ public function recover($ids)
+ {
+ if (!is_array($ids)) {
+ $ids = [$ids];
+ }
+ $where = array(
+ ['id', 'in', $ids],
+ ['status', '=', CouponMemberDict::USED]
+ );
+
+ $coupon_member_list = $this->model->where($where)->select();
+ if ($coupon_member_list->isEmpty()) {
+ return true;
+ }
+ //恢复没必要返还错误
+ //判断使用时间是否过期
+ $update = [];
+ foreach ($coupon_member_list as $item) {
+ if (time() >= $item->expire_time) {
+ $status = CouponMemberDict::EXPIRE;
+ } else {
+ $status = CouponMemberDict::WAIT_USE;
+ }
+ $update[] = [
+ 'id' => $item->id,
+ 'status' => $status,
+ 'trade_id' => 0,
+ 'use_time' => 0,
+ ];
+ }
+ $this->model->saveAll($update);
+ return true;
+ }
+
+ /**
+ * 失效
+ * @param $ids
+ * @return void
+ */
+ public function invalid($ids)
+ {
+ $where = [
+ ['id', 'in', $ids],
+ ['status', '=', CouponMemberDict::WAIT_USE]
+ ];
+ $data = [
+ 'status' => CouponMemberDict::INVALID
+ ];
+ $this->model->where($where)->update($data);
+ return true;
+ }
+
+ /**
+ * 过期
+ * @param $ids
+ * @return void
+ */
+ public function expire($ids)
+ {
+ $where = [
+ ['id', 'in', $ids],
+ ['status', '=', CouponMemberDict::WAIT_USE]
+ ];
+ $data = [
+ 'status' => CouponMemberDict::EXPIRE
+ ];
+ $this->model->where($where)->update($data);
+ return true;
+ }
+
+ /**
+ * 使用
+ * @param array $data
+ * @return void
+ */
+ public function use(array $data)
+ {
+ $id = $data['id'];
+ $where = array(
+ ['id', '=', $id],
+ ['status', '=', CouponMemberDict::WAIT_USE]
+ );
+ $coupon = $this->model->where($where)->findOrEmpty();
+ if ($coupon->isEmpty()) throw new CommonException('SHOP_COUPON_IS_USED_OR_EXIST');//优惠券不存在或已使用
+ $coupon->save(
+ [
+ 'status' => CouponMemberDict::USED,
+ 'trade_id' => $data['trade_id'],
+ 'use_time' => time()
+ ]
+ );
+ return true;
+ }
+
+ /**
+ * 发放优惠券
+
+ * @param $member_ids
+ * @param $coupon_id
+ * @param $num
+ * @return false|int
+ */
+ public function sendCoupon($member_ids, $coupon_id, $num)
+ {
+ if (!is_array($member_ids)) {
+ $member_ids = [$member_ids];
+ }
+
+ $give_count = 0;
+ $coupon = (new Coupon())->where([['id', '=', $coupon_id], ['status', '=', CouponDict::NORMAL]])->findOrEmpty();
+ if ($coupon->isEmpty()) {
+ return $give_count;
+ }
+ // 剩余数量不足
+// if ($coupon[ 'remain_count' ] != '-1' && $coupon[ 'remain_count' ] < $num) {
+// throw new CommonException('COUPON_STOCK_INSUFFICIENT');
+// }
+//
+// if (strtotime($coupon[ 'start_time' ]) > 0) {
+// $time = time();
+// if ($time < strtotime($coupon[ 'start_time' ])) {
+// throw new CommonException('COUPON_RECEIVE_NOT_TIME');//优惠券不在领取时间范围内
+// }
+// if ($time > strtotime($coupon[ 'end_time' ])) {
+// throw new CommonException('COUPON_RECEIVE_NOT_TIME');//优惠券不在领取时间范围内
+// }
+// }
+
+ if ($coupon['valid_type'] == 1) {
+ $expire_time = 86400 * $coupon['length'] + time();
+ } else {
+ $expire_time = strtotime($coupon['valid_end_time']);
+ }
+
+ $member_coupon_data = [];
+ foreach ($member_ids as $member_id) {
+ for ($i = 0; $i < $num; $i++) {
+ $member_coupon_data[] = [
+ 'coupon_id' => $coupon_id,
+ 'member_id' => $member_id,
+ 'create_time' => time(),
+ 'expire_time' => $expire_time,
+ 'receive_type' => 'send',
+ 'type' => $coupon['type'],
+ 'title' => $coupon['title'],
+ 'price' => $coupon['price'],
+ 'status' => CouponMemberDict::WAIT_USE,
+ 'min_condition_money' => $coupon['min_condition_money']
+ ];
+ }
+ $give_count += $num;
+ }
+
+
+ $this->model->insertAll($member_coupon_data);
+
+ $coupon->give_count += $give_count;
+// if ($coupon[ 'remain_count' ] != -1) {
+// $coupon->remain_count -= $num;
+// }
+ $coupon->save();
+
+ return $give_count;
+ }
+
+ /**
+ * 刷新用户优惠券过期时间
+ * @param $coupon_id
+ * @return void
+ */
+ public function refeshMemberCouponExpireTime($coupon_id)
+ {
+ $coupon_info = (new Coupon())->where([
+ ['id', '=', $coupon_id]
+ ])->findOrEmpty($coupon_id)->toArray();
+ if ($coupon_info['valid_type'] == 1) {
+ $time = 86400 * $coupon_info['length'];
+ $this->model->where([
+ ['coupon_id', '=', $coupon_id]
+ ])->update([
+ 'expire_time' => Db::raw("create_time +{$time}")
+ ]);
+ } else {
+ $this->model->where([
+ ['coupon_id', '=', $coupon_id]
+ ])->update([
+ 'expire_time' => strtotime($coupon_info['valid_end_time'])
+ ]);
+ }
+ }
+
+}
diff --git a/niucloud/addon/shop/app/service/core/delivery/CoreCompanyService.php b/niucloud/addon/shop/app/service/core/delivery/CoreCompanyService.php
new file mode 100644
index 000000000..a0659e2c3
--- /dev/null
+++ b/niucloud/addon/shop/app/service/core/delivery/CoreCompanyService.php
@@ -0,0 +1,68 @@
+create($data);
+ return true;
+ }
+
+ /**
+ * 批量添加物流公司
+ * @param $data
+ * @return bool
+ */
+ public function addAll($data)
+ {
+ ( new Company() )->insertAll($data);
+ return true;
+ }
+
+ /**
+ * 获取物流公司信息
+ * @param array $condition
+ * @param string $field
+ * @return mixed
+ */
+ public function getInfo(array $condition, $field = 'company_id,company_name,logo,url,express_no,express_no_electronic_sheet,electronic_sheet_switch,print_style,exp_type')
+ {
+ $info = ( new Company() )->field($field)->where($condition)->findOrEmpty()->toArray();
+ return $info;
+ }
+
+ /**
+ * 获取物流公司列表
+ * @param array $condition
+ * @param string $field
+ * @return array
+ */
+ public function getList(array $condition = [], $field = 'company_id,company_name,logo,url,express_no,express_no_electronic_sheet,electronic_sheet_switch,print_style,exp_type')
+ {
+ $order = 'create_time desc';
+ return ( new Company() )->where($condition)->field($field)->order($order)->select()->toArray();
+ }
+
+}
diff --git a/niucloud/addon/shop/app/service/core/delivery/CoreConfigService.php b/niucloud/addon/shop/app/service/core/delivery/CoreConfigService.php
new file mode 100644
index 000000000..264ccba3a
--- /dev/null
+++ b/niucloud/addon/shop/app/service/core/delivery/CoreConfigService.php
@@ -0,0 +1,78 @@
+setConfig( 'DELIVERY_INTERFACE', $data);
+ }
+
+ /**
+ * 获取快递鸟、快递100配置
+ * @return array
+ */
+ public function getDeliverySearchConfig()
+ {
+ $info = ( new ConfigService() )->getConfig( 'DELIVERY_INTERFACE');
+ if (empty($info)) {
+ $info = [];
+ $info[ 'value' ] = [
+ 'interface_type' => 1,
+ 'kdniao_id' => '',
+ 'kdniao_app_key' => '',
+ 'kdniao_is_pay' => 1,
+ 'kd100_app_key' => '',
+ 'kd100_customer' => 0
+ ];
+ } else {
+ $info[ 'value' ][ 'interface_type' ] = intval($info[ 'value' ][ 'interface_type' ]);
+ }
+ return $info[ 'value' ];
+ }
+
+
+ /**
+ * 获取快递鸟、快递100电子面单配置
+ * @return array
+ */
+ public function getDeliveryElectronSheeticConfig()
+ {
+ $info = ( new ConfigService() )->getConfig( 'ELECTRONIC_SHEET_CONFIG');
+ if (empty($info)) {
+ $info = [];
+ $info[ 'value' ] = [
+ 'interface_type' => 'kdbird', // 接口类型,kdbird:快递鸟,后期支持扩展
+ 'kdniao_id' => '',
+ 'kdniao_api_key' => '',
+ 'server_port1' => '8000',
+ 'server_port2' => '18000',
+ 'https_port' => '8443'
+ ];
+ }
+ return $info[ 'value' ];
+ }
+}
diff --git a/niucloud/addon/shop/app/service/core/delivery/CoreDeliveryService.php b/niucloud/addon/shop/app/service/core/delivery/CoreDeliveryService.php
new file mode 100644
index 000000000..5277a1cd2
--- /dev/null
+++ b/niucloud/addon/shop/app/service/core/delivery/CoreDeliveryService.php
@@ -0,0 +1,191 @@
+core_config_service = new CoreConfigService();
+ }
+
+ /**
+ * 配置设置
+ * @param array $params
+ * @return array
+ */
+
+ public function setConfig($key, $data)
+ {
+ $this->core_config_service->setConfig($key, $data);
+ return true;
+ }
+
+ public function getConfig($key)
+ {
+ return $this->core_config_service->getConfig($key);
+ }
+
+ /**
+ * 物流
+ */
+ public function getExpressConfig()
+ {
+ $data = (new CoreConfigService())->getConfigValue('SHOP_DELIVERY_CONFIG');
+ if (empty($data)) {
+ $expressInfo = [
+ 'name' => '物流配送',
+ 'status' => '',
+ 'key' => 'express',
+ 'desc' => '买家下单可以选择快递发货'
+ ];
+ } else {
+ $expressInfo = $data[array_search('express', array_column($data, 'key'))];
+ }
+ return $expressInfo;
+ }
+
+ /**
+ * 同城
+ */
+ public function getLocalDeliveryConfig()
+ {
+ $data = (new CoreConfigService())->getConfigValue('SHOP_DELIVERY_CONFIG');
+ if (empty($data)) {
+ $localDeliveryInfo = [
+ 'name' => '同城配送',
+ 'status' => '',
+ 'key' => 'local_delivery',
+ 'desc' => '在配送范围内的买家可以选择同城配送'
+ ];
+ } else {
+ $localDeliveryInfo = $data[array_search('local_delivery', array_column($data, 'key'))];
+ }
+ return $localDeliveryInfo;
+ }
+
+ /**
+ * 门店
+ */
+ public function getStoreConfig()
+ {
+ $data = (new CoreConfigService())->getConfigValue('SHOP_DELIVERY_CONFIG');
+ if (empty($data)) {
+ $storeInfo = [
+ 'name' => '门店配送',
+ 'status' => '',
+ 'key' => 'store',
+ 'desc' => '买家可选择自提点提货'
+ ];
+ } else {
+ $storeInfo = $data[array_search('store', array_column($data, 'key'))];
+ }
+ return $storeInfo;
+ }
+
+
+ /**
+ * 查询物流配置
+ * @return array
+ */
+ public function getDeliveryConfig()
+ {
+ $data = (new CoreConfigService())->getConfigValue('SHOP_DELIVERY_CONFIG');
+ if (empty($data)) {
+ $list = [
+ 'express' => [
+ 'name' => '物流配送',
+ 'status' => 1,
+ 'key' => 'express',
+ 'desc' => '买家下单可以选择快递发货'
+ ],
+ 'local_delivery' => [
+ 'name' => '同城配送',
+ 'status' => 1,
+ 'key' => 'local_delivery',
+ 'desc' => '在配送范围内的买家可以选择同城配送'
+ ],
+ 'store' => [
+ 'name' => '门店自提',
+ 'status' => 1,
+ 'key' => 'store',
+ 'desc' => '买家可选择自提点提货'
+ ]
+ ];
+ } else {
+ $desc_arr = [
+ 'express' => '买家下单可以选择快递发货',
+ 'local_delivery' => '在配送范围内的买家可以选择同城配送',
+ 'store' => '买家可选择自提点提货',
+ ];
+ foreach ($data as $value) {
+ $list[$value['key']] = [
+ 'name' => $value['name'],
+ 'status' => $value['status'],
+ 'key' => $value['key'],
+ 'desc' => $value['desc'] ?? $desc_arr[$value['key']]
+ ];
+ }
+ }
+ return $list;
+ }
+
+ /**
+ * 查询物流配置
+ * @return array
+ */
+ public function getDeliveryList()
+ {
+ $deliver = (new CoreConfigService())->getConfigValue('SHOP_DELIVERY_CONFIG');
+ foreach ($deliver as $value) {
+ $list[$value['key']] = [
+ 'name' => $value['name'],
+ 'status' => $value['status'],
+ 'key' => $value['key']
+ ];
+ }
+ if (empty($deliver)) {
+ $deliver = [
+ [
+ 'name' => '物流配送',
+ 'status' => 1,
+ 'key' => 'express'
+ ],
+ [
+ 'name' => '同城配送',
+ 'status' => 1,
+ 'key' => 'local_delivery'
+ ],
+ [
+ 'name' => '门店自提',
+ 'status' => 1,
+ 'key' => 'store'
+ ],
+ ];
+ }
+ return $deliver;
+ }
+
+}
diff --git a/niucloud/addon/shop/app/service/core/delivery/CoreElectronicSheetService.php b/niucloud/addon/shop/app/service/core/delivery/CoreElectronicSheetService.php
new file mode 100644
index 000000000..b78744654
--- /dev/null
+++ b/niucloud/addon/shop/app/service/core/delivery/CoreElectronicSheetService.php
@@ -0,0 +1,659 @@
+setConfig( 'ELECTRONIC_SHEET_CONFIG', $data);
+ }
+
+ /**
+ * 获取电子面单设置
+ * @return array|mixed
+ */
+ public function getElectronicSheetConfig()
+ {
+ $info = ( new ConfigService() )->getConfig('ELECTRONIC_SHEET_CONFIG');
+ if (empty($info)) {
+ $info = [];
+ $info[ 'value' ] = [
+ 'interface_type' => 'kdbird', // 接口类型,kdbird:快递鸟,后期支持扩展
+ 'kdniao_id' => '',
+ 'kdniao_api_key' => '',
+ 'server_port1' => '8000',
+ 'server_port2' => '18000',
+ 'https_port' => '8443'
+ ];
+ }
+ return $info[ 'value' ];
+ }
+
+ /**
+ * 添加电子面单模板
+ * @param $data
+ * @return bool
+ */
+ public function add( $data)
+ {
+ ( new ElectronicSheet() )->create($data);
+ return true;
+ }
+
+ /**
+ * 批量添加电子面单模板
+ * @param $data
+ * @return bool
+ */
+ public function addAll($data)
+ {
+ ( new ElectronicSheet() )->insertAll($data);
+ return true;
+ }
+
+ /**
+ * 获取电子面单信息
+ * @param array $condition
+ * @param string $field
+ * @return array
+ */
+ public function getInfo($condition = [], $field = 'id,template_name,express_company_id,customer_name,customer_pwd,send_site,send_staff,month_code,pay_type,is_notice,status,exp_type,print_style,is_default,interface_data,temp_id,child_temp_id,back_temp_id')
+ {
+ $info = ( new ElectronicSheet() )->field($field)->where($condition)->withJoin([
+ 'company' => [ 'company_name', 'express_no_electronic_sheet' ,'kd100_express_no_electronic_sheet']
+ ])->append(['kdbird_config', 'kd100_config'])->findOrEmpty()
+ ->toArray();
+ return $info;
+ }
+
+ /**
+ * 打印电子面单
+ * @param $params
+ * @return mixed
+ */
+ public function printElectronicSheet($params)
+ {
+ $es_config = $this->getElectronicSheetConfig();
+
+ // 查询订单信息
+ $order_model = new Order();
+ $field = 'order_id, order_no, member_id, taker_name, taker_mobile, taker_province, taker_city, taker_district, taker_address,delivery_money';
+ $order_list = $order_model->where([
+ [ 'order_id', 'in', $params[ 'order_id' ] ],
+ [ 'delivery_type', '=', DeliveryDict::EXPRESS ], // 物流配送
+ [ 'status', 'in', [ OrderDict::WAIT_DELIVERY, OrderDict::WAIT_TAKE ] ], // 待发货、待收货状态下
+ ])->field($field)
+ ->with(
+ [
+ 'order_goods' => function($query) {
+ $query->field('order_goods_id,order_id, sku_id, goods_name, sku_name, num,status,delivery_id');
+ }
+ ])->select()->toArray();
+
+ if (empty($order_list)) {
+ throw new CommonException('SHOP_ORDER_NOT_FOUND');
+ }
+
+ $sys_area_model = new SysArea();
+
+ // 查询商家地址库(默认)
+ $shop_address_model = new ShopAddress();
+ $default_shop_address = $shop_address_model->where([
+ [ 'is_delivery_address', '=', 1 ],
+ [ 'is_default_delivery', '=', 1 ]
+ ])->field('contact_name,mobile,province_id,city_id,district_id,address')->findOrEmpty()->toArray();
+
+ if (empty($default_shop_address)) {
+ throw new CommonException('SHOP_ADDRESS_DEFAULT_EMPTY');
+ }
+
+ $sender_province_name = $sys_area_model->where([ [ 'id', '=', $default_shop_address[ 'province_id' ] ] ])->field('name')->findOrEmpty()->toArray()[ 'name' ] ?? '';
+ $sender_city_name = $sys_area_model->where([ [ 'id', '=', $default_shop_address[ 'city_id' ] ] ])->field('name')->findOrEmpty()->toArray()[ 'name' ] ?? '';
+ $sender_exp_area_name = $sys_area_model->where([ [ 'id', '=', $default_shop_address[ 'district_id' ] ] ])->field('name')->findOrEmpty()->toArray()[ 'name' ] ?? '';
+
+ $goods_sku_model = new GoodsSku();
+
+ // 替换商品名称中的特殊字符 ' " # & + < > % \
+ $search = array( "'", '"', '&', '+', '<', '>', '%', "\\", '#', "and" );
+
+ $result = [];
+
+ // 打印方式,single:单订单,multiple:多订单
+
+ if ($params[ 'print_type' ] == 'single') {
+ // 单订单打印,按照包裹拆分打印
+
+ foreach ($params[ 'list' ] as $k => $v) {
+ // 查询电子面单模板
+ $es_template_info = $this->getInfo([
+ [ 'id', '=', $v[ 'electronic_sheet_id' ] ],
+ [ 'status', '=', 1 ]
+ ], 'express_company_id,customer_name,customer_pwd,send_site,send_staff,month_code,pay_type,is_notice,exp_type,print_style,interface_data,temp_id,child_temp_id,back_temp_id');
+
+ if (empty($es_template_info)) {
+ // 电子面单模板不存在
+ continue;
+ }
+
+ if ($es_template_info[ 'print_style' ] == '0') {
+ $es_template_info[ 'print_style' ] = '';
+ }
+
+ foreach ($order_list as $ck => $cv) {
+
+ $key = $es_template_info[ 'company' ][ 'express_no_electronic_sheet' ] . '_' . $cv[ 'order_no' ]
+ . '_' . $es_config[ 'kdniao_id' ] . '_' . $es_template_info[ 'print_style' ]
+ . '_' . $v[ 'delivery_id' ] . '_' . $k;
+
+ $cache = Cache::get($key);
+ if (!empty($cache)) {
+ $cache[ 'delivery_id' ] = $v[ 'delivery_id' ];
+ $result[] = $cache;
+ continue;
+ }
+
+ $commodity = []; // 商品信息
+ $weight_total = 0; // 包裹总重量kg
+ $volume_total = 0; // 包裹总体积 m³
+ $remark = []; // 备注
+ foreach ($cv[ 'order_goods' ] as $og_k => $og_v) {
+ // 排除退款订单项
+ if ($og_v[ 'status' ] != 1) {
+ continue;
+ }
+
+ // 排除 无需物流的订单项
+ if (empty($og_v[ 'delivery_id' ])) {
+ continue;
+ }
+
+ // 排除不是一个包裹
+ if ($og_v[ 'delivery_id' ] != $v[ 'delivery_id' ]) {
+ continue;
+ }
+
+ $order_goods_delivery = ( new OrderDelivery() )
+ ->where([
+ [ 'order_id', '=', $cv[ 'order_id' ] ],
+ [ 'id', '=', $og_v[ 'delivery_id' ] ],
+ [ 'delivery_type', '=', 'express' ],
+ [ 'sub_delivery_type', '=', 'express' ]
+ ])
+ ->field('id, order_id, delivery_type, sub_delivery_type,express_company_id, express_number')
+ ->findOrEmpty()->toArray();
+
+ // 只打印 物流配送的订单项
+ if (!empty($order_goods_delivery)) {
+ $commodity[] = [
+ 'GoodsName' => str_replace($search, '', mb_substr($og_v[ 'goods_name' ] . ' ' . $og_v[ 'sku_name' ], 0, 50, 'UTF-8')),
+ 'GoodsQuantity' => $og_v[ 'num' ]
+ ];
+// $remark[] = str_replace($search, '', mb_substr($og_v[ 'goods_name' ] . ' ' . $og_v[ 'sku_name' ], 0, 50, 'UTF-8'));
+ $goods_sku_info = $goods_sku_model->field('weight,volume')->where([ [ 'sku_id', '=', $og_v[ 'sku_id' ] ] ])->findOrEmpty()->toArray();
+ if (!empty($goods_sku_info)) {
+ $weight_total += number_format($goods_sku_info[ 'weight' ], 3);
+ $volume_total += number_format($goods_sku_info[ 'volume' ], 3);
+ }
+ }
+
+ }
+
+ if (empty($commodity)) {
+ $result[] = [
+ 'success' => false,
+ 'result_code' => -1,
+ 'reason' => '该订单不支持打印电子面单',
+ 'order_no' => $cv[ 'order_no' ]
+ ];
+ continue;
+ }
+
+ $receiver_province_name = $sys_area_model->where([ [ 'id', '=', $cv[ 'taker_province' ] ] ])->field('name')->findOrEmpty()->toArray()[ 'name' ] ?? '';
+ $receiver_city_name = $sys_area_model->where([ [ 'id', '=', $cv[ 'taker_city' ] ] ])->field('name')->findOrEmpty()->toArray()[ 'name' ] ?? '';
+ $receiver_exp_area_name = $sys_area_model->where([ [ 'id', '=', $cv[ 'taker_district' ] ] ])->field('name')->findOrEmpty()->toArray()[ 'name' ] ?? '';
+
+ $api_data = [
+ 'cache_key' => $key,
+// 'ShipperCode' => $es_template_info[ 'company' ][ 'express_no_electronic_sheet' ], // 快递公司编码
+// 'CustomerName' => $es_template_info[ 'customer_name' ], // 电子面单账号,申请:https://www.yuque.com/kdnjishuzhichi/rg4owd
+// 'CustomerPwd' => $es_template_info[ 'customer_pwd' ], // 电子面单密码,电子面单账号对照表:https://www.yuque.com/kdnjishuzhichi/dfcrg1/hrfw43
+// 'SendSite' => $es_template_info[ 'send_site' ],
+// 'SendStaff' => $es_template_info[ 'send_staff' ],
+// 'MonthCode' => $es_template_info[ 'month_code' ], // 月结账号
+// 'PayType' => $es_template_info[ 'pay_type' ], // 运费支付方式(1:现付,2:到付,3:月结)
+// 'ExpType' => $es_template_info[ 'exp_type' ], // 快递业务类型,https://www.yuque.com/kdnjishuzhichi/dfcrg1/hgx758hom5p6wz0l
+// 'TemplateSize' => $es_template_info[ 'print_style' ], // 模板规格,https://www.yuque.com/kdnjishuzhichi/dfcrg1/vpptucr1q5ahcxa7#iZvLV
+// 'IsNotice' => $es_template_info[ 'is_notice' ], // 是否通知快递员上门揽件跨越速运,京东快运必填
+
+ 'es_template_info'=>$es_template_info,
+ 'OrderCode' => $cv[ 'order_no' ] . $k, // 订单编号,多包裹防重复,要增加下标
+ // 发件人信息
+ 'Sender' => [
+ 'Name' => $default_shop_address[ 'contact_name' ], // 发件人
+ 'Mobile' => $default_shop_address[ 'mobile' ], // 手机
+ 'ProvinceName' => $sender_province_name, // 发件省
+ 'CityName' => $sender_city_name, // 发件市
+ 'ExpAreaName' => $sender_exp_area_name, // 发件区
+ 'Address' => $default_shop_address[ 'address' ], // 发件人详细地址
+ 'PostCode' => '000000' // 发件地邮编邮政/EMS 必填可填000000
+ ],
+ // 收件人信息
+ 'Receiver' => [
+ 'Name' => $cv[ 'taker_name' ], // 收件人
+ 'Mobile' => $cv[ 'taker_mobile' ], // 电话
+ 'ProvinceName' => $receiver_province_name, // 收件省
+ 'CityName' => $receiver_city_name, // 收件市
+ 'ExpAreaName' => $receiver_exp_area_name, // 收件区
+ 'Address' => mb_substr($cv[ 'taker_address' ], 0, 100, 'UTF-8'), // 收件人详细地址
+ 'PostCode' => '000000' // 收件地邮编邮政/EMS 必填可填000000
+ ],
+ 'Quantity' => count($cv[ 'order_goods' ]) > 50 ? 50 : count($cv[ 'order_goods' ]), // 包裹数 (至少填1,最多50)
+ // 商品信息
+ 'Commodity' => $commodity,
+ 'Weight' => $weight_total, // 包裹总重量kg,京东、快运类必填
+ 'Volume' => $volume_total, // 包裹总体积 m³,京东、快运类必填
+ 'Cost' => $cv[ 'delivery_money' ], // 快递运费
+ 'Remark' => '', // '
' . mb_substr(implode('
', $remark), 0, 80, 'UTF-8'), // 备注
+ 'IsReturnPrintTemplate' => 1, // 是否返回电子面单模板:(不填默认为0)0:不需要,1:需要
+ ];
+
+ $class = new ElectronicSheetSearchLoader();
+ $temp_result = $class->electronicSheet($api_data);
+ $temp_result[ 'order_no' ] = $cv[ 'order_no' ]; // 记录打印的 订单号
+ $temp_result[ 'delivery_id' ] = $v[ 'delivery_id' ]; // 记录打印的 包裹id
+
+ $result[] = $temp_result;
+ }
+
+ }
+
+ return $result;
+
+ } elseif ($params[ 'print_type' ] == 'multiple') {
+ // 多订单打印,一个订单一个电子面单
+ // 查询电子面单模板
+ if (!empty($params[ 'electronic_sheet_id' ])) {
+ $es_template_info = $this->getInfo([
+ [ 'id', '=', $params[ 'electronic_sheet_id' ] ],
+ [ 'status', '=', 1 ]
+ ], 'express_company_id,customer_name,customer_pwd,send_site,send_staff,month_code,pay_type,is_notice,exp_type,print_style,interface_data,temp_id,child_temp_id,back_temp_id');
+ } else {
+ $es_template_info = $this->getInfo([
+ [ 'is_default', '=', 1 ],
+ [ 'status', '=', 1 ]
+ ], 'express_company_id,customer_name,customer_pwd,send_site,send_staff,month_code,pay_type,is_notice,exp_type,print_style,interface_data,temp_id,child_temp_id,back_temp_id');
+ }
+
+ if (empty($es_template_info)) {
+ throw new CommonException('SHOP_ELECTRONIC_SHEET_TEMPLATE_FOUND');
+ }
+
+ if ($es_template_info[ 'print_style' ] == '0') {
+ $es_template_info[ 'print_style' ] = '';
+ }
+
+ // 查询指定订单项
+ if (!empty($params[ 'order_goods_ids' ])) {
+ foreach ($order_list as $k => $v) {
+ if ($v[ 'order_id' ] == $params[ 'order_id' ]) {
+ foreach ($v[ 'order_goods' ] as $ck => $cv) {
+ if (!in_array($cv[ 'order_goods_id' ], $params[ 'order_goods_ids' ])) {
+ unset($order_list[ $k ][ 'order_goods' ][ $ck ]);
+ }
+ }
+ $order_list[ $k ][ 'order_goods' ] = array_values($order_list[ $k ][ 'order_goods' ]);
+ }
+ }
+ }
+
+ foreach ($order_list as $k => $v) {
+
+ $order_goods_delivery_count = ( new OrderDelivery() )->where([
+ [ 'order_id', '=', $v[ 'order_id' ] ],
+ [ 'delivery_type', '=', 'express' ],
+ [ 'sub_delivery_type', '=', 'express' ]
+ ])->count();
+
+ if ($order_goods_delivery_count > 0) {
+ $order_goods_delivery_count--;
+ }
+
+ $key = $es_template_info[ 'company' ][ 'express_no_electronic_sheet' ] . '_' . $v[ 'order_no' ]
+ . '_' . $es_config[ 'kdniao_id' ]
+ . '_' . $es_template_info[ 'print_style' ] . '_' . $order_goods_delivery_count;
+
+ $cache = Cache::get($key);
+ if (!empty($cache)) {
+ $result[] = $cache;
+ continue;
+ }
+
+ $commodity = []; // 商品信息
+ $weight_total = 0; // 包裹总重量kg
+ $volume_total = 0; // 包裹总体积 m³
+ $remark = []; // 备注
+ foreach ($v[ 'order_goods' ] as $ck => $cv) {
+
+ // 排除退款订单项
+ if ($cv[ 'status' ] != 1) {
+ continue;
+ }
+
+ // 排除 无需物流的订单项
+ if (empty($cv[ 'delivery_id' ])) {
+ continue;
+ }
+
+ $order_goods_delivery = ( new OrderDelivery() )
+ ->where([
+ [ 'order_id', '=', $v[ 'order_id' ] ],
+ [ 'id', '=', $cv[ 'delivery_id' ] ],
+ [ 'delivery_type', '=', 'express' ],
+ [ 'sub_delivery_type', '=', 'express' ]
+ ])
+ ->field('id, order_id, delivery_type, sub_delivery_type,express_company_id, express_number')
+ ->findOrEmpty()->toArray();
+
+ // 只打印 物流配送的订单项
+ if (!empty($order_goods_delivery)) {
+ $commodity[] = [
+ 'GoodsName' => str_replace($search, '', mb_substr($cv[ 'goods_name' ] . ' ' . $cv[ 'sku_name' ], 0, 50, 'UTF-8')),
+ 'GoodsQuantity' => $cv[ 'num' ]
+ ];
+// $remark[] = str_replace($search, '', mb_substr($cv[ 'goods_name' ] . ' ' . $cv[ 'sku_name' ], 0, 50, 'UTF-8'));
+ $goods_sku_info = $goods_sku_model->field('weight,volume')->where([ [ 'sku_id', '=', $cv[ 'sku_id' ] ] ])->findOrEmpty()->toArray();
+ if (!empty($goods_sku_info)) {
+ $weight_total += number_format($goods_sku_info[ 'weight' ], 3);
+ $volume_total += number_format($goods_sku_info[ 'volume' ], 3);
+ }
+ }
+ }
+
+ if (empty($commodity)) {
+ $result[] = [
+ 'success' => false,
+ 'result_code' => -1,
+ 'reason' => '该订单不支持打印电子面单',
+ 'order_no' => $v[ 'order_no' ]
+ ];
+ continue;
+ }
+
+ $receiver_province_name = $sys_area_model->where([ [ 'id', '=', $v[ 'taker_province' ] ] ])->field('name')->findOrEmpty()->toArray()[ 'name' ] ?? '';
+ $receiver_city_name = $sys_area_model->where([ [ 'id', '=', $v[ 'taker_city' ] ] ])->field('name')->findOrEmpty()->toArray()[ 'name' ] ?? '';
+ $receiver_exp_area_name = $sys_area_model->where([ [ 'id', '=', $v[ 'taker_district' ] ] ])->field('name')->findOrEmpty()->toArray()[ 'name' ] ?? '';
+
+ $api_data = [
+ 'cache_key' => $key,
+// 'ShipperCode' => $es_template_info[ 'company' ][ 'express_no_electronic_sheet' ], // 快递公司编码
+// 'CustomerName' => $es_template_info[ 'customer_name' ], // 电子面单账号,申请:https://www.yuque.com/kdnjishuzhichi/rg4owd
+// 'CustomerPwd' => $es_template_info[ 'customer_pwd' ], // 电子面单密码,电子面单账号对照表:https://www.yuque.com/kdnjishuzhichi/dfcrg1/hrfw43
+// 'SendSite' => $es_template_info[ 'send_site' ],
+// 'SendStaff' => $es_template_info[ 'send_staff' ],
+// 'MonthCode' => $es_template_info[ 'month_code' ], // 月结账号
+ 'es_template_info'=> $es_template_info,
+ 'OrderCode' => $v[ 'order_no' ] . $order_goods_delivery_count, // 订单编号,多包裹防重复,要增加下标
+
+ 'PayType' => $es_template_info[ 'pay_type' ], // 运费支付方式(1:现付,2:到付,3:月结)
+ 'ExpType' => $es_template_info[ 'exp_type' ], // 快递业务类型,https://www.yuque.com/kdnjishuzhichi/dfcrg1/hgx758hom5p6wz0l
+
+ // 发件人信息
+ 'Sender' => [
+ 'Name' => $default_shop_address[ 'contact_name' ], // 发件人
+ 'Mobile' => $default_shop_address[ 'mobile' ], // 手机
+ 'ProvinceName' => $sender_province_name, // 发件省
+ 'CityName' => $sender_city_name, // 发件市
+ 'ExpAreaName' => $sender_exp_area_name, // 发件区
+ 'Address' => $default_shop_address[ 'address' ], // 发件人详细地址
+ 'PostCode' => '000000' // 发件地邮编邮政/EMS 必填可填000000
+ ],
+
+ // 收件人信息
+ 'Receiver' => [
+ 'Name' => $v[ 'taker_name' ], // 收件人
+ 'Mobile' => $v[ 'taker_mobile' ], // 电话
+ 'ProvinceName' => $receiver_province_name, // 收件省
+ 'CityName' => $receiver_city_name, // 收件市
+ 'ExpAreaName' => $receiver_exp_area_name, // 收件区
+ 'Address' => mb_substr($v[ 'taker_address' ], 0, 100, 'UTF-8'), // 收件人详细地址
+ 'PostCode' => '000000' // 收件地邮编邮政/EMS 必填可填000000
+ ],
+
+ 'Quantity' => count($v[ 'order_goods' ]) > 50 ? 50 : count($v[ 'order_goods' ]), // 包裹数 (至少填1,最多50)
+
+ // 商品信息
+ 'Commodity' => $commodity,
+ 'Weight' => $weight_total, // 包裹总重量kg,京东、快运类必填
+ 'Volume' => $volume_total, // 包裹总体积 m³,京东、快运类必填
+ 'Cost' => $v[ 'delivery_money' ], // 快递运费
+ 'Remark' => '',// '
' . mb_substr(implode('
', $remark), 0, 80, 'UTF-8'), // 备注
+
+ 'IsReturnPrintTemplate' => 1, // 是否返回电子面单模板:(不填默认为0)0:不需要,1:需要
+
+ 'TemplateSize' => $es_template_info[ 'print_style' ], // 模板规格,https://www.yuque.com/kdnjishuzhichi/dfcrg1/vpptucr1q5ahcxa7#iZvLV
+ 'IsNotice' => $es_template_info[ 'is_notice' ] // 是否通知快递员上门揽件跨越速运,京东快运必填
+ ];
+
+ $class = new ElectronicSheetSearchLoader();
+
+ $temp_result = $class->electronicSheet($api_data);
+ $temp_result[ 'order_no' ] = $v[ 'order_no' ]; // 记录打印的 订单号
+ $result[] = $temp_result;
+ }
+ return $result;
+ }
+ }
+
+ /**
+ * 发货的同时打印电子面单
+ * @param $params
+ * @return array|void
+ */
+ public function printElectronicSheetByDelivery($params)
+ {
+ $es_config = $this->getElectronicSheetConfig();
+ // 查询订单信息
+ $order_model = new Order();
+ $field = 'order_id, order_no, member_id, taker_name, taker_mobile, taker_province, taker_city, taker_district, taker_address,delivery_money';
+ $order_info = $order_model->where([
+ [ 'order_id', '=', $params[ 'order_id' ] ],
+ [ 'delivery_type', '=', DeliveryDict::EXPRESS ], // 物流配送
+ [ 'status', 'in', [ OrderDict::WAIT_DELIVERY, OrderDict::WAIT_TAKE ] ], // 待发货、待收货状态下
+ ])->field($field)->findOrEmpty()->toArray();
+
+ if (empty($order_info)) {
+ throw new CommonException('SHOP_ORDER_NOT_FOUND');
+ }
+
+ // 发货的同时打印电子面单
+ if (!empty($params[ 'order_goods_data' ])) {
+ $order_info[ 'order_goods' ] = $params[ 'order_goods_data' ];
+ }
+
+ $sys_area_model = new SysArea();
+
+ // 查询商家地址库(默认)
+ $shop_address_model = new ShopAddress();
+ $default_shop_address = $shop_address_model->where([
+ [ 'is_delivery_address', '=', 1 ],
+ [ 'is_default_delivery', '=', 1 ]
+ ])->field('contact_name,mobile,province_id,city_id,district_id,address')->findOrEmpty()->toArray();
+
+ if (empty($default_shop_address)) {
+ throw new CommonException('SHOP_ADDRESS_DEFAULT_EMPTY');
+ }
+
+ $sender_province_name = $sys_area_model->where([ [ 'id', '=', $default_shop_address[ 'province_id' ] ] ])->field('name')->findOrEmpty()->toArray()[ 'name' ] ?? '';
+ $sender_city_name = $sys_area_model->where([ [ 'id', '=', $default_shop_address[ 'city_id' ] ] ])->field('name')->findOrEmpty()->toArray()[ 'name' ] ?? '';
+ $sender_exp_area_name = $sys_area_model->where([ [ 'id', '=', $default_shop_address[ 'district_id' ] ] ])->field('name')->findOrEmpty()->toArray()[ 'name' ] ?? '';
+
+ $goods_sku_model = new GoodsSku();
+
+ // 替换商品名称中的特殊字符 ' " # & + < > % \
+ $search = array( "'", '"', '&', '+', '<', '>', '%', "\\", '#', "and" );
+
+ // 查询电子面单模板
+ if (!empty($params[ 'electronic_sheet_id' ])) {
+ $es_template_info = $this->getInfo([
+ [ 'id', '=', $params[ 'electronic_sheet_id' ] ],
+ [ 'status', '=', 1 ]
+ ], 'express_company_id,customer_name,customer_pwd,send_site,send_staff,month_code,pay_type,is_notice,exp_type,print_style,exp_type_name,interface_data,temp_id,child_temp_id,back_temp_id');
+ } else {
+ $es_template_info = $this->getInfo([
+ [ 'is_default', '=', 1 ],
+ [ 'status', '=', 1 ]
+ ], 'express_company_id,customer_name,customer_pwd,send_site,send_staff,month_code,pay_type,is_notice,exp_type,print_style,exp_type_name,interface_data,temp_id,child_temp_id,back_temp_id');
+ }
+
+ if (empty($es_template_info)) {
+ throw new CommonException('SHOP_ELECTRONIC_SHEET_TEMPLATE_FOUND');
+ }
+
+ if ($es_template_info[ 'print_style' ] == '0') {
+ $es_template_info[ 'print_style' ] = '';
+ }
+
+ $order_goods_delivery_count = ( new OrderDelivery() )
+ ->where([
+ [ 'order_id', '=', $order_info[ 'order_id' ] ],
+ [ 'delivery_type', '=', 'express' ],
+ [ 'sub_delivery_type', '=', 'express' ]
+ ])
+ ->count();
+
+ $key = $es_template_info[ 'company' ][ 'express_no_electronic_sheet' ] . '_' . $order_info[ 'order_no' ]
+ . '_' . $es_config[ 'kdniao_id' ] . '_' . $es_template_info[ 'print_style' ]
+ . '_' . $order_goods_delivery_count;
+
+ $cache = Cache::get($key);
+ if (!empty($cache)) {
+ return $cache;
+ }
+
+ $commodity = []; // 商品信息
+ $weight_total = 0; // 包裹总重量kg
+ $volume_total = 0; // 包裹总体积 m³
+ $remark = []; // 备注
+ foreach ($order_info[ 'order_goods' ] as $ck => $cv) {
+
+ $commodity[] = [
+ 'GoodsName' => str_replace($search, '', mb_substr($cv[ 'goods_name' ] . ' ' . $cv[ 'sku_name' ], 0, 50, 'UTF-8')),
+ 'GoodsQuantity' => $cv[ 'num' ]
+ ];
+// $remark[] = str_replace($search, '', mb_substr($cv[ 'goods_name' ] . ' ' . $cv[ 'sku_name' ], 0, 50, 'UTF-8'));
+ $goods_sku_info = $goods_sku_model->field('weight,volume')->where([ [ 'sku_id', '=', $cv[ 'sku_id' ] ] ])->findOrEmpty()->toArray();
+ if (!empty($goods_sku_info)) {
+ $weight_total += number_format($goods_sku_info[ 'weight' ], 3);
+ $volume_total += number_format($goods_sku_info[ 'volume' ], 3);
+ }
+ }
+
+ if (empty($commodity)) {
+ $result = [
+ 'success' => false,
+ 'result_code' => -1,
+ 'reason' => '该订单不支持打印电子面单',
+ 'order_no' => $order_info[ 'order_no' ]
+ ];
+ return $result;
+ }
+
+ $receiver_province_name = $sys_area_model->where([ [ 'id', '=', $order_info[ 'taker_province' ] ] ])->field('name')->findOrEmpty()->toArray()[ 'name' ] ?? '';
+ $receiver_city_name = $sys_area_model->where([ [ 'id', '=', $order_info[ 'taker_city' ] ] ])->field('name')->findOrEmpty()->toArray()[ 'name' ] ?? '';
+ $receiver_exp_area_name = $sys_area_model->where([ [ 'id', '=', $order_info[ 'taker_district' ] ] ])->field('name')->findOrEmpty()->toArray()[ 'name' ] ?? '';
+
+
+// $ShipperCode = $es_config['interface_type'] == 'kdbird' ? $es_template_info[ 'company' ][ 'express_no_electronic_sheet' ] : $es_template_info[ 'company' ][ 'kd100_express_no_electronic_sheet' ];
+ $api_data = [
+ 'cache_key' => $key,
+// 'ShipperCode' => $ShipperCode, // 快递公司编码
+// 'CustomerName' => $es_template_info[ 'customer_name' ], // 电子面单账号,申请:https://www.yuque.com/kdnjishuzhichi/rg4owd
+// 'CustomerPwd' => $es_template_info[ 'customer_pwd' ], // 电子面单密码,电子面单账号对照表:https://www.yuque.com/kdnjishuzhichi/dfcrg1/hrfw43
+// 'SendSite' => $es_template_info[ 'send_site' ],
+// 'SendStaff' => $es_template_info[ 'send_staff' ],
+// 'MonthCode' => $es_template_info[ 'month_code' ], // 月结账号
+ 'es_template_info'=>$es_template_info,
+ 'OrderCode' => $order_info[ 'order_no' ] . $order_goods_delivery_count, // 订单编号,多包裹防重复,要增加下标
+
+ 'PayType' => $es_template_info[ 'pay_type' ], // 运费支付方式(1:现付,2:到付,3:月结)
+ 'ExpType' => $es_template_info[ 'exp_type' ], // 快递业务类型,https://www.yuque.com/kdnjishuzhichi/dfcrg1/hgx758hom5p6wz0l
+
+ // 发件人信息
+ 'Sender' => [
+ 'Name' => $default_shop_address[ 'contact_name' ], // 发件人
+ 'Mobile' => $default_shop_address[ 'mobile' ], // 手机
+ 'ProvinceName' => $sender_province_name, // 发件省
+ 'CityName' => $sender_city_name, // 发件市
+ 'ExpAreaName' => $sender_exp_area_name, // 发件区
+ 'Address' => $default_shop_address[ 'address' ], // 发件人详细地址
+ 'PostCode' => '000000' // 发件地邮编邮政/EMS 必填可填000000
+ ],
+
+ // 收件人信息
+ 'Receiver' => [
+ 'Name' => $order_info[ 'taker_name' ], // 收件人
+ 'Mobile' => $order_info[ 'taker_mobile' ], // 电话
+ 'ProvinceName' => $receiver_province_name, // 收件省
+ 'CityName' => $receiver_city_name, // 收件市
+ 'ExpAreaName' => $receiver_exp_area_name, // 收件区
+ 'Address' => mb_substr($order_info[ 'taker_address' ], 0, 100, 'UTF-8'), // 收件人详细地址
+ 'PostCode' => '000000' // 收件地邮编邮政/EMS 必填可填000000
+ ],
+
+ 'Quantity' => count($order_info[ 'order_goods' ]) > 50 ? 50 : count($order_info[ 'order_goods' ]), // 包裹数 (至少填1,最多50)
+
+ // 商品信息
+ 'Commodity' => $commodity,
+ 'Weight' => $weight_total, // 包裹总重量kg,京东、快运类必填
+ 'Volume' => $volume_total, // 包裹总体积 m³,京东、快运类必填
+ 'Cost' => $order_info[ 'delivery_money' ], // 快递运费
+ 'Remark' => '', // '
' . mb_substr(implode('
', $remark), 0, 80, 'UTF-8'), // 备注
+
+ 'IsReturnPrintTemplate' => 1, // 是否返回电子面单模板:(不填默认为0)0:不需要,1:需要
+
+ 'TemplateSize' => $es_template_info[ 'print_style' ], // 模板规格,https://www.yuque.com/kdnjishuzhichi/dfcrg1/vpptucr1q5ahcxa7#iZvLV
+ 'IsNotice' => $es_template_info[ 'is_notice' ] // 是否通知快递员上门揽件跨越速运,京东快运必填
+ ];
+
+ $class = new ElectronicSheetSearchLoader();
+ $result = $class->electronicSheet($api_data);
+ $result[ 'order_no' ] = $order_info[ 'order_no' ]; // 记录打印的 订单号
+
+ return $result;
+ }
+
+}
diff --git a/niucloud/addon/shop/app/service/core/delivery/CoreExpressService.php b/niucloud/addon/shop/app/service/core/delivery/CoreExpressService.php
new file mode 100644
index 000000000..ee06e2ebc
--- /dev/null
+++ b/niucloud/addon/shop/app/service/core/delivery/CoreExpressService.php
@@ -0,0 +1,158 @@
+delivery['take_address'] ?? [];
+
+ if (empty($address)) {
+ $order->error[] = get_lang('NOT_SELECT_ADDRESS');
+ return;
+ }
+
+ $template_goods_data = [];
+ foreach ($order->goods_data as $k => &$v) {
+ $goods_type = $v['goods']['goods_type'];
+ if ($goods_type == GoodsDict::REAL) {
+ if (in_array(OrderDeliveryDict::EXPRESS, $v['goods']['delivery_type'])) {
+ if ($v['goods']['is_free_shipping'] == 0) {
+ if ($v['goods']['fee_type'] == 'template') {
+ $delivery_template_id = $v['goods']['delivery_template_id'];
+ $template_goods_data[$delivery_template_id][] = $v;
+ } else {
+ $v['delivery_money'] = $v['goods']['delivery_money'] * $v['num'];
+ }
+ $delivery_money += $v['delivery_money'] ?? 0;
+ }
+ } else {
+ $v['not_support_delivery'] = 1;
+ $order->error[] = get_lang('NOT_SUPPORT_DELIVERY_TYPE');
+ }
+ }
+ }
+
+ //运费模板运费计算
+ if (!empty($template_goods_data)) {
+ (new self())->feeCalculate($order, $template_goods_data, $delivery_money, $order->goods_data);
+ }
+
+ // 判断会员等级是否有包邮的权益
+ if (isset($order->buyer['member_level']['level_benefits']) && isset($order->buyer['member_level']['level_benefits']['shop_free_shipping'])) {
+ if ($order->buyer['member_level']['level_benefits']['shop_free_shipping']['is_use']) {
+ $order->basic['delivery_money'] = 0;
+ return;
+ }
+ }
+
+ $order->basic['delivery_money'] = $delivery_money;
+ }
+
+ /**
+ * 运费模板运费计算
+ * @param $order
+ * @param $template_goods_data
+ * @param $delivery_money
+ * @param $goods_data
+ * @return true|void
+ */
+ private function feeCalculate(&$order, $template_goods_data, &$delivery_money, &$goods_data) {
+ foreach ($template_goods_data as $delivery_template_id => $goods_list) {
+ $address = $order->delivery['take_address'] ?? [];
+
+ $field = 'snum,sprice,xnum,xprice,fee_type,fee_area_ids,no_delivery,no_delivery_area_ids,is_free_shipping,free_shipping_area_ids,free_shipping_price,free_shipping_num';
+ $template = (new ShippingTemplateItem())->where([['template_id', '=', $delivery_template_id], ['city_id', '=', $address['city_id']]])->field($field)->findOrEmpty()->toArray();
+ $nationwide = (new ShippingTemplateItem())->where([['template_id', '=', $delivery_template_id], ['city_id', '=', 0]])->field($field)->findOrEmpty()->toArray();
+ if (empty($template)) {
+ $template = $nationwide;
+ if (empty($nationwide)) {
+ $order->error[] = get_lang('SHOP_THE_AVAILABLE_SHIPPING_RATES_AREN_T_CONFIGURED');
+ return true;
+ }
+ } else {
+ if (empty($template['snum'])) $template['snum'] = $nationwide['snum'];
+ if (empty($template['sprice'])) $template['sprice'] = $nationwide['sprice'];
+ if (empty($template['xnum'])) $template['xnum'] = $nationwide['xnum'];
+ if (empty($template['xprice'])) $template['xprice'] = $nationwide['xprice'];
+ }
+
+ //按运费模板计算总量和总金额
+ $total = 0;
+ $total_goods_money = 0;
+ foreach ($goods_list as $goods) {
+ $this->totalCalculate($template, $goods, $total, $total_goods_money);
+ }
+
+ foreach ($goods_list as $goods) {
+ // 判断收货地址是否不配送
+ if ($template['no_delivery'] && !empty($template['no_delivery_area_ids'])) {
+ $goods_data[$goods['sku_id']]['not_support_delivery'] = 1;
+ $order->error[] = get_lang('NOT_SUPPORT_DELIVERY_ADDRESS');
+ return true;
+ }
+ // 判断收货地址是否包邮
+ if ($template['is_free_shipping'] && !empty($template['free_shipping_area_ids']) && ($total >= $template['free_shipping_num'] || $total_goods_money >= $template['free_shipping_price'])) {
+ $goods_data[$goods['sku_id']]['is_free_shipping'] = 1;
+ return true;
+ }
+ }
+ // 计算费用
+ $item_delivery_money = $template['sprice'];
+ if ($total > $template['snum']) {
+ $item_delivery_money += round(ceil(($total - $template['snum']) / $template['xnum']) * $template['xprice'], 2);
+ }
+ $delivery_money += $item_delivery_money;
+ }
+ }
+
+ /**
+ * 按运费模板计算总量和总金额
+ * @param $template
+ * @param $goods
+ * @param $total
+ * @param $total_goods_money
+ * @return void
+ */
+ private function totalCalculate($template, $goods, &$total, &$total_goods_money) {
+ $total_goods_money += $goods['goods_money'];
+ switch ($template['fee_type']) {
+ case ShippingTemplateDict::NUM:
+ $total += $goods['num'];
+ break;
+ case ShippingTemplateDict::VOLUME:
+ $total += $goods['volume'] * $goods['num'];
+ break;
+ case ShippingTemplateDict::WEIGHT:
+ $total += $goods['weight'] * $goods['num'];
+ break;
+ }
+ }
+
+}
diff --git a/niucloud/addon/shop/app/service/core/delivery/CoreLocalDeliveryService.php b/niucloud/addon/shop/app/service/core/delivery/CoreLocalDeliveryService.php
new file mode 100644
index 000000000..3a15066d8
--- /dev/null
+++ b/niucloud/addon/shop/app/service/core/delivery/CoreLocalDeliveryService.php
@@ -0,0 +1,197 @@
+core_config_service = new CoreConfigService();
+ }
+
+ /**
+ * 配置设置
+ * @param array $params
+ * @return array
+ */
+
+ public function setConfig( $data)
+ {
+ $this->core_config_service->setConfig( DeliveryLocalDict::SHOP_THIRD_PARTY_DELIVERY_CONFIG, $data);
+ return true;
+ }
+
+ public function getConfig()
+ {
+ $data = $this->core_config_service->getConfigValue( DeliveryLocalDict::SHOP_THIRD_PARTY_DELIVERY_CONFIG);
+ $config = DeliveryLocalDict::getType();
+ foreach ($config as $type => $item) {
+ if (!isset($data[$type])) {
+ $temp = [];
+ foreach ($item['column'] as $column) {
+ $temp[$column] = '';
+ }
+ $data[$type] = $temp;
+ }
+ }
+ return $data;
+ }
+
+ /**
+ * 配送费用计算
+ * @param $order
+ * @return void
+ */
+ public static function calculate(&$order)
+ {
+ $address = $order->delivery['take_address'] ?? [];
+
+ if (empty($address)) {
+ $order->error[] = get_lang('NOT_SELECT_ADDRESS');
+ return;
+ }
+
+ $goods_money = 0; // 商品价格
+ $goods_weight = 0; // 商品重量
+
+ foreach ($order->goods_data as $k => &$v) {
+ $goods_type = $v['goods']['goods_type'];
+ if ($goods_type == GoodsDict::REAL) {
+ if (in_array(OrderDeliveryDict::LOCAL_DELIVERY, $v['goods']['delivery_type'])) {
+ $goods_money += $v['goods_money'];
+ $goods_weight += $v['weight'] * $v['num'];
+ } else {
+ $v['not_support_delivery'] = 1;
+ $order->error[] = get_lang('NOT_SUPPORT_DELIVERY_TYPE');
+ }
+ }
+ }
+ (new self())->feeCalculate($order, $goods_money, $goods_weight);
+ }
+
+ /**
+ * 运费计算
+ * @param $order
+ * @param float $goods_money
+ * @param float $goods_weight
+ * @return void
+ */
+ public function feeCalculate(&$order, float $goods_money, float $goods_weight)
+ {
+ $address = $order->delivery['take_address'] ?? [];
+ $local = (new Local())->where([['local_id', '>', 0]])->field('fee_type,base_dist,base_price,grad_dist,grad_price,weight_start,weight_unit,weight_price,delivery_type,area,center')->findOrEmpty();
+ if ($local->isEmpty()) {
+ $order->error[] = get_lang('NOT_CONFIGURED_LOCAL_DELIVERY');
+ return;
+ }
+ if (empty($address['lat']) || empty($address['lng'])) {
+ $order->error[] = get_lang('NOT_SUPPORT_DELIVERY_ADDRESS');
+ return;
+ }
+ // 收货地址
+ $address_point = new Coordinate($address['lat'], $address['lng']);
+ // 取货地址
+ $local_address_point = new Coordinate($local['center']['lat'], $local['center']['lng']);
+ $local = $local->toArray();
+// $local['delivery_type'][0] = 'third'; //TODO调试使用 后续删除
+ // 判断所在区域
+ $located_in_area = null;
+ foreach ($local['area'] as $area) {
+ if ($area['area_type'] == 'radius') {
+ $center = new Coordinate($area['area_json']['center']['lat'], $area['area_json']['center']['lng']);
+ $distance = (new Vincenty())->getDistance($address_point, $center);
+ if ($distance <= $area['area_json']['radius']) {
+ $located_in_area = $area;
+ break;
+ }
+ } else {
+ $geofence = new Polygon();
+ $geofence->addPoints(array_map(function ($latlng) {
+ return new Coordinate($latlng['lat'], $latlng['lng']);
+ }, $area['area_json']['paths']));
+ if ($geofence->contains($address_point)) {
+ $located_in_area = $area;
+ break;
+ }
+ }
+ }
+ if (!$located_in_area) {
+ $order->error[] = get_lang('NOT_SUPPORT_DELIVERY_ADDRESS');
+ return;
+ }
+
+ if (bccomp($goods_money, $located_in_area['start_price'], 2) == -1) {
+ $order->error[] = '差' . $located_in_area['start_price'] - $goods_money . '元起送';
+ return;
+ }
+ if ($local['delivery_type'][0] == DeliveryLocalDict::DELIVERY_TYPE_THIRD) {
+ //TODO::计算三方配送费用
+ $config = $this->getConfig();
+ $third_type = $config['default'];
+ $loader = new ThirdDeliveryLoader($third_type, $config[$third_type]);
+ $res = $loader->calculate($order);
+ // 按配送区域收费
+ $order->basic['delivery_money'] = $res['delivery_price'];
+ $order->basic['delivery_third'] = [
+ 'name' => DeliveryLocalDict::getType($third_type)['name'],
+ 'type' => $third_type,
+ 'third_order_no' => $res['third_order_no'],
+ ];
+ } else {
+
+ if ($local['fee_type'] == 'distance') {
+ // 按距离收费
+ // 计算收货地址与取货地址的距离
+ $distance = round((new Vincenty())->getDistance($address_point, $local_address_point) / 1000, 2);
+ $order->basic['delivery_money'] = $local['base_price'];
+ if ($distance > $local['base_dist']) {
+ $order->basic['delivery_money'] += round(ceil(($distance - $local['base_dist']) / $local['grad_dist']) * $local['grad_price'], 2);
+ }
+ } else {
+ // 按配送区域收费
+ $order->basic['delivery_money'] = $located_in_area['delivery_price'];
+ }
+
+ // 计算续重费用
+ if ($goods_weight > 0 && $goods_weight > $local['weight_start'] && $local['weight_unit'] > 0 && $local['weight_price'] > 0) {
+ $order->basic['delivery_money'] += round(ceil(($goods_weight - $local['weight_start']) / $local['weight_unit']) * $local['weight_price'], 2);
+ }
+ }
+ }
+
+ public function thirdDeliveryCallback(array $data)
+ {
+ $config = $this->getConfig();
+ $loader = new ThirdDeliveryLoader($data['type'], $config[$data['type']]);
+ $loader->callback($data);
+ }
+}
diff --git a/niucloud/addon/shop/app/service/core/delivery/CoreStoreService.php b/niucloud/addon/shop/app/service/core/delivery/CoreStoreService.php
new file mode 100644
index 000000000..a1570cd89
--- /dev/null
+++ b/niucloud/addon/shop/app/service/core/delivery/CoreStoreService.php
@@ -0,0 +1,171 @@
+model = new Store();
+ }
+
+ /**
+ * 配送费用计算
+ * @param $order
+ * @return void
+ */
+ public static function calculate(&$order)
+ {
+ $store = $order->delivery[ 'take_store' ] ?? [];
+
+ if (empty($store)) {
+ $order->error[] = get_lang('NOT_SELECT_STORE');
+ return;
+ }
+
+ foreach ($order->goods_data as $k => &$v) {
+ $goods_type = $v[ 'goods' ][ 'goods_type' ];
+ if ($goods_type == GoodsDict::REAL) {
+ if (!in_array(OrderDeliveryDict::STORE, $v[ 'goods' ][ 'delivery_type' ])) {
+ $v[ 'not_support_delivery' ] = 1;
+ $order->error[] = get_lang('NOT_SUPPORT_DELIVERY_TYPE');
+ }
+ }
+ }
+ }
+
+ /**
+ * 查询自提点
+ * @param int $id
+ * @return array
+ */
+ public function getInfoById(int $store_id)
+ {
+ $condition = array(
+ [ 'store_id', '=', $store_id ]
+ );
+ return $this->model->where($condition)->findOrEmpty()->toArray();
+ }
+
+ /**
+ * 查询自提点
+ * @param $latlng
+ * @return array
+ * @throws \think\db\exception\DataNotFoundException
+ * @throws \think\db\exception\DbException
+ * @throws \think\db\exception\ModelNotFoundException
+ */
+ public function getStoreList($latlng = [])
+ {
+ $list = $this->model->where([ [ 'store_id', '>', 0 ] ])->field('store_id,time_week,time_interval,trade_time_json,store_name,store_logo,store_mobile,full_address,longitude,latitude,trade_time')->select()->toArray();
+ if (!empty($list) && !empty($latlng) && !empty($latlng[ 'lat' ]) && !empty($latlng[ 'lng' ])) {
+ $location = new Coordinate($latlng[ 'lat' ], $latlng[ 'lng' ]);
+ $list = array_map(function($item) use ($location) {
+ $item[ 'distance' ] = ( new Vincenty() )->getDistance($location, new Coordinate((float) $item[ 'latitude' ], (float) $item[ 'longitude' ]));
+ return $item;
+ }, $list);
+ array_multisort(array_column($list, 'distance'), SORT_ASC, $list);
+ }
+ $day_start_time = strtotime(date('Y-m-d'));
+ foreach ($list as &$item) {
+ $item[ 'store_time_list' ] = $this->formatTime($item[ 'time_week' ], $item[ 'trade_time_json' ], $day_start_time, $item[ 'time_interval' ]);
+ }
+ return $list;
+ }
+
+ /**
+ * @param $weekList
+ * @param $hour_arr
+ * @param $start_time
+ * @param $interval
+ * @return array
+ */
+ private function formatTime($weekList, $hour_arr, $start_time, $interval)
+ {
+ if (empty($weekList)) {
+ return [];
+ }
+ $array = [];
+ $day_week = (int) date('w', time());
+ foreach ($weekList as $week) {
+ $name = DeliveryDict::getWeekList($week)[ 'name' ];
+ if ($day_week == $week) {
+ $day_str = '今天';
+ $time = $start_time;
+ }
+ if ($day_week < $week) {
+ $day = $week - $day_week;
+ $time = strtotime("+{$day} day", $start_time);
+ if ($day_week + 1 == $week) {
+ $day_str = '明天';
+ } else {
+ $day_str = date("Y-m-d", $time);
+ }
+ }
+
+ if ($day_week > $week) {
+ $day = $day_week - $week;
+ $time = strtotime('+1 week', strtotime("-{$day} day", $start_time));
+ $day_str = date("Y-m-d", $time);
+ }
+ $array[ $time ] = [
+ 'name' => $day_str . "({$name})",
+ 'time_list' => $this->getTimeArr($hour_arr, $time, (int) $interval)
+ ];
+ }
+ ksort($array);
+ return array_values($array);
+ }
+
+ /**
+ * @param $hour_arr
+ * @param $start_time
+ * @param int $interval
+ * @return array
+ */
+ private function getTimeArr($hour_arr, $start_time, int $interval)
+ {
+ $array = [];
+ foreach ($hour_arr as $item) {
+ $start_second = (int) $item[ 'start_time' ];
+ $end_second = (int) $item[ 'end_time' ];
+ $num = ( $end_second - $start_second ) / 60 / $interval;
+ for ($i = 1; $i <= $num; $i++) {
+ $start_hour = $start_time + $start_second + ( $i - 1 ) * $interval * 60;
+ $end_hour = $start_time + $start_second + $i * $interval * 60;
+ if ($end_hour <= time()) {
+ continue;
+ }
+ $array[] = [
+// 'is_show'=>$end_hour>time() ?1:0,
+ 'show_hour' => date('H:i', $start_hour) . '-' . date('H:i', $end_hour),
+ 'time_str' => date('Y-m-d H:i', $start_hour) . '-' . date('H:i', $end_hour),
+ ];
+ }
+ }
+ return $array;
+ }
+}
diff --git a/niucloud/addon/shop/app/service/core/delivery/delivery_search/BaseDeliverySearch.php b/niucloud/addon/shop/app/service/core/delivery/delivery_search/BaseDeliverySearch.php
new file mode 100644
index 000000000..3a710f1be
--- /dev/null
+++ b/niucloud/addon/shop/app/service/core/delivery/delivery_search/BaseDeliverySearch.php
@@ -0,0 +1,38 @@
+ 'KdniaoDeliverySearch',
+ 2 => 'Kd100DeliverySearch',
+ ];
+
+ public function __construct()
+ {
+ $config = ( new CoreConfigService() )->getDeliverySearchConfig();
+ if(empty($config['interface_type']) || !isset($this->method[$config['interface_type']]) ){
+ throw new AdminException('NOT_CONFIGURED_DELIVERY_TYPE');
+ }
+ parent::__construct($this->method[$config['interface_type']], $config);
+ }
+ /**
+ * 空间名
+ * @var string
+ */
+ protected $namespace = '\\addon\\shop\\app\\service\\core\\delivery\\delivery_search\\';
+
+ protected $config_name = 'delivery_search';
+
+ /**
+ * 默认驱动
+ * @return mixed
+ */
+ protected function getDefault()
+ {
+ return 'kdbird';
+ }
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/app/service/core/delivery/delivery_search/Kd100DeliverySearch.php b/niucloud/addon/shop/app/service/core/delivery/delivery_search/Kd100DeliverySearch.php
new file mode 100644
index 000000000..f3e1f7488
--- /dev/null
+++ b/niucloud/addon/shop/app/service/core/delivery/delivery_search/Kd100DeliverySearch.php
@@ -0,0 +1,63 @@
+kd100_app_key = $config[ 'kd100_app_key' ] ?? '';
+ $this->kd100_customer = $config[ 'kd100_customer' ] ?? '';
+ if (empty($this->kd100_app_key) || empty($this->kd100_customer)){
+ throw new AdminException('NOT_CONFIGURED_DELIVERY_KD100');
+ }
+ $this->config = [
+ 'kd100_app_key' => $this->kd100_app_key,
+ 'kd100_customer' => $this->kd100_customer
+ ];
+ }
+
+
+ /**
+ * @param array $data
+ * @return mixed|void
+ */
+ public function search(array $data = [])
+ {
+ //查询数据
+ if(!empty($data['company_id'])){
+ $express_no = (new Company())->where('company_id',$data['company_id'])->value('kd100_express_no');
+ }else{
+ $express_no = $data['express_no'];
+ }
+ return (new Kd100($this->config))->orderTracesSubByJson(
+ $express_no,
+ $data[ 'logistic_no' ],
+ $data[ 'mobile' ]
+ );
+ }
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/app/service/core/delivery/delivery_search/KdniaoDeliverySearch.php b/niucloud/addon/shop/app/service/core/delivery/delivery_search/KdniaoDeliverySearch.php
new file mode 100644
index 000000000..3fc88fca0
--- /dev/null
+++ b/niucloud/addon/shop/app/service/core/delivery/delivery_search/KdniaoDeliverySearch.php
@@ -0,0 +1,43 @@
+logistic_config = $config;
+ }
+
+ /**
+ * 物流跟踪查询
+ * @param array $data
+ * @return array
+ */
+ public function search(array $data = [])
+ {
+ $kdniao_sdk = ( new Kdbird($this->logistic_config) );
+
+ $data = $kdniao_sdk->orderTracesSubByJson($data[ 'express_no' ], $data[ 'logistic_no' ], $data[ 'mobile' ]);
+ return $data;
+ }
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/app/service/core/delivery/delivery_search/sdk/Kd100.php b/niucloud/addon/shop/app/service/core/delivery/delivery_search/sdk/Kd100.php
new file mode 100644
index 000000000..f44bdf7a4
--- /dev/null
+++ b/niucloud/addon/shop/app/service/core/delivery/delivery_search/sdk/Kd100.php
@@ -0,0 +1,107 @@
+key = $config[ "kd100_app_key" ];
+ $this->customer = $config[ "kd100_customer" ];
+ $this->url = 'https://poll.kuaidi100.com/poll/query.do';
+ }
+
+ public function orderTracesSubByJson($shipper_code, $logistic_code, $mobile)
+ {
+ $param = [
+ 'com' => $shipper_code, // 快递公司编码
+ 'num' => $logistic_code, // 快递单号
+ ];
+ if(!empty($mobile)){
+ $param[ 'phone' ] = $mobile; // 手机号
+ }
+ $post_data = array();
+ $post_data[ 'customer' ] = $this->customer;
+ $post_data[ 'param' ] = json_encode($param, JSON_UNESCAPED_UNICODE);
+ $sign = md5($post_data[ 'param' ] . $this->key . $post_data[ 'customer' ]);
+ $post_data[ 'sign' ] = strtoupper($sign);
+ $result = $this->sendPost($this->url, $post_data);
+ $res = [];
+
+ if (!empty($result[ 'result' ]) && $result[ 'result' ] == false) {
+ $res[ "success" ] = false;
+ $res[ "reason" ] = $result[ "message" ];
+ }
+ if (!empty($result[ 'status' ]) && $result[ "status" ] != 200) {
+ $res[ "success" ] = false;
+ $res[ "reason" ] = $result[ "message" ];
+ } else if (!empty($result[ 'status' ]) && $result[ "status" ] == 200) {
+ $list = [];
+ if (!empty($result[ 'data' ])) {
+ foreach ($result[ 'data' ] as $trace) {
+ $list[] = [
+ 'datetime' => $trace[ 'time' ],
+ 'remark' => $trace[ 'context' ]
+ ];
+ }
+ }
+ $res = [
+ 'success' => $result[ 'message' ],
+ 'status' => !empty($result[ 'status' ]) ? $result[ 'status' ] : '',
+ 'list' => array_reverse($list)
+ ];
+ }else{
+ $res = [
+ 'success' => false,
+ 'reason' => '暂无物流信息'
+ ];
+ }
+ return $res;
+ }
+
+ /**
+ * post提交数据
+ * @param string $url 请求Url
+ * @param array $datas 提交的数据
+ * @return url响应返回的html
+ */
+ public function sendPost($url, $datas)
+ {
+ $ch = curl_init();
+ curl_setopt($ch, CURLOPT_URL, $url);
+ curl_setopt($ch, CURLOPT_POST, 1);
+ curl_setopt($ch, CURLOPT_HEADER, 0);
+ curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($datas));
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
+ curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
+ $result = curl_exec($ch);
+ // 第二个参数为true,表示格式化输出json
+ $data = json_decode($result, true);
+ return $data;
+ }
+
+ /**
+ * 物流跟踪状态
+ * @param $state
+ */
+ public function getStatusName($status)
+ {
+ $data = [
+ 0 => "暂无轨迹信息",
+ 1 => "已揽收",
+ 2 => "在途中",
+ 3 => "已签收",
+ 4 => "问题件",
+ 5 => "转寄",
+ 6 => "清关"
+ ];
+ $status_name = isset($data[ $status ]) ? $data[ $status ] : '';
+ return $status_name;
+ }
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/app/service/core/delivery/delivery_search/sdk/Kdbird.php b/niucloud/addon/shop/app/service/core/delivery/delivery_search/sdk/Kdbird.php
new file mode 100644
index 000000000..41398d910
--- /dev/null
+++ b/niucloud/addon/shop/app/service/core/delivery/delivery_search/sdk/Kdbird.php
@@ -0,0 +1,130 @@
+EBusinessID = $config[ "kdniao_id" ];
+ $this->AppKey = $config[ "kdniao_app_key" ];
+ $this->is_pay = $config[ "kdniao_is_pay" ];
+ }
+
+ /**
+ * 物流跟踪
+ * @param $shipper_code
+ * @param $logistic_code
+ * @param $mobile
+ * @return array
+ */
+ public function orderTracesSubByJson($shipper_code, $logistic_code, $mobile)
+ {
+ $request_array = array(
+ 'ShipperCode' => $shipper_code,
+ 'LogisticCode' => $logistic_code,
+ 'CustomerName' => substr($mobile, 7, 10)
+ );
+
+ $requestData = json_encode($request_array);
+
+ $data = array(
+ 'EBusinessID' => $this->EBusinessID,
+ 'RequestType' => '8001',
+ 'RequestData' => urlencode($requestData),
+ 'DataType' => '2',
+ );
+
+ if ($this->is_pay == 2) $data[ 'RequestType' ] = 8002;
+
+ $data[ 'DataSign' ] = $this->encrypt($requestData, $this->AppKey);
+ $result = $this->sendPost($this->traces_url, $data);
+ //根据公司业务处理返回的信息......
+ $result = json_decode($result, true);
+ $res = [];
+ if ($result[ "Success" ] == false) {
+ $res[ "success" ] = false;
+ $res[ "reason" ] = $result[ "Reason" ];
+ } else {
+ $list = [];
+ if (!empty($result[ 'Traces' ])) {
+ foreach ($result[ 'Traces' ] as $trace) {
+ $list[] = [
+ 'datetime' => $trace[ 'AcceptTime' ],
+ 'remark' => $trace[ 'AcceptStation' ]
+ ];
+ }
+ }
+ $res = [
+ 'success' => $result[ 'Success' ],
+ 'reason' => !empty($result[ 'Reason' ]) ? $result[ 'Reason' ] : '',
+ 'status' => !empty($result[ 'State' ]) ? $result[ 'State' ] : '',
+ 'status_name' => !empty($result[ 'State' ]) ? $this->getStatusName($result[ 'State' ]) : '',
+ 'shipper_code' => !empty($result[ 'ShipperCode' ]) ? $result[ 'ShipperCode' ] : '',
+ 'logistic_code' => !empty($result[ 'LogisticCode' ]) ? $result[ 'LogisticCode' ] : '',
+ 'list' => $list
+ ];
+ }
+ return $res;
+ }
+
+ /**
+ * 电商Sign签名生成
+ * @param string $data 内容
+ * @param $appkey
+ * @return string DataSign签名
+ */
+ public function encrypt($data, $appkey)
+ {
+ return urlencode(base64_encode(md5($data . $appkey)));
+ }
+
+ /**
+ * post提交数据
+ * @param string $url 请求Url
+ * @param array $data 提交的数据
+ * @return false|string
+ */
+ public function sendPost($url, $data)
+ {
+ $postdata = http_build_query($data);
+ $options = array(
+ 'http' => array(
+ 'method' => 'POST',
+ 'header' => 'Content-type:application/x-www-form-urlencoded',
+ 'content' => $postdata,
+ 'timeout' => 15 * 60 // 超时时间(单位:s)
+ )
+ );
+ $context = stream_context_create($options);
+ $result = file_get_contents($url, false, $context);
+ return $result;
+ }
+
+ /**
+ * 物流跟踪状态
+ * @param $status
+ * @return mixed|string
+ */
+ public function getStatusName($status)
+ {
+ $data = [
+ 0 => "暂无轨迹信息",
+ 1 => "已揽收",
+ 2 => "在途中",
+ 3 => "已签收",
+ 4 => "问题件",
+ 5 => "转寄",
+ 6 => "清关"
+ ];
+ $status_name = isset($data[ $status ]) ? $data[ $status ] : '';
+ return $status_name;
+ }
+}
diff --git a/niucloud/addon/shop/app/service/core/delivery/electronic_sheet/BaseElectronicSheetSearch.php b/niucloud/addon/shop/app/service/core/delivery/electronic_sheet/BaseElectronicSheetSearch.php
new file mode 100644
index 000000000..4ca7ba5bf
--- /dev/null
+++ b/niucloud/addon/shop/app/service/core/delivery/electronic_sheet/BaseElectronicSheetSearch.php
@@ -0,0 +1,38 @@
+ 'KdniaoSearch',
+ //需线上测试,先隐藏 'kd100' => 'Kd100Search',
+ ];
+
+ public function __construct()
+ {
+ $config = ( new CoreConfigService() )->getDeliveryElectronSheeticConfig();
+ if(empty($config['interface_type']) || !isset($this->method[$config['interface_type']]) ){
+ throw new AdminException('NOT_CONFIGURED_DELIVERY_TYPE');
+ }
+ parent::__construct($this->method[$config['interface_type']], $config);
+ }
+
+ /**
+ * 空间名
+ * @var string
+ */
+ protected $namespace = '\\addon\\shop\\app\\service\\core\\delivery\\electronic_sheet\\';
+
+ protected $config_name = 'electronic_sheet';
+
+ /**
+ * 默认驱动
+ * @return mixed
+ */
+ protected function getDefault()
+ {
+ return 'kdbird';
+ }
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/app/service/core/delivery/electronic_sheet/Kd100Search.php b/niucloud/addon/shop/app/service/core/delivery/electronic_sheet/Kd100Search.php
new file mode 100644
index 000000000..25c57b769
--- /dev/null
+++ b/niucloud/addon/shop/app/service/core/delivery/electronic_sheet/Kd100Search.php
@@ -0,0 +1,132 @@
+key = $config[ 'kd100_key' ] ?? '';
+ $this->secret = $config[ 'kd100_secret' ] ?? '';
+ if (empty($this->key) || empty($this->secret)){
+ throw new AdminException('NOT_CONFIGURED_DELIVERY_KD100');
+ }
+ }
+
+ /**
+ * 电子面单
+ * @param array $data
+ * @return array
+ */
+ public function electronicSheet(array $data = [])
+ {
+ $kd100_config = $data['es_template_info']['kd100_config'];
+ $template_info = [
+ 'printType'=>'HTML',//打印类型,NON:只下单不打印(默认); IMAGE:生成图片短链;HTML:生成html短链
+ 'partnerId'=>$kd100_config['month_code'],//单客户账户或月结账号
+ 'partnerKey'=>$kd100_config['customer_pwd'],//电子面单密码
+ 'partnerSecret'=>$kd100_config['month_code'],//电子面单密钥
+ 'partnerName'=>$kd100_config['customer_name'],//电子面单客户账户名称
+ 'code'=>$kd100_config['send_site'],//电子面单承载编号
+ 'checkMan'=>$kd100_config['send_staff'],//电子面单承载快递员名
+ 'payType'=>$kd100_config['pay_type'],//支付方式: SHIPPER:寄方付(默认) CONSIGNEE:到付 MONTHLY:月结 THIRDPARTY
+ 'expType'=>$data['es_template_info']['exp_type'],//产品类型
+ ];
+ $param_data =[
+ 'kuaidicom'=>$data['es_template_info']['company']['kd100_express_no_electronic_sheet'],//快递公司编码
+ 'recMan'=>[
+ 'name'=>$data['Receiver']['Name'],//收件人姓名
+ 'mobile'=>$data['Receiver']['Mobile'],//收件人手机
+ 'printAddr'=>$data['Receiver']['ProvinceName'].$data['Receiver']['CityName'].$data['Receiver']['ExpAreaName'].$data['Receiver']['Address'],//完整地址地址
+ ],
+ 'sendMan'=>[
+ 'name'=>$data['Sender']['Name'],//寄件人姓名
+ 'mobile'=>$data['Sender']['Mobile'],//寄件人手机
+ 'printAddr'=>$data['Sender']['ProvinceName'].$data['Sender']['CityName'].$data['Sender']['ExpAreaName'].$data['Sender']['Address'],//完整地址地址
+ ],
+ 'cargo'=>'商品',//物品名称,例:文件
+ 'count'=>$data['Quantity'],//包裹总数量
+ 'weight'=>$data['Weight'],//包裹总重量,极兔速递必填
+ 'remark'=>'',//备注
+ 'tempId'=>$data['es_template_info']['temp_id'],//主单模板,
+ 'childTempId'=>$data['es_template_info']['child_temp_id'],//子单模板
+ 'backTempId'=>$data['es_template_info']['back_temp_id'],//回单模板
+ ];
+
+ $param = array_merge($template_info,$param_data);
+ $post_data['method'] = 'order';
+ $post_data['param'] = json_encode($param, JSON_UNESCAPED_UNICODE);
+ $post_data['key'] = $this->key;
+ $post_data['t'] = time();
+ $sign = md5($post_data['param'] . $post_data['t']. $this->key . $this->secret);
+ $post_data[ 'sign' ] = strtoupper($sign);
+ $result = $this->sendPost($this->url, $post_data);
+ Log::write('快递100电子面单返回数据');
+ Log::write($result);
+
+ $res = [
+ 'success' => false,
+ 'reason' => '',
+ 'result_code' => 105,
+ ];
+ if (!empty($result[ 'code' ]) && $result[ 'code' ] == 200) {
+ $res[ 'success' ] = $result[ 'success' ];
+ $res[ 'result_code' ] = $result[ 'code' ];
+ $data = $result[ 'data' ];
+ $res[ 'print_template' ] = $data[ 'label' ];
+ $res['order_info'] = [
+ 'LogisticCode'=>$data[ 'kuaidinum' ]
+ ];
+ }else{
+ $res[ 'reason' ] = $result[ 'message' ];
+ }
+ return $res;
+ }
+
+
+ /**
+ * post提交数据
+ * @param string $url 请求Url
+ * @param array $datas 提交的数据
+ * @return url响应返回的html
+ */
+ public function sendPost($url, $datas)
+ {
+ $ch = curl_init();
+ curl_setopt($ch, CURLOPT_URL, $url);
+ curl_setopt($ch, CURLOPT_POST, 1);
+ curl_setopt($ch, CURLOPT_HEADER, 0);
+ curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($datas));
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
+ curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
+ $result = curl_exec($ch);
+ // 第二个参数为true,表示格式化输出json
+ $result = json_decode($result, true);
+ return $result;
+ }
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/app/service/core/delivery/electronic_sheet/KdniaoSearch.php b/niucloud/addon/shop/app/service/core/delivery/electronic_sheet/KdniaoSearch.php
new file mode 100644
index 000000000..cc12efd91
--- /dev/null
+++ b/niucloud/addon/shop/app/service/core/delivery/electronic_sheet/KdniaoSearch.php
@@ -0,0 +1,68 @@
+logistic_config = $config;
+ }
+
+ /**
+ * 电子面单
+ * @param array $data
+ * @return array
+ */
+ public function electronicSheet(array $data = [])
+ {
+ //后端暂不支持单独配置,先注释
+// $kdbird_config = $data['es_template_info']['kdbird_config'];
+// $template_info = [
+// 'ShipperCode' => $data['es_template_info']['company'][ 'express_no_electronic_sheet' ], // 快递公司编码
+// 'CustomerName' => $kdbird_config[ 'customer_name' ], // 电子面单账号,申请:https://www.yuque.com/kdnjishuzhichi/rg4owd
+// 'CustomerPwd' => $kdbird_config[ 'customer_pwd' ], // 电子面单密码,电子面单账号对照表:https://www.yuque.com/kdnjishuzhichi/dfcrg1/hrfw43
+// 'SendSite' => $kdbird_config[ 'send_site' ],
+// 'SendStaff' => $kdbird_config[ 'send_staff' ],
+// 'MonthCode' => $kdbird_config[ 'month_code' ], // 月结账号
+// 'PayType' => $kdbird_config[ 'pay_type' ], // 运费支付方式(1:现付,2:到付,3:月结)
+// 'ExpType' => $data['es_template_info'][ 'exp_type' ], // 快递业务类型,https://www.yuque.com/kdnjishuzhichi/dfcrg1/hgx758hom5p6wz0l
+// 'TemplateSize' => $kdbird_config[ 'print_style' ], // 模板规格,https://www.yuque.com/kdnjishuzhichi/dfcrg1/vpptucr1q5ahcxa7#iZvLV
+// 'IsNotice' => $kdbird_config[ 'is_notice' ], // 是否通知快递员上门揽件跨越速运,京东快运必填
+// ];
+ $template_info = [
+ 'ShipperCode' => $data['es_template_info'][ 'company' ][ 'express_no_electronic_sheet' ], // 快递公司编码
+ 'CustomerName' => $data['es_template_info'][ 'customer_name' ], // 电子面单账号,申请:https://www.yuque.com/kdnjishuzhichi/rg4owd
+ 'CustomerPwd' => $data['es_template_info'][ 'customer_pwd' ], // 电子面单密码,电子面单账号对照表:https://www.yuque.com/kdnjishuzhichi/dfcrg1/hrfw43
+ 'SendSite' => $data['es_template_info'][ 'send_site' ],
+ 'SendStaff' => $data['es_template_info'][ 'send_staff' ],
+ 'MonthCode' => $data['es_template_info'][ 'month_code' ], // 月结账号
+ 'PayType' => $data['es_template_info'][ 'pay_type' ], // 运费支付方式(1:现付,2:到付,3:月结)
+ 'ExpType' => $data['es_template_info'][ 'exp_type' ], // 快递业务类型,https://www.yuque.com/kdnjishuzhichi/dfcrg1/hgx758hom5p6wz0l
+ 'TemplateSize' => $data['es_template_info'][ 'print_style' ], // 模板规格,https://www.yuque.com/kdnjishuzhichi/dfcrg1/vpptucr1q5ahcxa7#iZvLV
+ 'IsNotice' => $data['es_template_info'][ 'is_notice' ], // 是否通知快递员上门揽件跨越速运,京东快运必填
+ ];
+ $data = array_merge($data, $template_info);
+ unset($data[ 'es_template_info' ]);
+ return ( new Kdbird($this->logistic_config) )->electronicSheetByJson($data);
+ }
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/app/service/core/delivery/electronic_sheet/sdk/Kdbird.php b/niucloud/addon/shop/app/service/core/delivery/electronic_sheet/sdk/Kdbird.php
new file mode 100644
index 000000000..1caa5293a
--- /dev/null
+++ b/niucloud/addon/shop/app/service/core/delivery/electronic_sheet/sdk/Kdbird.php
@@ -0,0 +1,108 @@
+EBusinessID = $config[ "kdniao_id" ];
+ $this->ApiKey = $config[ "kdniao_api_key" ];
+ }
+
+ /**
+ * 电子面单
+ * 文档:https://www.yuque.com/kdnjishuzhichi/dfcrg1/xxvu6s
+ * @param $requestData
+ * @return array
+ */
+ public function electronicSheetByJson($requestData)
+ {
+ $jsonParam = json_encode($requestData, JSON_UNESCAPED_UNICODE);
+
+ $data = array(
+ 'EBusinessID' => $this->EBusinessID,
+ 'RequestType' => '1007',
+ 'RequestData' => urlencode($jsonParam),
+ 'DataType' => '2',
+ );
+
+ $data[ 'DataSign' ] = $this->encrypt($jsonParam, $this->ApiKey);
+
+ $key = $requestData[ 'cache_key' ];
+ $cache = Cache::get($key);
+ if (!empty($cache)) {
+ return $cache;
+ }
+
+ $result = $this->sendPost($this->electronic_sheet_url, $data);
+ //根据公司业务处理返回的信息......
+ Log::write('电子面单返回数据 electronicSheetByJson:', $result);
+ $result = json_decode($result, true);
+
+ $res = [
+ 'success' => false,
+ 'reason' => '接口返回为空,请稍后再试',
+ 'result_code' => 105,
+ ];
+
+ if (!empty($result)) {
+
+ $res[ 'success' ] = $result[ 'Success' ];
+ $res[ 'result_code' ] = $result[ 'ResultCode' ] ?? -1;
+ $res[ 'reason' ] = $result[ 'Reason' ];
+ if ($res[ 'success' ]) {
+ $res[ 'print_template' ] = $result[ 'PrintTemplate' ];
+ $res[ 'order_info' ] = $result[ 'Order' ];
+ $res[ 'order_no' ] = $requestData[ 'OrderCode' ]; // 记录打印的 订单号
+
+ // 请求成功,存缓存,防止浪费请求资源
+ Cache::tag('electronic_sheet_cache_kdbird')->set($key, $res);
+ }
+ }
+
+ return $res;
+ }
+
+ /**
+ * 电商Sign签名生成
+ * @param string $data 内容
+ * @param $ApiKey
+ * @return string DataSign签名
+ */
+ public function encrypt($data, $ApiKey)
+ {
+ return urlencode(base64_encode(md5($data . $ApiKey)));
+ }
+
+ /**
+ * post提交数据
+ * @param string $url 请求Url
+ * @param array $data 提交的数据
+ * @return false|string
+ */
+ public function sendPost($url, $data)
+ {
+ $postdata = http_build_query($data);
+ $options = array(
+ 'http' => array(
+ 'method' => 'POST',
+ 'header' => 'Content-type:application/x-www-form-urlencoded',
+ 'content' => $postdata,
+ 'timeout' => 15 * 60 // 超时时间(单位:s)
+ )
+ );
+ $context = stream_context_create($options);
+ $result = file_get_contents($url, false, $context);
+ return $result;
+ }
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/app/service/core/delivery/third_delivery/BaseThirdDelivery.php b/niucloud/addon/shop/app/service/core/delivery/third_delivery/BaseThirdDelivery.php
new file mode 100644
index 000000000..504cabb6b
--- /dev/null
+++ b/niucloud/addon/shop/app/service/core/delivery/third_delivery/BaseThirdDelivery.php
@@ -0,0 +1,36 @@
+Niucloud Team
+// +----------------------------------------------------------------------
+namespace addon\shop\app\service\core\delivery\third_delivery;
+
+
+use addon\shop\app\service\core\delivery\third_delivery\sdk\Dada\OrderCancelRequest;
+use addon\shop\app\service\core\delivery\third_delivery\sdk\Dada\OrderCreateByFeeOrderNoRequest;
+use addon\shop\app\service\core\delivery\third_delivery\sdk\Dada\OrderCreateRequest;
+use addon\shop\app\service\core\delivery\third_delivery\sdk\Dada\OrderFeeRequest;
+use addon\shop\app\service\core\delivery\third_delivery\sdk\Dada\OrderInfoRequest;
+use addon\shop\app\service\core\delivery\third_delivery\sdk\Dada\OrderTransporterPositionH5Request;
+use addon\shop\app\service\core\delivery\third_delivery\sdk\Dada\OrderTransporterPositionRequest;
+use think\facade\Log;
+
+class Dada extends BaseThirdDelivery
+{
+ public $app_secret;//App_secret
+ public $app_key;//App_key
+ public $shop_id;//商户ID
+ public $shop_store_no;//门店编号
+ public $config;
+
+ public function initialize(array $config = [])
+ {
+ $this->app_secret = $config['app_secret'];
+ $this->app_key = $config['app_key'];
+ $this->shop_id = $config['shop_id'];
+ $this->shop_store_no = $config['shop_store_no'];
+ $this->config = $config;
+ }
+
+ /**
+ * ADMINAPI 发货使用
+ * @param $data
+ * @return array
+ */
+ public function createOrder($data)
+ {
+ $order_data = $data['order_data'];
+ $order_goods_data = $data['order_goods_data'];
+ $order_no = $order_data->order_no;
+// return [//调试数据
+// 'delivery_price' => 100,//$res['fee'],
+// 'third_order_no' => $order_no,//$res['fee'],
+// ];
+ $request = new OrderCreateRequest();
+ $product_list = [];
+ $weight = $num = 0;
+ foreach ($order_goods_data as $sku_info) {
+ $product_list[] = [
+ 'count' => $sku_info['num'],
+ 'sku_name' => $sku_info['goods_name'] . $sku_info['sku_name'],
+ 'src_product_no' => $sku_info['sku_id'],
+ 'unit' => $sku_info['goods']['unit'],
+ ];
+ $weight += $sku_info['sku']['weight'] * $sku_info['num'];
+ $num += $sku_info['num'];
+ }
+ // 创建请求对象并链式设置参数
+ $request = $request->setBaseParams($this->config)
+ ->setCallback($order_no)
+ ->setShopNo($this->shop_store_no)
+ ->setOriginId($order_no)
+ ->setReceiverName($order_data->taker_name)
+ ->setReceiverPhone($order_data->taker_phone)
+ ->setReceiverAddress($order_data->taker_address)
+ ->setReceiverLat($order_data->taker_latitude)
+ ->setReceiverLng($order_data->taker_longitude)
+ ->setCargoNum($num)
+ ->setCargoWeight(max($weight, 1))
+ ->setCargoPrice($order_data->order_money)
+ ->setProductList($product_list);
+ try {
+ $res = $request->sendRequest();
+ return [
+ 'delivery_price' => $res['fee'],
+ 'third_order_no' => $order_no,
+ ];
+
+ } catch (\Exception $e) {
+ Log::write('DADA' . $e->getMessage());
+ return [
+ 'delivery_price' => 0,
+ 'third_order_no' => $order_no,
+ ];
+
+ }
+
+ }
+
+ /**
+ * API使用
+ * @param $order_data
+ * @return array
+ */
+ public function calculate($order_data)
+ {
+ $order_no = $order_data->order_key;
+ $goods_data = $order_data->goods_data;
+ $member_address = $order_data->delivery['take_address'];
+ $request = new OrderFeeRequest();
+ $product_list = [];
+ $weight = 0;
+ foreach ($goods_data as $sku_id => $sku_info) {
+ $product_list[] = [
+ 'count' => $sku_info['num'],
+ 'sku_name' => $sku_info['goods']['goods_name'] . $sku_info['sku_name'],
+ 'src_product_no' => $sku_id,
+ 'unit' => $sku_info['goods']['unit'],
+ ];
+ $weight += $sku_info['weight'] * $sku_info['num'];
+ }
+ // 创建请求对象并链式设置参数
+ $request = $request->setBaseParams($this->config)
+ ->setShopNo($this->shop_store_no)
+ ->setOriginId($order_no)
+ ->setCargoPrice($order_data->basic['goods_money'])
+ ->setReceiverName($member_address['name'])
+ ->setReceiverPhone($member_address['mobile'])
+ ->setReceiverAddress($member_address['full_address'])
+ ->setReceiverLat($member_address['lat'])
+ ->setReceiverLng($member_address['lng'])
+ ->setCargoNum(count($goods_data))
+ ->setCargoWeight(max($weight, 1))
+ ->setCallback($order_no)
+ ->setProductList($product_list);
+ try {
+ $res = $request->sendRequest();
+ return [
+ 'delivery_price' => $res['fee'],
+ 'third_order_no' => $order_no,
+ ];
+ } catch (\Exception $exception) {
+ Log::write('DADA' . $exception->getMessage());
+ return [
+ 'delivery_price' => 0,
+ 'third_order_no' => $order_no,
+ ];
+ }
+ }
+
+ /**
+ *
+ * @param $delivery_third_order_no `计算运费接口返回的 配送方单号 queryFeeMoney.response.delivery_third_order_no`
+ * @return string[]
+ */
+ public function createOrderAfterCalculate($delivery_third_order_no)
+ {
+ return (new OrderCreateByFeeOrderNoRequest())->setDeliveryNo($delivery_third_order_no)->sendRequest();
+ }
+
+ /**
+ * @param $order_no `订单号`
+ * @return string[]
+ */
+ public function queryOrderInfo($data)
+ {
+// return [//模拟返回的数据
+// 'order_no' => $data,
+// 'status' => 1,
+// 'status_name' => '待接单',
+// 'transporter_name' => '配送员1',
+// 'transporter_phone' => '15235353636',
+// 'transporter_lng' => '121.531522',
+// 'transporter_lat' => '31.252839',
+// 'accept_time' => '2025-06-22 12:00:00',
+// 'finish_time' => '2025-06-22 12:00:00',
+// 'order_finish_code' => '9527',
+// ];
+ $order_no = $data['order_no'];
+ try {
+ $res = (new OrderInfoRequest())->setOrderId($order_no)->sendRequest();
+ return [
+ 'order_no' => $res['orderId'],
+ 'status' => $res['statusCode'],
+ 'status_name' => $res['statusMsg'],
+ 'transporter_name' => $res['transporterName'],
+ 'transporter_phone' => $res['transporterPhone'],
+ 'transporter_lng' => $res['transporterLng'],
+ 'transporter_lat' => $res['transporterLat'],
+ 'accept_time' => $res['acceptTime'],
+ 'finish_time' => $res['finishTime'],
+ 'order_finish_code' => $res['orderFinishCode'],
+ ];
+ } catch (\Exception $exception) {
+ Log::write('DADA' . $exception->getMessage());
+ return [//模拟返回的数据
+ 'order_no' => $order_no,
+ 'status' => 1,
+ 'status_name' => '待接单',
+ 'transporter_name' => '未知',
+ 'transporter_phone' => '未知',
+ 'transporter_lng' => '',
+ 'transporter_lat' => '',
+ 'accept_time' => '',
+ 'finish_time' => '',
+ 'order_finish_code' => '',
+ ];
+ }
+
+ }
+
+ /**
+ * @param $order_no `订单号`
+ * @param $cancel_reason_id `取消原因类型ID`
+ * @param $cancel_reason `取消原因`
+ * @return false|string[]
+ */
+ public function closeOrder($data)
+ {
+ try {
+ return (new OrderCancelRequest())
+ ->setOrderId($data['order_no'])
+ ->setCancelReasonId($data['cancel_reason_id'])
+ ->setCancelReason($data['cancel_reason'])
+ ->sendRequest();
+ } catch (\Exception $exception) {
+ Log::write('DADA' . $exception->getMessage());
+ return false;
+ }
+
+ }
+
+ public function GetTransporterPosition($data)
+ {
+ //调试数据
+// return [
+// 'transporter_name' => '配送员1',
+// 'transporter_phone' => '15235353636',
+// 'transporter_lng' => '121.531522',
+// 'transporter_lat' => '31.252839',
+// ];
+ try {
+ if ($data['is_h5']) {
+ $res = (new OrderTransporterPositionH5Request())
+ ->setOrderId($data['order_no'])
+ ->sendRequest();
+ $h5_url = $res['trackUrl'];
+ }
+ $res = (new OrderTransporterPositionRequest())
+ ->setOrderIds([$data['order_no']])
+ ->sendRequest();
+ return [
+ 'transporter_name' => $res['transporterName'],
+ 'transporter_phone' => $res['transporterPhone'],
+ 'transporter_lng' => $res['transporterLng'],
+ 'transporter_lat' => $res['transporterLat'],
+ 'h5_url' => $h5_url ?? "",
+ ];
+ } catch (\Exception $exception) {
+ Log::write('DADA' . $exception->getMessage());
+ return [
+ 'transporter_name' => '',
+ 'transporter_phone' => '',
+ 'transporter_lng' => '',
+ 'transporter_lat' => '',
+ ];
+ }
+
+ }
+
+ public function callback($data)
+ {
+ $callback = [
+ 'order_no' => '112233',//自主追加
+ "signature" => "2b3aa825562bcea9471fe860b3f8a8fa",
+ "client_id" => "1357061741749469184",
+ "order_id" => "Cu16538768403935339353",//订单号
+ "order_status" => 100,//订单状态(待接单=1,待取货=2,骑士到店=100,配送中=3,已完成=4,已取消=5, 已追加待接单=8,妥投异常之物品返回中=9, 妥投异常之物品返回完成=10, 售后取件单送达门店=6, 创建达达运单失败=1000)
+ "cancel_reason" => "",
+ "cancel_from" => 0,
+ "dm_id" => 170900,
+ "dm_name" => "张三",
+ "dm_mobile" => "18500000000",
+ "update_time" => 1653876860,
+ "finish_code" => "1234"
+ ];
+ $status = $data['order_status'];//订单配送状态
+ }
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/app/service/core/delivery/third_delivery/ThirdDeliveryLoader.php b/niucloud/addon/shop/app/service/core/delivery/third_delivery/ThirdDeliveryLoader.php
new file mode 100644
index 000000000..bcf6ad0e9
--- /dev/null
+++ b/niucloud/addon/shop/app/service/core/delivery/third_delivery/ThirdDeliveryLoader.php
@@ -0,0 +1,42 @@
+app_secret = $app_secret;
+ return $this;
+ }
+
+ public function getAppSecret(): string
+ {
+ return $this->app_secret;
+ }
+
+ // 设置App Key
+ public function setAppKey(string $app_key): self
+ {
+ $this->app_key = $app_key;
+ return $this;
+ }
+
+ public function getAppKey(): string
+ {
+ return $this->app_key;
+ }
+
+ // 设置商户ID
+ public function setShopId(string $shop_id): self
+ {
+ $this->shop_id = $shop_id;
+ return $this;
+ }
+
+ public function getShopId(): string
+ {
+ return $this->shop_id;
+ }
+
+ // 设置门店编号
+ public function setShopStoreNo(string $shop_store_no): self
+ {
+ $this->shop_store_no = $shop_store_no;
+ return $this;
+ }
+
+ public function getShopStoreNo(): string
+ {
+ return $this->shop_store_no;
+ }
+
+ // 回调地址
+ public function setCallback($order_no)
+ {
+ $this->callback = sprintf($this->callback,DeliveryLocalDict::DADA,$order_no);
+ return $this;
+ }
+
+ public function getCallback()
+ {
+ return $this->callback;
+ }
+
+ // 获取基础参数
+ public function getBaseParams(): array
+ {
+ return [
+ 'app_key' => $this->app_key,
+ 'shop_id' => $this->shop_id,
+ 'shop_store_no' => $this->shop_store_no,
+ 'app_secret' => $this->app_secret,
+ ];
+ }
+
+ // 获取基础参数
+ public function setBaseParams($config)
+ {
+ $this->app_key = $config['app_key'];
+ $this->shop_id = $config['shop_id'];
+ $this->shop_store_no = $config['shop_store_no'];
+ $this->app_secret = $config['app_secret'];
+ return $this;
+ }
+
+
+ /**
+ * 构建请求参数
+ *
+ * @param mixed $body 接口的body参数内容
+ * @return array 构建真正的api接口参数
+ */
+ protected function generateParams($body)
+ {
+ $data = [
+ "source_id" => $this->shop_id,
+ "app_key" => $this->app_key,
+ "timestamp" => time(),
+ "format" => "json",
+ "v" => "1.0",
+ "body" => empty($body) ? "" : json_encode($body),
+ ];
+
+ $data["signature"] = $this->signature($data);
+ return $data;
+ }
+
+ /**
+ * 生成签名
+ *
+ * @param array $data 请求参数
+ * @param string $app_secret 应用密钥
+ * @return string 签名结果
+ */
+ private function signature($data)
+ {
+ // 请求参数按照【属性名】字典升序排序
+ ksort($data);
+
+ // 按照属性名+属性值拼接
+ $signStr = '';
+ foreach ($data as $key => $value) {
+ $signStr .= $key . $value;
+ }
+
+ // 拼接后的结果首尾加上appSecret
+ $finalSignStr = $this->app_secret . $signStr . $this->app_secret;
+
+ // MD5加密并转为大写
+ return strtoupper(md5($finalSignStr));
+ }
+
+ protected function request($body, $method_url)
+ {
+ $product_type = env('product_type');
+ if ($product_type != 'product') {
+ $domain = $this->test_domain;
+ } else {
+ $domain = $this->domain;
+ }
+ $request_data = $this->generateParams($body);
+ $res = (new HttpHelper())->httpRequest('POST', $domain . $method_url, $request_data);
+ if ($res['code'] != 0) {
+ throw new \Exception('DD' . $res['code'] . ":" . $res['msg']);
+ }
+ return $res['result'];
+ }
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/app/service/core/delivery/third_delivery/sdk/Dada/ConfigRequest.php b/niucloud/addon/shop/app/service/core/delivery/third_delivery/sdk/Dada/ConfigRequest.php
new file mode 100644
index 000000000..a6044b8c6
--- /dev/null
+++ b/niucloud/addon/shop/app/service/core/delivery/third_delivery/sdk/Dada/ConfigRequest.php
@@ -0,0 +1,12 @@
+request([], $this->cancel_reason_url);
+ }
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/app/service/core/delivery/third_delivery/sdk/Dada/OrderCancelRequest.php b/niucloud/addon/shop/app/service/core/delivery/third_delivery/sdk/Dada/OrderCancelRequest.php
new file mode 100644
index 000000000..3c04668ce
--- /dev/null
+++ b/niucloud/addon/shop/app/service/core/delivery/third_delivery/sdk/Dada/OrderCancelRequest.php
@@ -0,0 +1,82 @@
+cancel_reason = $cancel_reason;
+ return $this;
+ }
+
+ public function getCancelReason(): string
+ {
+ return $this->cancel_reason;
+ }
+
+ public function setCancelReasonId(int $cancel_reason_id): self
+ {
+ $this->cancel_reason_id = $cancel_reason_id;
+ return $this;
+ }
+
+ public function getCancelReasonId(): int
+ {
+ return $this->cancel_reason_id;
+ }
+
+ public function setOrderId(string $order_id): self
+ {
+ $this->order_id = $order_id;
+ return $this;
+ }
+
+ public function getOrderId(): string
+ {
+ return $this->order_id;
+ }
+
+ public function toArray(): array
+ {
+ return [
+ 'cancel_reason' => $this->cancel_reason,
+ 'cancel_reason_id' => $this->cancel_reason_id,
+ 'order_id' => $this->order_id,
+ ];
+ }
+
+ public function toJson(): string
+ {
+ return json_encode($this->toArray(), JSON_UNESCAPED_UNICODE);
+ }
+
+ private function validate()
+ {
+ if (empty($this->order_id)) {
+ throw new \Exception('订单ID不能为空');
+ }
+ if (empty($this->cancel_reason_id ==1 )) {
+ throw new \Exception('订单ID不能为空');
+ }
+ }
+
+ public function sendRequest()
+ {
+ $this->validate();
+ $body = $this->toArray();
+ foreach ($body as $key => $value) {
+ if (is_null($value)) {
+ unset($body[$key]);
+ }
+ }
+ return $this->request($body, $this->request_url);
+ }
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/app/service/core/delivery/third_delivery/sdk/Dada/OrderCreateByFeeOrderNoRequest.php b/niucloud/addon/shop/app/service/core/delivery/third_delivery/sdk/Dada/OrderCreateByFeeOrderNoRequest.php
new file mode 100644
index 000000000..1052f04db
--- /dev/null
+++ b/niucloud/addon/shop/app/service/core/delivery/third_delivery/sdk/Dada/OrderCreateByFeeOrderNoRequest.php
@@ -0,0 +1,78 @@
+delivery_no = $delivery_no;
+ return $this;
+ }
+
+ public function getDeliveryNo()
+ {
+ return $this->delivery_no;
+ }
+
+ public function setEnableReset($enable_reset)
+ {
+ $this->enable_reset = $enable_reset;
+ return $this;
+ }
+
+ public function getEnableReset()
+ {
+ return $this->enable_reset;
+ }
+
+ public function setInfo($info)
+ {
+ $this->info = $info;
+ return $this;
+ }
+
+ public function getInfo()
+ {
+ return $this->info;
+ }
+
+ public function toArray()
+ {
+ return [
+ 'delivery_no' => $this->delivery_no,
+ 'enable_reset' => $this->enable_reset,
+ 'info' => $this->info,
+ ];
+ }
+
+ public function toJson(): string
+ {
+ return json_encode($this->toArray(), JSON_UNESCAPED_UNICODE);
+ }
+ private function validate()
+ {
+ if (empty($this->delivery_no)) {
+ throw new \Exception('单号不能为空');
+ }
+ }
+ public function sendRequest()
+ {
+ $this->validate();
+ $body = $this->toArray();
+ foreach ($body as $key => $value) {
+ if (is_null($value)) {
+ unset($body[$key]);
+ }
+ }
+ return $this->request($body,$this->request_url);
+ }
+
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/app/service/core/delivery/third_delivery/sdk/Dada/OrderCreateRequest.php b/niucloud/addon/shop/app/service/core/delivery/third_delivery/sdk/Dada/OrderCreateRequest.php
new file mode 100644
index 000000000..ceb67c17b
--- /dev/null
+++ b/niucloud/addon/shop/app/service/core/delivery/third_delivery/sdk/Dada/OrderCreateRequest.php
@@ -0,0 +1,436 @@
+cargo_num = $cargo_num;
+ return $this;
+ }
+
+ public function getCargoNum()
+ {
+ return $this->cargo_num;
+ }
+
+ // 货物价格
+ public function setCargoPrice($cargo_price)
+ {
+ $this->cargo_price = $cargo_price;
+ return $this;
+ }
+
+ public function getCargoPrice()
+ {
+ return $this->cargo_price;
+ }
+
+ // 货物类型
+ public function setCargoType($cargo_type)
+ {
+ $this->cargo_type = $cargo_type;
+ return $this;
+ }
+
+ public function getCargoType()
+ {
+ return $this->cargo_type;
+ }
+
+ // 货物重量
+ public function setCargoWeight($cargo_weight)
+ {
+ $this->cargo_weight = $cargo_weight;
+ return $this;
+ }
+
+ public function getCargoWeight()
+ {
+ return $this->cargo_weight;
+ }
+
+ // 备注信息
+ public function setInfo($info)
+ {
+ $this->info = $info;
+ return $this;
+ }
+
+ public function getInfo()
+ {
+ return $this->info;
+ }
+
+ // 发票抬头
+ public function setInvoiceTitle($invoice_title)
+ {
+ $this->invoice_title = $invoice_title;
+ return $this;
+ }
+
+ public function getInvoiceTitle()
+ {
+ return $this->invoice_title;
+ }
+
+ // 是否需要收货码
+ public function setIsFinishCodeNeeded($is_finish_code_needed)
+ {
+ $this->is_finish_code_needed = $is_finish_code_needed;
+ return $this;
+ }
+
+ public function getIsFinishCodeNeeded()
+ {
+ return $this->is_finish_code_needed;
+ }
+
+ // 是否垫付
+ public function setIsPrepay($is_prepay)
+ {
+ $this->is_prepay = $is_prepay;
+ return $this;
+ }
+
+ public function getIsPrepay()
+ {
+ return $this->is_prepay;
+ }
+
+ // 是否保价
+ public function setIsUseInsurance($is_use_insurance)
+ {
+ $this->is_use_insurance = $is_use_insurance;
+ return $this;
+ }
+
+ public function getIsUseInsurance()
+ {
+ return $this->is_use_insurance;
+ } // 是否保价
+
+ public function setIsExpectFinishOrder($is_expect_finish_order)
+ {
+ $this->is_expect_finish_order = $is_expect_finish_order;
+ return $this;
+ }
+
+ public function getIsExpectFinishOrder()
+ {
+ return $this->is_expect_finish_order;
+ }
+
+ // 订单ID
+ public function setOriginId($origin_id)
+ {
+ $this->origin_id = $origin_id;
+ return $this;
+ }
+
+ public function getOriginId()
+ {
+ return $this->origin_id;
+ }
+
+ // 取货位置
+ public function setPickUpPos($pick_up_pos)
+ {
+ $this->pick_up_pos = $pick_up_pos;
+ return $this;
+ }
+
+ public function getPickUpPos()
+ {
+ return $this->pick_up_pos;
+ }
+
+ // 商品列表
+ public function setProductList($product_list)
+ {
+ $this->product_list = $product_list;
+ return $this;
+ }
+
+ public function getProductList()
+ {
+ return $this->product_list;
+ }
+
+ // 添加单个商品
+ public function addProductItem($product_item)
+ {
+ $this->product_list[] = $product_item;
+ return $this;
+ }
+
+ // 收货人地址
+ public function setReceiverAddress($receiver_address)
+ {
+ $this->receiver_address = $receiver_address;
+ return $this;
+ }
+
+ public function getReceiverAddress()
+ {
+ return $this->receiver_address;
+ }
+
+ // 收货人纬度
+ public function setReceiverLat($receiver_lat)
+ {
+ $this->receiver_lat = $receiver_lat;
+ return $this;
+ }
+
+ public function getReceiverLat()
+ {
+ return $this->receiver_lat;
+ }
+
+ // 收货人经度
+ public function setReceiverLng($receiver_lng)
+ {
+ $this->receiver_lng = $receiver_lng;
+ return $this;
+ }
+
+ public function getReceiverLng()
+ {
+ return $this->receiver_lng;
+ }
+
+ // 收货人姓名
+ public function setReceiverName($receiver_name)
+ {
+ $this->receiver_name = $receiver_name;
+ return $this;
+ }
+
+ public function getReceiverName()
+ {
+ return $this->receiver_name;
+ }
+
+ // 收货人电话
+ public function setReceiverPhone($receiver_phone)
+ {
+ $this->receiver_phone = $receiver_phone;
+ return $this;
+ }
+
+ public function getReceiverPhone()
+ {
+ return $this->receiver_phone;
+ }
+
+ // 门店编号
+ public function setShopNo($shop_no)
+ {
+ $this->shop_no = $shop_no;
+ return $this;
+ }
+
+ public function getShopNo()
+ {
+ return $this->shop_no;
+ }
+
+ // 小费
+ public function setTips($tips)
+ {
+ $this->tips = $tips;
+ return $this;
+ }
+
+ public function getTips()
+ {
+ return $this->tips;
+ }
+
+ // 业务类型
+ public function setBusinessType($business_type)
+ {
+ $this->business_type = $business_type;
+ return $this;
+ }
+
+ public function getBusinessType()
+ {
+ return $this->business_type;
+ }
+
+ // 商家地址
+ public function setSupplierAddress($supplier_address)
+ {
+ $this->supplier_address = $supplier_address;
+ return $this;
+ }
+
+ public function getSupplierAddress()
+ {
+ return $this->supplier_address;
+ }
+
+ // 商家纬度
+ public function setSupplierLat($supplier_lat)
+ {
+ $this->supplier_lat = $supplier_lat;
+ return $this;
+ }
+
+ public function getSupplierLat()
+ {
+ return $this->supplier_lat;
+ }
+
+ // 商家经度
+ public function setSupplierLng($supplier_lng)
+ {
+ $this->supplier_lng = $supplier_lng;
+ return $this;
+ }
+
+ public function getSupplierLng()
+ {
+ return $this->supplier_lng;
+ }
+
+ // 商家名称
+ public function setSupplierName($supplier_name)
+ {
+ $this->supplier_name = $supplier_name;
+ return $this;
+ }
+
+ public function getSupplierName()
+ {
+ return $this->supplier_name;
+ }
+
+ // 商家电话
+ public function setSupplierPhone($supplier_phone)
+ {
+ $this->supplier_phone = $supplier_phone;
+ return $this;
+ }
+
+ public function getSupplierPhone()
+ {
+ return $this->supplier_phone;
+ }
+
+ // 将对象转换为数组
+ public function toArray()
+ {
+ return [
+ 'callback' => $this->callback,
+ 'cargo_num' => $this->cargo_num,
+ 'cargo_price' => $this->cargo_price,
+ 'cargo_type' => $this->cargo_type,
+ 'cargo_weight' => $this->cargo_weight,
+ 'info' => $this->info,
+ 'invoice_title' => $this->invoice_title,
+ 'is_finish_code_needed' => $this->is_finish_code_needed ? 1 : 0,
+ 'is_prepay' => $this->is_prepay ? 1 : 0,
+ 'is_use_insurance' => $this->is_use_insurance ? 1 : 0,
+ 'origin_id' => $this->origin_id,
+ 'pick_up_pos' => $this->pick_up_pos,
+ 'product_list' => $this->product_list,
+ 'receiver_address' => $this->receiver_address,
+ 'receiver_lat' => $this->receiver_lat,
+ 'receiver_lng' => $this->receiver_lng,
+ 'receiver_name' => $this->receiver_name,
+ 'receiver_phone' => $this->receiver_phone,
+ 'shop_no' => $this->shop_no,
+ 'tips' => $this->tips,
+ 'business_type' => $this->business_type,
+ 'supplier_address' => $this->supplier_address,
+ 'supplier_lat' => $this->supplier_lat,
+ 'supplier_lng' => $this->supplier_lng,
+ 'supplier_name' => $this->supplier_name,
+ 'supplier_phone' => $this->supplier_phone,
+ ];
+ }
+
+ // 将对象转换为JSON
+ public function toJson()
+ {
+ return json_encode($this->toArray(), JSON_UNESCAPED_UNICODE);
+ }
+
+ private function validate()
+ {
+ if (empty($this->shop_no)) {
+ throw new \Exception('门店编号不能为空');
+ }
+ if (empty($this->origin_id)) {
+ throw new \Exception('第三方订单ID不能为空');
+ }
+ if (empty($this->cargo_price)) {
+ throw new \Exception('订单金额不能为空');
+ }
+ if (empty($this->receiver_name)) {
+ throw new \Exception('收货人名称不能为空');
+ }
+ if (empty($this->receiver_address)) {
+ throw new \Exception('收货人地址不能为空');
+ }
+ if (empty($this->receiver_lat) || empty($this->receiver_lng)) {
+ throw new \Exception('收货人地址经纬度不能为空');
+ }
+ if (empty($this->callback)) {
+ throw new \Exception('回调URL不能为空');
+ }
+ if ($this->cargo_weight <= 0) {
+ throw new \Exception('订单重量必须大于0');
+ }
+ if (empty($this->receiver_phone)) {
+ throw new \Exception('收货人手机号不能为空');
+ }
+ }
+
+ public function sendRequest()
+ {
+ $this->validate();
+ $body = $this->toArray();
+ foreach ($body as $key => $value) {
+ if (is_null($value)) {
+ unset($body[$key]);
+ }
+ }
+ return $this->request($body,$this->request_url);
+ }
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/app/service/core/delivery/third_delivery/sdk/Dada/OrderFeeRequest.php b/niucloud/addon/shop/app/service/core/delivery/third_delivery/sdk/Dada/OrderFeeRequest.php
new file mode 100644
index 000000000..1e67ab984
--- /dev/null
+++ b/niucloud/addon/shop/app/service/core/delivery/third_delivery/sdk/Dada/OrderFeeRequest.php
@@ -0,0 +1,432 @@
+cargo_num = $cargo_num;
+ return $this;
+ }
+
+ public function getCargoNum()
+ {
+ return $this->cargo_num;
+ }
+
+ // 货物价格
+ public function setCargoPrice($cargo_price)
+ {
+ $this->cargo_price = $cargo_price;
+ return $this;
+ }
+
+ public function getCargoPrice()
+ {
+ return $this->cargo_price;
+ }
+
+ // 货物类型
+ public function setCargoType($cargo_type)
+ {
+ $this->cargo_type = $cargo_type;
+ return $this;
+ }
+
+ public function getCargoType()
+ {
+ return $this->cargo_type;
+ }
+
+ // 货物重量
+ public function setCargoWeight($cargo_weight)
+ {
+ $this->cargo_weight = $cargo_weight;
+ return $this;
+ }
+
+ public function getCargoWeight()
+ {
+ return $this->cargo_weight;
+ }
+
+ // 备注信息
+ public function setInfo($info)
+ {
+ $this->info = $info;
+ return $this;
+ }
+
+ public function getInfo()
+ {
+ return $this->info;
+ }
+
+ // 发票抬头
+ public function setInvoiceTitle($invoice_title)
+ {
+ $this->invoice_title = $invoice_title;
+ return $this;
+ }
+
+ public function getInvoiceTitle()
+ {
+ return $this->invoice_title;
+ }
+
+ // 是否需要收货码
+ public function setIsFinishCodeNeeded($is_finish_code_needed)
+ {
+ $this->is_finish_code_needed = $is_finish_code_needed;
+ return $this;
+ }
+
+ public function getIsFinishCodeNeeded()
+ {
+ return $this->is_finish_code_needed;
+ }
+
+ // 是否垫付
+ public function setIsPrepay($is_prepay)
+ {
+ $this->is_prepay = $is_prepay;
+ return $this;
+ }
+
+ public function getIsPrepay()
+ {
+ return $this->is_prepay;
+ }
+
+ // 是否保价
+ public function setIsUseInsurance($is_use_insurance)
+ {
+ $this->is_use_insurance = $is_use_insurance;
+ return $this;
+ }
+
+ public function getIsUseInsurance()
+ {
+ return $this->is_use_insurance;
+ }
+
+ // 订单ID
+ public function setOriginId($origin_id)
+ {
+ $this->origin_id = $origin_id;
+ return $this;
+ }
+
+ public function getOriginId()
+ {
+ return $this->origin_id;
+ }
+
+ // 取货位置
+ public function setPickUpPos($pick_up_pos)
+ {
+ $this->pick_up_pos = $pick_up_pos;
+ return $this;
+ }
+
+ public function getPickUpPos()
+ {
+ return $this->pick_up_pos;
+ }
+
+ // 商品列表
+ public function setProductList($product_list)
+ {
+ $this->product_list = $product_list;
+ return $this;
+ }
+
+ public function getProductList()
+ {
+ return $this->product_list;
+ }
+
+ // 收货人地址
+ public function setReceiverAddress($receiver_address)
+ {
+ $this->receiver_address = $receiver_address;
+ return $this;
+ }
+
+ public function getReceiverAddress()
+ {
+ return $this->receiver_address;
+ }
+
+ // 收货人纬度
+ public function setReceiverLat($receiver_lat)
+ {
+ $this->receiver_lat = $receiver_lat;
+ return $this;
+ }
+
+ public function getReceiverLat()
+ {
+ return $this->receiver_lat;
+ }
+
+ // 收货人经度
+ public function setReceiverLng($receiver_lng)
+ {
+ $this->receiver_lng = $receiver_lng;
+ return $this;
+ }
+
+ public function getReceiverLng()
+ {
+ return $this->receiver_lng;
+ }
+
+ // 收货人姓名
+ public function setReceiverName($receiver_name)
+ {
+ $this->receiver_name = $receiver_name;
+ return $this;
+ }
+
+ public function getReceiverName()
+ {
+ return $this->receiver_name;
+ }
+
+ // 收货人电话
+ public function setReceiverPhone($receiver_phone)
+ {
+ $this->receiver_phone = $receiver_phone;
+ return $this;
+ }
+
+ public function getReceiverPhone()
+ {
+ return $this->receiver_phone;
+ }
+
+ // 门店编号
+ public function setShopNo($shop_no)
+ {
+ $this->shop_no = $shop_no;
+ return $this;
+ }
+
+ public function getShopNo()
+ {
+ return $this->shop_no;
+ }
+
+ // 小费
+ public function setTips($tips)
+ {
+ $this->tips = $tips;
+ return $this;
+ }
+
+ public function getTips()
+ {
+ return $this->tips;
+ }
+
+ // 业务类型
+ public function setBusinessType($business_type)
+ {
+ $this->business_type = $business_type;
+ return $this;
+ }
+
+ public function getBusinessType()
+ {
+ return $this->business_type;
+ }
+
+ // 商家地址
+ public function setSupplierAddress($supplier_address)
+ {
+ $this->supplier_address = $supplier_address;
+ return $this;
+ }
+
+ public function getSupplierAddress()
+ {
+ return $this->supplier_address;
+ }
+
+ // 商家纬度
+ public function setSupplierLat($supplier_lat)
+ {
+ $this->supplier_lat = $supplier_lat;
+ return $this;
+ }
+
+ public function getSupplierLat()
+ {
+ return $this->supplier_lat;
+ }
+
+ // 商家经度
+ public function setSupplierLng($supplier_lng)
+ {
+ $this->supplier_lng = $supplier_lng;
+ return $this;
+ }
+
+ public function getSupplierLng()
+ {
+ return $this->supplier_lng;
+ }
+
+ // 商家名称
+ public function setSupplierName($supplier_name)
+ {
+ $this->supplier_name = $supplier_name;
+ return $this;
+ }
+
+ public function getSupplierName()
+ {
+ return $this->supplier_name;
+ }
+
+ // 商家电话
+ public function setSupplierPhone($supplier_phone)
+ {
+ $this->supplier_phone = $supplier_phone;
+ return $this;
+ }
+
+ public function getSupplierPhone()
+ {
+ return $this->supplier_phone;
+ }
+
+ // 将对象转换为数组
+ public function toArray()
+ {
+ return [
+ 'callback' => $this->callback,
+ 'cargo_num' => $this->cargo_num,
+ 'cargo_price' => $this->cargo_price,
+ 'cargo_type' => $this->cargo_type,
+ 'cargo_weight' => $this->cargo_weight,
+ 'info' => $this->info,
+ 'invoice_title' => $this->invoice_title,
+ 'is_finish_code_needed' => $this->is_finish_code_needed,
+ 'is_prepay' => $this->is_prepay,
+ 'is_use_insurance' => $this->is_use_insurance,
+ 'origin_id' => $this->origin_id,
+ 'pick_up_pos' => $this->pick_up_pos,
+ 'product_list' => $this->product_list,
+ 'receiver_address' => $this->receiver_address,
+ 'receiver_lat' => $this->receiver_lat,
+ 'receiver_lng' => $this->receiver_lng,
+ 'receiver_name' => $this->receiver_name,
+ 'receiver_phone' => $this->receiver_phone,
+ 'shop_no' => $this->shop_no,
+ 'tips' => $this->tips,
+ 'business_type' => $this->business_type,
+ 'supplier_address' => $this->supplier_address,
+ 'supplier_lat' => $this->supplier_lat,
+ 'supplier_lng' => $this->supplier_lng,
+ 'supplier_name' => $this->supplier_name,
+ 'supplier_phone' => $this->supplier_phone,
+ ];
+ }
+
+ public function toJson(): string
+ {
+ $body = $this->toArray();
+ foreach ($body as $key => $value) {
+ if (is_null($value)) {
+ unset($body[$key]);
+ }
+ }
+ return json_encode($body, JSON_UNESCAPED_UNICODE);
+ }
+
+ private function validate()
+ {
+ if (empty($this->shop_no)) {
+ throw new \Exception('门店编号不能为空');
+ }
+ if (empty($this->origin_id)) {
+ throw new \Exception('第三方订单ID不能为空');
+ }
+ if (empty($this->cargo_price)) {
+ throw new \Exception('订单金额不能为空');
+ }
+ if (empty($this->receiver_name)) {
+ throw new \Exception('收货人名称不能为空');
+ }
+ if (empty($this->receiver_address)) {
+ throw new \Exception('收货人地址不能为空');
+ }
+ if (empty($this->receiver_lat) || empty($this->receiver_lng)) {
+ throw new \Exception('收货人地址经纬度不能为空');
+ }
+ if (empty($this->callback)) {
+ throw new \Exception('回调URL不能为空');
+ }
+ if ($this->cargo_weight <= 0) {
+ throw new \Exception('订单重量必须大于0');
+ }
+ if (empty($this->receiver_phone)) {
+ throw new \Exception('收货人手机号不能为空');
+ }
+ }
+
+ public function sendRequest()
+ {
+ $this->validate();
+ $body = $this->toArray();
+ foreach ($body as $key => $value) {
+ if (is_null($value)) {
+ unset($body[$key]);
+ }
+ }
+ return $this->request($body,$this->request_url);
+ }
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/app/service/core/delivery/third_delivery/sdk/Dada/OrderInfoRequest.php b/niucloud/addon/shop/app/service/core/delivery/third_delivery/sdk/Dada/OrderInfoRequest.php
new file mode 100644
index 000000000..f0e52f1a3
--- /dev/null
+++ b/niucloud/addon/shop/app/service/core/delivery/third_delivery/sdk/Dada/OrderInfoRequest.php
@@ -0,0 +1,53 @@
+order_id = $order_id;
+ return $this;
+ }
+
+ public function getOrderId(): string
+ {
+ return $this->order_id;
+ }
+
+ public function toArray(): array
+ {
+ return [
+ 'order_id' => $this->order_id,
+ ];
+ }
+
+ public function toJson(): string
+ {
+ return json_encode($this->toArray(), JSON_UNESCAPED_UNICODE);
+ }
+
+ private function validate()
+ {
+ if (empty($this->order_id)) {
+ throw new \Exception('订单ID不能为空');
+ }
+ }
+
+ public function sendRequest()
+ {
+ $this->validate();
+ $body = $this->toArray();
+ foreach ($body as $key => $value) {
+ if (is_null($value)) {
+ unset($body[$key]);
+ }
+ }
+ return $this->request($body, $this->request_url);
+ }
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/app/service/core/delivery/third_delivery/sdk/Dada/OrderTransporterPositionH5Request.php b/niucloud/addon/shop/app/service/core/delivery/third_delivery/sdk/Dada/OrderTransporterPositionH5Request.php
new file mode 100644
index 000000000..579e8797f
--- /dev/null
+++ b/niucloud/addon/shop/app/service/core/delivery/third_delivery/sdk/Dada/OrderTransporterPositionH5Request.php
@@ -0,0 +1,56 @@
+order_id = $order_id;
+ return $this;
+ }
+
+ public function getOrderId()
+ {
+ return $this->order_id;
+ }
+
+
+ public function toArray()
+ {
+ return [
+ 'order_id' => $this->order_id,
+ ];
+ }
+
+ public function toJson()
+ {
+ return json_encode($this->toArray(), JSON_UNESCAPED_UNICODE);
+ }
+
+ private function validate()
+ {
+ if (empty($this->order_id)) {
+ throw new \Exception('订单ID不能为空');
+ }
+ }
+
+ public function sendRequest()
+ {
+ $this->validate();
+ $body = $this->toArray();
+ foreach ($body as $key => $value) {
+ if (is_null($value)) {
+ unset($body[$key]);
+ }
+ }
+ return $this->request($body, $this->request_url);
+ }
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/app/service/core/delivery/third_delivery/sdk/Dada/OrderTransporterPositionRequest.php b/niucloud/addon/shop/app/service/core/delivery/third_delivery/sdk/Dada/OrderTransporterPositionRequest.php
new file mode 100644
index 000000000..3be65c24a
--- /dev/null
+++ b/niucloud/addon/shop/app/service/core/delivery/third_delivery/sdk/Dada/OrderTransporterPositionRequest.php
@@ -0,0 +1,62 @@
+order_ids = $order_ids;
+ return $this;
+ }
+
+ public function getOrderIds()
+ {
+ return $this->order_ids;
+ }
+
+ // 添加单个商品
+ public function addProductItem($order_id)
+ {
+ $this->order_ids[] = $order_id;
+ return $this;
+ }
+
+ public function toArray()
+ {
+ return [
+ 'order_ids' => $this->order_ids,
+ ];
+ }
+
+ public function toJson()
+ {
+ return json_encode($this->toArray(), JSON_UNESCAPED_UNICODE);
+ }
+
+ private function validate()
+ {
+ if (empty($this->order_ids)) {
+ throw new \Exception('订单ID不能为空');
+ }
+ }
+
+ public function sendRequest()
+ {
+ $this->validate();
+ $body = $this->toArray();
+ foreach ($body as $key => $value) {
+ if (is_null($value)) {
+ unset($body[$key]);
+ }
+ }
+ return $this->request($body, $this->request_url);
+ }
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/app/service/core/goods/CoreGoodsAccessNumService.php b/niucloud/addon/shop/app/service/core/goods/CoreGoodsAccessNumService.php
new file mode 100644
index 000000000..cfe8ee6bb
--- /dev/null
+++ b/niucloud/addon/shop/app/service/core/goods/CoreGoodsAccessNumService.php
@@ -0,0 +1,51 @@
+model = new Goods();
+ }
+
+ /**
+ * 增加
+ * @param $data
+ * @return void
+ */
+ public function inc($data)
+ {
+ $this->model->where([['goods_id', '=', $data['goods_id']]])->inc('access_num', $data['access_num']) ->update();
+ return true;
+ }
+
+ /**
+ * 减少
+ * @param $data
+ * @return void
+ */
+ public function dec($data)
+ {
+ $this->model->where([['goods_id', '=', $data['goods_id']]])->dec('access_num', $data['access_num']) ->update();
+ return true;
+ }
+
+}
diff --git a/niucloud/addon/shop/app/service/core/goods/CoreGoodsActivePriceService.php b/niucloud/addon/shop/app/service/core/goods/CoreGoodsActivePriceService.php
new file mode 100644
index 000000000..0c473369e
--- /dev/null
+++ b/niucloud/addon/shop/app/service/core/goods/CoreGoodsActivePriceService.php
@@ -0,0 +1,159 @@
+ $price, 'show_type' => GoodsDict::ORIGINAL_PRICE ]
+ ];
+
+ $goods_service = new GoodsService();
+
+ if ($member_id > 0) {
+ $member_price = $goods_service->getMemberPrice($goods_service->getMemberInfo(), $sku_info[ 'member_discount' ], $sku_info[ 'member_price' ], $price);
+ $show_price_data[] = [ 'show_price' => $member_price, 'show_type' => GoodsDict::MEMBER_PRICE ];
+ }
+
+ $discount = (new DiscountGoods())->where([
+ [ 'goods_id', '=', $sku_info['goods_id'] ],
+ [ 'sku_id', '=', $sku_info['sku_id'] ],
+ [ 'status', '=', DiscountDict::ACTIVE ],
+ [ 'is_enabled', '=', DiscountDict::YES ],
+ ])->findOrEmpty();
+
+ if (!$discount->isEmpty()) {
+ $discount_price = floatval($sku_info[ 'sale_price' ] ?? 0);
+ $show_price_data[] = [ 'show_price' => $discount_price, 'show_type' => GoodsDict::DISCOUNT_PRICE, 'discount_id' => $discount['discount_id'] ];
+ }
+
+ return $this->getMinShowPrice($show_price_data, $price);
+ }
+
+ /**
+ * 查询商品的展示价格
+ * @param $sku_info
+ * @param $member_id
+ * @return array
+ */
+ public function getShowPrice($sku_info, $member_id)
+ {
+ $type = $sku_info[ 'type' ] ?? '';
+ $price = floatval($sku_info[ 'price' ]);
+ $show_price_data = [
+ [ 'show_price' => $price, 'show_type' => GoodsDict::ORIGINAL_PRICE ]
+ ];
+
+ $goods_service = new GoodsService();
+
+ if ($member_id > 0) {
+ $member_price = $goods_service->getMemberPrice($goods_service->getMemberInfo(), $sku_info[ 'member_discount' ], $sku_info[ 'member_price' ], $price);
+ $show_price_data[] = [ 'show_price' => $member_price, 'show_type' => GoodsDict::MEMBER_PRICE ];
+ }
+
+ $discount = (new DiscountGoods())->where([
+ [ 'goods_id', '=', $sku_info['goods_id'] ],
+ [ 'sku_id', '=', $sku_info['sku_id'] ],
+ [ 'status', '=', DiscountDict::ACTIVE ],
+ [ 'is_enabled', '=', DiscountDict::YES ],
+ ])->findOrEmpty();
+
+ if (!$discount->isEmpty()) {
+ $discount_price = floatval($sku_info[ 'sale_price' ] ?? 0);
+ $show_price_data[] = [ 'show_price' => $discount_price, 'show_type' => GoodsDict::DISCOUNT_PRICE ];
+ }
+
+// // 如果有活动类型,只保留该类型对应的价格和原价
+// if (!empty($type)) {
+// $show_type = '';
+//
+// switch ($type){
+// case ActiveDict::DISCOUNT:
+// $show_type = GoodsDict::DISCOUNT_PRICE;
+// break;
+// }
+// if (!empty($show_type)){
+// $show_price_data = array_filter($show_price_data, function ($item) use ($show_type) {
+// return in_array($item[ 'show_type' ], [GoodsDict::ORIGINAL_PRICE, $show_type]);
+// });
+// }else{
+// $show_price_data = [[ 'show_price' => $price, 'show_type' => GoodsDict::ORIGINAL_PRICE ]];
+// }
+//
+// // 重建索引
+// $show_price_data = array_values($show_price_data);
+// }
+ return $this->getMinShowPrice($show_price_data, $price);
+ }
+
+ /**
+ * 提取最低价格(优先 original_price)
+ * @param $price_data
+ * @param $original_price
+ * @return array
+ */
+ private function getMinShowPrice(array $price_data, float $original_price): array
+ {
+ $priority = [
+ 'discount_price' => 1,
+ 'member_price' => 2,
+ 'original_price' => 3,
+ ];
+
+ usort($price_data, function ($one, $two) use ($priority){
+ $price_cmp = floatval($one[ 'show_price' ]) <=> floatval($two[ 'show_price' ]);
+
+ if ($price_cmp === 0) {
+ // 价格相等时按优先级排序,数字越小优先级越高
+ return ($priority[ $one[ 'show_type' ] ] ?? 99) <=> ($priority[ $two[ 'show_type' ] ] ?? 99);
+ }
+
+ return $price_cmp;
+ });
+
+ $min = $price_data[0];
+
+ if ($min[ 'show_type' ] !== GoodsDict::ORIGINAL_PRICE && floatval($min[ 'show_price' ]) == $original_price) {
+ $min[ 'show_type' ] = GoodsDict::ORIGINAL_PRICE;
+ }
+ return $min;
+ }
+
+
+
+}
diff --git a/niucloud/addon/shop/app/service/core/goods/CoreGoodsCartNumService.php b/niucloud/addon/shop/app/service/core/goods/CoreGoodsCartNumService.php
new file mode 100644
index 000000000..881fc0ed0
--- /dev/null
+++ b/niucloud/addon/shop/app/service/core/goods/CoreGoodsCartNumService.php
@@ -0,0 +1,51 @@
+model = new Goods();
+ }
+
+ /**
+ * 增加
+ * @param $data
+ * @return void
+ */
+ public function inc($data)
+ {
+ $this->model->where([['goods_id', '=', $data['goods_id']]])->inc('cart_num', $data['cart_num']) ->update();
+ return true;
+ }
+
+ /**
+ * 减少
+ * @param $data
+ * @return void
+ */
+ public function dec($data)
+ {
+ $this->model->where([['goods_id', '=', $data['goods_id']]])->dec('cart_num', $data['cart_num']) ->update();
+ return true;
+ }
+
+}
diff --git a/niucloud/addon/shop/app/service/core/goods/CoreGoodsCategoryService.php b/niucloud/addon/shop/app/service/core/goods/CoreGoodsCategoryService.php
new file mode 100644
index 000000000..488b41fa5
--- /dev/null
+++ b/niucloud/addon/shop/app/service/core/goods/CoreGoodsCategoryService.php
@@ -0,0 +1,70 @@
+model = new Category();
+ }
+
+ /**
+ * 设置商品分类配置
+ * @param array $params
+ * @return array
+ */
+ public function setGoodsCategoryConfig(array $params = [])
+ {
+ $goods_config_service = new CoreGoodsConfigService();
+ $res = $goods_config_service->setGoodsCategoryConfig($params);
+ return $res;
+ }
+
+ /**
+ * 获取商品分类配置
+ * @return array
+ */
+ public function getGoodsCategoryConfig()
+ {
+ $goods_config_service = new CoreGoodsConfigService();
+ $res = $goods_config_service->getGoodsCategoryConfig();
+ return $res;
+ }
+
+ /**
+ * 查询商品分类树结构
+ * @param string $condition
+ * @param string $field
+ * @param string $order
+ * @return array
+ */
+ public function getTree($condition = [], $field = 'category_id,category_name,image,level,pid,category_full_name,is_show,sort', $order = 'sort desc, create_time desc')
+ {
+ $list = $this->model->where($condition)->field($field)->order($order)->select()->toArray();
+ $list = list_to_tree($list, 'category_id', 'pid', 'child_list');
+ return $list;
+ }
+
+}
diff --git a/niucloud/addon/shop/app/service/core/goods/CoreGoodsCollectNumService.php b/niucloud/addon/shop/app/service/core/goods/CoreGoodsCollectNumService.php
new file mode 100644
index 000000000..4186d1ef7
--- /dev/null
+++ b/niucloud/addon/shop/app/service/core/goods/CoreGoodsCollectNumService.php
@@ -0,0 +1,51 @@
+model = new Goods();
+ }
+
+ /**
+ * 增加
+ * @param $data
+ * @return void
+ */
+ public function inc($data)
+ {
+ $this->model->where([['goods_id', '=', $data['goods_id']]])->inc('collect_num', $data['collect_num']) ->update();
+ return true;
+ }
+
+ /**
+ * 减少
+ * @param $data
+ * @return void
+ */
+ public function dec($data)
+ {
+ $this->model->where([['goods_id', '=', $data['goods_id']]])->dec('collect_num', $data['collect_num']) ->update();
+ return true;
+ }
+
+}
diff --git a/niucloud/addon/shop/app/service/core/goods/CoreGoodsConfigService.php b/niucloud/addon/shop/app/service/core/goods/CoreGoodsConfigService.php
new file mode 100644
index 000000000..b0c88fe9e
--- /dev/null
+++ b/niucloud/addon/shop/app/service/core/goods/CoreGoodsConfigService.php
@@ -0,0 +1,198 @@
+core_config_service = new CoreConfigService();
+ }
+
+ /**
+ * 设置商品分类配置
+ * @param array $params
+ * @return array
+ */
+ public function setGoodsCategoryConfig($params)
+ {
+
+ $value = [
+ "level" => $params[ 'level' ], // 展示分类等级
+ "template" => $params[ 'template' ], // 分类模版名称
+ 'page_title' => $params[ 'page_title' ], // 页面标题
+ "search" => $params[ 'search' ],// 顶部搜索框
+ 'goods' => $params[ 'goods' ], // 商品样式,single-cols:单列,double-cols
+ "sort" => $params[ 'sort' ], // 商品排序,default:综合,sales:热销、price:价格
+ 'cart' => $params[ 'cart' ]
+ ];
+
+ $this->core_config_service->setConfig('GOODS_CATEGORY_CONFIG', $value);
+ return true;
+ }
+
+ /**
+ * 获取商品分类配置
+ * @return array
+ */
+ public function getGoodsCategoryConfig()
+ {
+ $res = ( new CoreConfigService() )->getConfig('GOODS_CATEGORY_CONFIG');
+ if (empty($res[ 'value' ])) {
+ $data = [
+ "level" => 2, // 展示分类等级
+ "template" => "style-1", // 分类模版名称
+ 'page_title' => '商品分类', // 页面标题
+ // 顶部搜索框
+ "search" => [
+ 'control' => 1, // 开关,1:开启,0:关闭
+ 'title' => '请搜索您想要的商品', // 搜索栏文字
+ ],
+ // 商品样式
+ 'goods' => [
+ 'style' => 'single-cols' // single-cols:单列,double-cols:双列
+ ],
+ "sort" => "default", // 商品排序,default:综合,sales:热销、price:价格
+ 'cart' => [
+ 'control' => 1, // 开关,1:开启,0:关闭
+ 'event' => 'detail', // 购物车事件,detail:跳转商品详情,cart:加入购物车
+ 'style' => 'style-4', // 样式风格
+ 'text' => '购买' //文字
+ ]
+ ];
+ } else {
+ $data = [
+ "level" => (int) $res[ 'value' ][ 'level' ], // 展示分类等级
+ "template" => $res[ 'value' ][ 'template' ], // 分类模版名称
+ 'page_title' => $res[ 'value' ][ 'page_title' ], // 页面标题
+ "search" => $res[ 'value' ][ 'search' ],// 顶部搜索框
+ 'goods' => $res[ 'value' ][ 'goods' ],
+ "sort" => $res[ 'value' ][ 'sort' ], // 商品排序,default:综合,sales:热销、price:价格
+ 'cart' => $res[ 'value' ][ 'cart' ]
+ ];
+
+ }
+ return $data;
+ }
+
+ /**
+ * 获取商品搜索配置
+ * @return array
+ */
+ public function getSearchConfig()
+ {
+ $data = $this->core_config_service->getConfigValue($this->search_key);
+ if (empty($data)) {
+ return [
+ 'default_word' => '',
+ 'search_words' => []
+ ];
+ }
+ return $data;
+ }
+
+ /**
+ * 设置商品搜索配置
+ * @param $data
+ * @return SysConfig|bool|\think\Model
+ */
+ public function setSearchConfig($data)
+ {
+ $data[ 'search_words' ] = explode(',', $data[ 'search_words' ]);
+ return $this->core_config_service->setConfig($this->search_key, $data);
+ }
+
+ /**
+ * 获取编码唯一配置
+ * @return array|int[]|mixed
+ */
+ public function getUniqueConfig()
+ {
+ $data = $this->core_config_service->getConfigValue($this->unique_key);
+ if (empty($data)) {
+ return [
+ 'is_enable' => 0,
+ ];
+ }
+ return $data;
+ }
+
+ /**
+ * 设置商品编码唯一值配置
+ * @param $data
+ * @return SysConfig|bool|\think\Model
+ */
+ public function setUniqueConfig($data)
+ {
+ return $this->core_config_service->setConfig($this->unique_key, $data);
+ }
+
+ /**
+ * 获取商品排序设置
+ * @return array|int[]|mixed
+ */
+ public function getSortConfig()
+ {
+ $data = $this->core_config_service->getConfigValue($this->sort_key);
+ if (empty($data)) {
+ $data = [
+ 'sort_type' => 'desc',
+ 'sort_column' => 'create_time',
+ 'default_sort' => 0,
+ ];
+ }
+ $data[ 'init' ] = [
+ 'sort_type' => GoodsDict::getSortTypeConfig(),
+ 'sort_column' => GoodsDict::getSortColumnConfig(),
+ ];
+
+ return $data;
+ }
+
+ /**
+ * 获取设置的默认排序号
+ * @return int|mixed
+ */
+ public function getDefaultSort()
+ {
+ $sort_config = $this->getSortConfig();
+ return $sort_config[ 'default_sort' ] ?? 0;
+ }
+
+ /**
+ * 设置商品排序配置
+ * @param $data
+ * @return SysConfig|bool|\think\Model
+ */
+ public function setSortConfig($data)
+ {
+ return $this->core_config_service->setConfig($this->sort_key, $data);
+ }
+
+}
diff --git a/niucloud/addon/shop/app/service/core/goods/CoreGoodsEvaluateService.php b/niucloud/addon/shop/app/service/core/goods/CoreGoodsEvaluateService.php
new file mode 100644
index 000000000..d045fb54e
--- /dev/null
+++ b/niucloud/addon/shop/app/service/core/goods/CoreGoodsEvaluateService.php
@@ -0,0 +1,65 @@
+model = new Evaluate();
+ }
+
+ /**
+ * 添加评价
+ * @param $data
+ */
+ public function addEvaluate($data)
+ {
+ $data = [
+ 'order_id' => $data[ 'order_id' ] ?? 0,
+ 'order_goods_id' => $data[ 'order_goods_id' ] ?? 0,
+ 'goods_id' => $data[ 'goods_id' ],
+ 'member_id' => $data[ 'member_id' ] ?? 0,
+ 'member_head' => $data[ 'member_head' ],
+ 'member_name' => $data[ 'member_name' ],
+ 'content' => $data[ 'content' ],
+ 'images' => $data[ 'images' ],
+ 'is_anonymous' => $data[ 'is_anonymous' ],
+ 'scores' => $data[ 'scores' ],
+ 'is_audit' => $data[ 'is_audit' ] ?? 1,
+ 'create_time' => isset($data[ 'create_time' ]) ? strtotime($data[ 'create_time' ]) : time(),
+ 'update_time' => 0
+ ];
+ $res = $this->model->create($data);
+ if($data[ 'order_id' ] > 0) (new Order())->where([['order_id', '=', $data[ 'order_id' ]]])->update(['is_evaluate' => 1]);
+
+ // 无需审核的增加评论统计数
+ if ($data['is_audit'] == EvaluateDict::AUDIT_NO) {
+ CoreGoodsStatService::addStat(['goods_id' => $data[ 'goods_id' ], 'evaluate_num' => 1]);
+ (new Goods())->where([['goods_id', '=', $data['goods_id']]])->inc('evaluate_num', 1) ->update();
+ }
+
+ return $res->evaluate_id;
+ }
+
+}
diff --git a/niucloud/addon/shop/app/service/core/goods/CoreGoodsLimitBuyService.php b/niucloud/addon/shop/app/service/core/goods/CoreGoodsLimitBuyService.php
new file mode 100644
index 000000000..876c20989
--- /dev/null
+++ b/niucloud/addon/shop/app/service/core/goods/CoreGoodsLimitBuyService.php
@@ -0,0 +1,84 @@
+model = new Goods();
+ }
+
+ /**
+ * 检测商品限购
+ * @param int $member_id
+ * @param array $goods_list
+ * @return string
+ */
+ public function checkGoodsLimitBuy(int $member_id, array $goods_list)
+ {
+ $goods_count = count($goods_list);
+ foreach ($goods_list as $item) {
+ if ($item[ 'min_buy' ] > 0) {
+ if ($item[ 'stock' ] < $item[ 'min_buy' ]) {
+ return ($goods_count > 1 ? "商品“" . $item[ 'goods_name' ] . "”" : "该商品") . "库存数量小于起购数量";
+ }
+ if ($item[ 'num' ] < $item[ 'min_buy' ]) {
+ return ($goods_count > 1 ? "商品“" . $item[ 'goods_name' ] . "”" : "该商品") . $item[ 'min_buy' ] . "件起购";
+ }
+ }
+ if ($item[ 'is_limit' ] == 1 && $item[ 'max_buy' ] > 0) {
+ if ($item[ 'limit_type' ] == GoodsDict::SINGLE_TIME) {//单次限购
+ if ($item[ 'num' ] > $item[ 'max_buy' ]) {
+ return ($goods_count > 1 ? "商品“" . $item[ 'goods_name' ] . "”" : "该商品") . "单次限购" . $item[ 'max_buy' ] . "件";
+ }
+ } elseif ($item[ 'limit_type' ] == GoodsDict::SINGLE_PERSON) {//长期限购
+ $sum = $this->getGoodsHasBuyNumber($member_id, $item[ 'goods_id' ]);
+ if ($sum + $item[ 'num' ] > $item[ 'max_buy' ]) {
+ return ($goods_count > 1 ? "商品“" . $item[ 'goods_name' ] . "”" : "该商品") . "每人限购" . $item[ 'max_buy' ] . "件" . ($sum > 0 ? ",您已购买" . $sum . "件" : "");
+ }
+ }
+ }
+ }
+ return "";
+ }
+
+ /**
+ * 获取已购买的商品数量
+ * @param $member_id
+ * @param $goods_id
+ * @return int
+ */
+ public function getGoodsHasBuyNumber($member_id, $goods_id)
+ {
+ return ( new OrderGoods() )->withJoin([ 'orderMain' ])->where([
+ [ 'order_goods.member_id', '=', $member_id ],
+ [ 'order_goods.goods_id', '=', $goods_id ],
+ [ 'order_goods.status', '<>', OrderGoodsDict::REFUND_FINISH ],
+ [ 'orderMain.status', '<>', OrderDict::CLOSE ]
+ ])->sum('num');
+ }
+
+}
diff --git a/niucloud/addon/shop/app/service/core/goods/CoreGoodsRankConfigService.php b/niucloud/addon/shop/app/service/core/goods/CoreGoodsRankConfigService.php
new file mode 100644
index 000000000..3ff1f6a2a
--- /dev/null
+++ b/niucloud/addon/shop/app/service/core/goods/CoreGoodsRankConfigService.php
@@ -0,0 +1,74 @@
+core_config_service = new CoreConfigService();
+ }
+
+ /**
+ * 设置商品排行榜配置
+ * @param array $params
+ * @return bool
+ */
+ public function setGoodsRankConfig($params)
+ {
+ $value = [
+// "rank_name" => $params[ 'rank_name' ], // 排行榜名称
+ "rank_images" => $params[ 'rank_images' ], // 广告图
+// 'rank_remark' => $params[ 'rank_remark' ], // 备注
+ "no_color" => $params[ 'no_color' ], // 常规颜色
+ "select_color" => $params[ 'select_color' ], // 选中文字颜色
+ "select_bg_color_start" => $params[ 'select_bg_color_start' ], // 选中背景色(开始)
+ "select_bg_color_end" => $params[ 'select_bg_color_end' ], // 选中背景色(结束)
+ ];
+
+ $this->core_config_service->setConfig('GOODS_RANK_CONFIG', $value);
+ return true;
+ }
+
+ /**
+ * 获取商品排行榜配置
+ * @return array
+ */
+ public function getGoodsRankConfig()
+ {
+ $res = ( new CoreConfigService() )->getConfig('GOODS_RANK_CONFIG');
+ $data = [
+// 'rank_name' => $res[ 'value' ][ 'rank_name' ] ?? '排名依据销量与销售额计算 定时更新',
+ 'rank_images' => $res[ 'value' ][ 'rank_images' ] ?? 'addon/shop/rank/rank_images.jpg',
+// 'rank_remark' => $res[ 'value' ][ 'rank_remark' ] ?? '精选商城内销量最高的商品,涵盖多个品类,为用户提供当前最受欢迎的商品参考。'. PHP_EOL.'本榜单以销量为主要排名依据,保证推荐商品的高质量和高热度。',
+ 'no_color' => $res[ 'value' ][ 'no_color' ] ?? '#FFFCF5',
+ 'select_color' => $res[ 'value' ][ 'select_color' ] ?? '#FF4142',
+ 'select_bg_color_start' => $res[ 'value' ][ 'select_bg_color_start' ] ?? '#FFFFFF',
+ 'select_bg_color_end' => $res[ 'value' ][ 'select_bg_color_end' ] ?? '#FFEBD7',
+ ];
+ return $data;
+ }
+
+}
diff --git a/niucloud/addon/shop/app/service/core/goods/CoreGoodsSaleNumService.php b/niucloud/addon/shop/app/service/core/goods/CoreGoodsSaleNumService.php
new file mode 100644
index 000000000..e851ef361
--- /dev/null
+++ b/niucloud/addon/shop/app/service/core/goods/CoreGoodsSaleNumService.php
@@ -0,0 +1,68 @@
+model = new Goods();
+ }
+
+ /**
+ * 增加
+ * @param $data
+ * @return void
+ */
+ public function inc($data)
+ {
+ $this->model->where([ [ 'goods_id', '=', $data[ 'goods_id' ] ] ])->inc('sale_num', $data[ 'num' ])->update();
+ ( new GoodsSku() )->where([ [ 'sku_id', '=', $data[ 'sku_id' ] ] ])->inc('sale_num', $data[ 'num' ])->update();
+ return true;
+ }
+
+ /**
+ * 减少
+ * @param $data
+ * @return void
+ */
+ public function dec($data)
+ {
+ $this->model->where([ [ 'goods_id', '=', $data[ 'goods_id' ] ] ])->dec('sale_num', $data[ 'num' ])->update();
+ ( new GoodsSku() )->where([ [ 'sku_id', '=', $data[ 'sku_id' ] ] ])->dec('sale_num', $data[ 'num' ])->update();
+ return true;
+ }
+
+ public function batchUpdateSaleNum($data)
+ {
+ if (!isset($data['goods']) || !isset($data['sku'])) {
+ return false;
+ }
+ try {
+ $this->model->saveAll($data['goods']);
+ (new GoodsSku())->saveAll($data['sku']);
+ }catch (\Exception $e){
+ throw new \Exception($e->getMessage());
+ }
+ }
+
+
+}
diff --git a/niucloud/addon/shop/app/service/core/goods/CoreGoodsStatService.php b/niucloud/addon/shop/app/service/core/goods/CoreGoodsStatService.php
new file mode 100644
index 000000000..1a547797b
--- /dev/null
+++ b/niucloud/addon/shop/app/service/core/goods/CoreGoodsStatService.php
@@ -0,0 +1,172 @@
+ date('Y-m-d', time()),
+ 'date_time' => strtotime(date('Y-m-d', time())),
+ 'goods_id' => $data[ 'goods_id' ],
+ ];
+ if ($stat_data['goods_id'] <= 0) return false;
+
+ $stat = ( new Stat() )->where($stat_data)->findOrEmpty();
+ if ($stat->isEmpty()) {
+ $stat->allowField(array_merge(array_keys($stat_data), self::STAT_FIELD))->save(array_merge($stat_data, $data));
+ } else {
+ unset($data[ 'goods_id' ]);
+ foreach ($data as $key => $value) {
+ $stat->$key = Db::raw("{$key} + {$value}");
+ }
+ $stat->allowField(self::STAT_FIELD)->save();
+ }
+ return true;
+ }
+
+ /**
+ * 累减统计数据
+ * @param $data
+ * @return true
+ */
+ public static function decStat($data = [])
+ {
+ $time = strtotime($data['time']);
+ // 更新天统计
+ $stat_data = [
+ 'date' => date('Y-m-d', $time),
+ 'date_time' => strtotime(date('Y-m-d', $time)),
+ 'goods_id' => $data[ 'goods_id' ],
+ ];
+
+ $stat = ( new Stat() )->where($stat_data)->findOrEmpty();
+ if (!$stat->isEmpty()) {
+ unset($data[ 'goods_id' ]);
+ unset($data[ 'time' ]);
+ foreach ($data as $key => $value) {
+ $stat->$key = Db::raw("CASE WHEN {$key} - {$value} >= 0 THEN {$key} - {$value} ELSE 0 END");
+ }
+ $stat->allowField(self::STAT_FIELD)->save();
+ }
+ return true;
+ }
+
+ /**
+ * 获取时间区间内天统计数据
+ * @param int $goods_id
+ * @param string $start_date
+ * @param string $end_date
+ * @return array
+ */
+ public function getStatData(int $goods_id, string $start_date, string $end_date)
+ {
+ $start_date = strtotime($start_date);
+ $end_date = strtotime($end_date);
+
+ $field = implode(',', array_merge(self::STAT_FIELD, [ 'date' ]));
+ $stat_data = ( new Stat() )->where([ [ 'goods_id', '=', $goods_id ], [ 'date_time', '>=', $start_date ], [ 'date_time', '<=', $end_date ] ])->field($field)->select()->toArray();
+ $stat_data = !empty($stat_data) ? array_column($stat_data, null, 'date') : [];
+
+ $data = [];
+ $day = ceil(( $end_date - $start_date ) / 86400);
+ foreach (self::STAT_FIELD as $field) {
+ $value = [];
+ $time = [];
+ for ($i = 0; $i < $day; $i++) {
+ $date = date('Y-m-d', $start_date + $i * 86400);
+ $time[] = $date;
+
+ $value[] = isset($stat_data[ $date ]) && isset($stat_data[ $date ][ $field ]) ? $stat_data[ $date ][ $field ] : 0;
+ }
+ $data[ $field ] = $value;
+ $data[ 'time' ] = $time;
+ }
+
+ return $data;
+ }
+
+ /**
+ * 根据订单统计商品的支付数量及支付金额
+ * @param $order_data
+ * @return bool
+ */
+ public function saveGoodsPayNumAndMoneyByOrderId($order_data)
+ {
+ $order_goods_model = new OrderGoods();
+ $order_goods_data = $order_goods_model->where([ 'order_id' => $order_data[ 'order_id' ] ])->select()->toArray();
+ if (!empty($order_goods_data)) {
+ foreach ($order_goods_data as $goods) {
+ CoreGoodsStatService::addStat([ 'goods_id' => $goods[ 'goods_id' ], 'pay_num' => $goods[ 'num' ], 'pay_money' => $goods[ 'order_goods_money' ] ]);
+
+ ( new Goods() )->where([ [ 'goods_id', '=', $goods[ 'goods_id' ] ] ])->inc('pay_num', $goods[ 'num' ])->update(); // 更新支付件数
+ ( new Goods() )->where([ [ 'goods_id', '=', $goods[ 'goods_id' ] ] ])->inc('pay_money', $goods[ 'order_goods_money' ])->update(); // 更新支付金额
+ }
+ }
+ return true;
+ }
+
+ /**
+ * 根据退款订单统计商品的退款件数、金额
+ * @param $refund_data
+ * @return bool
+ */
+ public function saveGoodsRefundNumAndMoneyByOrderId($refund_data)
+ {
+ $order_goods_model = new OrderGoods();
+ $order_goods_info = $order_goods_model->where([ 'order_goods_id' => $refund_data[ 'order_goods_id' ] ])->findOrEmpty();
+ if (!$order_goods_info->isEmpty()) {
+ CoreGoodsStatService::addStat([ 'goods_id' => $order_goods_info[ 'goods_id' ], 'refund_num' => $order_goods_info[ 'num' ], 'refund_money' => $refund_data[ 'money' ] ]);
+
+ ( new Goods() )->where([ [ 'goods_id', '=', $order_goods_info[ 'goods_id' ] ] ])->inc('refund_num', $order_goods_info[ 'num' ])->update(); // 更新退款件数
+ ( new Goods() )->where([ [ 'goods_id', '=', $order_goods_info[ 'goods_id' ] ] ])->inc('refund_money', $refund_data[ 'money' ])->update(); // 更新退款金额
+ }
+
+ return true;
+ }
+
+}
diff --git a/niucloud/addon/shop/app/service/core/goods/CoreGoodsStockService.php b/niucloud/addon/shop/app/service/core/goods/CoreGoodsStockService.php
new file mode 100644
index 000000000..b5a31e92b
--- /dev/null
+++ b/niucloud/addon/shop/app/service/core/goods/CoreGoodsStockService.php
@@ -0,0 +1,68 @@
+model = new Goods();
+ }
+
+ /**
+ * 增加库存
+ * @param $data
+ * @return void
+ */
+ public function inc($data)
+ {
+ $this->model->where([['goods_id', '=', $data['goods_id']]])->inc('stock', $data['num'])->update();
+ (new GoodsSku())->where([['sku_id', '=', $data['sku_id']]])->inc('stock', $data['num'])->update();
+ return true;
+ }
+
+ public function batchUpdateStock($data)
+ {
+ if (!isset($data['goods']) || !isset($data['sku'])) {
+ return false;
+ }
+ try {
+ $this->model->saveAll($data['goods']);
+ (new GoodsSku())->saveAll($data['sku']);
+ }catch (\Exception $e){
+ throw new \Exception($e->getMessage());
+ }
+ }
+
+ /**
+ * 减少库存
+ * @param $data
+ * @return void
+ */
+ public function dec($data)
+ {
+ $this->model->where([['goods_id', '=', $data['goods_id']]])->dec('stock', $data['num'])->update();
+ (new GoodsSku())->where([['sku_id', '=', $data['sku_id']]])->dec('stock', $data['num'])->update();
+ return true;
+ }
+
+}
diff --git a/niucloud/addon/shop/app/service/core/marketing/CoreActiveService.php b/niucloud/addon/shop/app/service/core/marketing/CoreActiveService.php
new file mode 100644
index 000000000..53b7d453a
--- /dev/null
+++ b/niucloud/addon/shop/app/service/core/marketing/CoreActiveService.php
@@ -0,0 +1,225 @@
+model = new Active();
+ }
+
+ /**
+ * 添加活动
+ * @param array $data
+ * @return mixed
+ */
+ public function add(array $data)
+ {
+ $active_goods_data = $data['active_goods'] ?? [];
+ if(empty($active_goods_data)) throw new AdminException('ACTIVE_GOODS_NOT_EMPTY');
+
+ if(!empty($data['end_time']) && $data['end_time'] < time()) throw new AdminException('END_TIME_NOT_LESS_CURRENT_TIME');
+
+ Db::startTrans();
+ try {
+ $create_data = [
+ 'active_name'=> $data['active_name'] ?? '',
+ 'active_desc'=> $data['active_desc'] ?? '',
+ 'active_type' => $data['active_type'],
+ 'active_goods_type' => $data['active_goods_type'],
+ 'active_goods_info' => $data['active_goods_info'] ?? '',
+ 'active_class' => $data['active_class'],
+ 'active_class_category' => $data['active_class_category'] ?? '',
+ 'active_value' => $data['active_value'] ?? '',
+ 'relate_member' => $data['relate_member'] ?? '',
+ 'create_time' => time(),
+ 'update_time' => 0,
+ 'start_time' => $data['start_time'] ?? 0,
+ 'end_time' => $data['end_time'] ?? 0,
+ 'active_status' => $data['active_status'],
+ ];
+
+ $res = $this->model->create($create_data);
+ $active_goods = [];
+ foreach ($active_goods_data as $k => $v){
+ $active_goods[] = [
+ 'active_id' => $res->active_id,
+ 'goods_id' => $v['goods_id'],
+ 'sku_id' => !empty($v['sku_id']) ? $v['sku_id'] : 0,
+ 'active_goods_value' => $v['active_goods_value'] ?? [],
+ 'active_goods_status' => $create_data['active_status'],
+ 'active_goods_price' => $v['active_goods_price'] ?? 0.00,
+ 'active_goods_type' => $v['active_goods_type'],
+ 'active_class' => $v['active_class'],
+ 'active_goods_label' => $v['active_goods_label'] ?? '',
+ 'active_goods_category' => $v['active_goods_category'] ?? '',
+ 'active_goods_point' => $v['active_goods_point'] ?? 0.00,
+ 'active_goods_stock' => $v['active_goods_stock'] ?? 0,
+ ];
+ }
+ $active_goods_model = new ActiveGoods();
+ $active_goods_model->saveAll($active_goods);
+
+ Db::commit();
+
+ if(!empty($data['start_time']) && $create_data['start_time'] <= time()) $this->start($res->active_id);
+ if(!empty($data['end_time']) && $create_data['end_time'] <= time()) $this->end($res->active_id);
+ return $res->active_id;
+ } catch (\Exception $e) {
+ Db::rollback();
+ throw new CommonException($e->getMessage());
+ }
+ }
+
+ /**
+ * 编辑活动
+ * @param int $id
+ * @param array $data
+ * @return bool
+ */
+ public function edit(int $active_id, array $data)
+ {
+ $info = $this->model->where([ ['active_id', '=', $active_id] ])->findOrEmpty();
+ if ($info->isEmpty()) throw new AdminException('ACTIVE_NOT_FOUND');
+ if ($info->active_class != ActiveDict::NEWCOMER_DISCOUNT && ($info->active_status == ActiveDict::CLOSE || $info->active_status == ActiveDict::END)) throw new AdminException('ACTIVE_NOT_EDIT');
+
+ //结束时间不能小于当前时间
+ if(!empty($data['end_time']) && $data['end_time'] < time()) throw new AdminException('END_TIME_NOT_LESS_CURRENT_TIME');
+ $active_goods_data = $data['active_goods'] ?? [];
+ if($data['active_class'] != ActiveDict::NEWCOMER_DISCOUNT && empty($active_goods_data)) throw new AdminException('ACTIVE_GOODS_NOT_EMPTY');
+ $active_goods_model = new ActiveGoods();
+ Db::startTrans();
+ try {
+
+ $active_goods_list = $active_goods_model->where([ ['active_id', '=', $active_id] ])->select()->toArray();
+ $active_goods_list = array_column($active_goods_list, null, 'goods_id');
+
+ $save_data = [
+ 'active_name'=> $data['active_name'] ?? '',
+ 'active_desc'=> $data['active_desc'] ?? '',
+ 'active_type' => $data['active_type'],
+ 'active_goods_type' => $data['active_goods_type'],
+ 'active_goods_info' => $data['active_goods_info'] ?? '',
+ 'active_class' => $data['active_class'],
+ 'active_class_category' => $data['active_class_category'] ?? '',
+ 'active_value' => $data['active_value'] ?? '',
+ 'relate_member' => $data['relate_member'] ?? '',
+ 'update_time' => time(),
+ 'start_time' => $data['start_time'] ?? 0,
+ 'end_time' => $data['end_time'] ?? 0,
+ 'active_status' => $data['active_status'],
+ ];
+
+ $this->model->where([ ['active_id', '=', $active_id] ])->update($save_data);
+
+ $active_goods = [];
+ foreach ($active_goods_data as $k => $v){
+ $active_goods[] = [
+ 'active_id' => $active_id,
+ 'goods_id' => $v['goods_id'],
+ 'sku_id' => !empty($v['sku_id']) ? $v['sku_id'] : 0,
+ 'active_goods_value' => $v['active_goods_value'] ?? [],
+ 'active_goods_status' => $save_data['active_status'],
+ 'active_goods_price' => $v['active_goods_price'] ?? 0.00,
+ 'active_goods_type' => $v['active_goods_type'],
+ 'active_class' => $v['active_class'],
+ 'active_goods_label' => $v['active_goods_label'] ?? '',
+ 'active_goods_category' => $v['active_goods_category'] ?? '',
+ 'active_goods_point' => $v['active_goods_point'] ?? 0.00,
+ 'active_goods_stock' => $v['active_goods_stock'] ?? 0,
+ 'active_goods_order_money' => $active_goods_list[$v['goods_id']]['active_goods_order_money'] ?? 0,
+ 'active_goods_order_num' => $active_goods_list[$v['goods_id']]['active_goods_order_num'] ?? 0,
+ 'active_goods_member_num' => $active_goods_list[$v['goods_id']]['active_goods_member_num'] ?? 0,
+ 'active_goods_success_num' => $active_goods_list[$v['goods_id']]['active_goods_success_num'] ?? 0,
+ ];
+ }
+
+ $active_goods_model->where([ ['active_id', '=', $active_id] ])->delete();
+ $active_goods_model->saveAll($active_goods);
+
+ Db::commit();
+ if(!empty($save_data['start_time']) && $save_data['start_time'] <= time())$this->start($active_id);
+ if(!empty($save_data['end_time']) && $save_data['end_time'] <= time())$this->end($active_id);
+ event('ActiveSaveAfter', $data);
+ return true;
+ } catch (\Exception $e) {
+ Db::rollback();
+ throw new CommonException($e->getMessage());
+ }
+ }
+
+ /**
+ * 删除活动
+ * @param int $active_id
+ * @return bool
+ */
+ public function del(int $active_id, $is_force=0)
+ {
+ $info = $this->model->where([ ['active_id', '=', $active_id] ])->findOrEmpty();
+ if ($info->isEmpty()) throw new AdminException('ACTIVE_NOT_FOUND');
+ if ($is_force==0 && $info->active_status == ActiveDict::ACTIVE) throw new AdminException('ACTIVE_NOT_DELETE');
+ $this->model->where([ [ 'active_id', '=', $active_id ] ])->delete();
+ (new ActiveGoods())->where([ [ 'active_id', '=', $active_id ] ])->delete();
+ return true;
+ }
+
+ /**
+ * 活动关闭
+ * @return void
+ */
+ public function close($active_id)
+ {
+ $this->model->where([ ['active_id', '=', $active_id], ['active_status', '=', ActiveDict::ACTIVE] ])->update([ 'active_status' => ActiveDict::CLOSE ]);
+ (new ActiveGoods())->where([ ['active_id', '=', $active_id]])->update([ 'active_goods_status' => ActiveDict::CLOSE ]);
+ return true;
+ }
+
+ /**
+ * 活动开启
+ * @return void
+ */
+ public function start($active_id)
+ {
+ $this->model->where([ ['active_id', '=', $active_id], ['active_status', '=', ActiveDict::NOT_ACTIVE], ['start_time', '<=', time()] ])->update([ 'active_status' => ActiveDict::ACTIVE ]);
+ (new ActiveGoods())->where([ ['active_id', '=', $active_id]])->update([ 'active_goods_status' => ActiveDict::ACTIVE ]);
+ ActiveStartAfter::dispatch(['active_id' => $active_id]);
+ return true;
+ }
+
+ /**
+ * 活动结束
+ * @return void
+ */
+ public function end($active_id)
+ {
+ $this->model->where([ ['active_id', '=', $active_id], ['active_status', '=', ActiveDict::ACTIVE], ['end_time', '<=', time()] ])->update([ 'active_status' => ActiveDict::END ]);
+ (new ActiveGoods())->where([ ['active_id', '=', $active_id]])->update([ 'active_goods_status' => ActiveDict::END ]);
+ ActiveEndAfter::dispatch(['active_id' => $active_id]);
+ return true;
+ }
+
+}
diff --git a/niucloud/addon/shop/app/service/core/marketing/CoreCouponService.php b/niucloud/addon/shop/app/service/core/marketing/CoreCouponService.php
new file mode 100644
index 000000000..ef712b968
--- /dev/null
+++ b/niucloud/addon/shop/app/service/core/marketing/CoreCouponService.php
@@ -0,0 +1,66 @@
+model = new Coupon();
+ }
+
+ /**
+ * 优惠券状态开启
+ * @param $ids
+ * @return true
+ */
+ public function couponNormal($ids)
+ {
+ $where = [
+ [ 'id', 'in', $ids ],
+ [ 'status', '=', CouponDict::WAIT_START ]
+ ];
+ $data = [
+ 'status' => CouponDict::NORMAL
+ ];
+ $this->model->where($where)->update($data);
+ return true;
+ }
+
+ /**
+ * 优惠券状态过期
+ * @param $ids
+ * @return true
+ */
+ public function couponExpire($ids)
+ {
+ $where = [
+ [ 'id', 'in', $ids ],
+ [ 'status', '=', CouponDict::NORMAL ]
+ ];
+ $data = [
+ 'status' => CouponDict::EXPIRE
+ ];
+ $this->model->where($where)->update($data);
+ return true;
+ }
+
+}
diff --git a/niucloud/addon/shop/app/service/core/marketing/CoreManjianService.php b/niucloud/addon/shop/app/service/core/marketing/CoreManjianService.php
new file mode 100644
index 000000000..c472a2adf
--- /dev/null
+++ b/niucloud/addon/shop/app/service/core/marketing/CoreManjianService.php
@@ -0,0 +1,1465 @@
+model = new Manjian();
+ }
+
+ /**
+ * 满减活动优惠计算
+ * @param $order
+ * @return void
+ */
+ public function calculate(&$order)
+ {
+ $manjian_discount_money = 0;
+
+ //查询满减活动
+ $manjian_list = $this->model->field('manjian_id,manjian_name,condition_type,goods_type,join_member_type,rule_type,rule_json,level_ids,label_ids')->where([
+ ['status', '=', ManjianDict::ACTIVE],
+ ['start_time', '<=', time()],
+ ['end_time', '>', time()]
+ ])->orderRaw("CASE WHEN goods_type = 'selected_goods' THEN 0 WHEN goods_type = 'selected_goods_not' THEN 1 ELSE 2 END ASC")->select()->toArray();
+ $member_info = (new Member())->field('member_level,member_label')->where([
+ ['member_id', '=', $order->member_id]
+ ])->findOrEmpty()->toArray();
+
+ if (!empty($manjian_list) && !empty($member_info)) {
+ $gift_goods_all = [];//合并所有赠品计算剩余库存
+ foreach ($manjian_list as &$value) {
+ //判断会员是否有参与资格
+ $can_join = 0;
+ $join_member_type = $value['join_member_type'];
+ $level_ids = $value['level_ids'];
+ $label_ids = $value['label_ids'];
+ if ($join_member_type == ManjianDict::ALL_MEMBER) {//所有会员参与
+ $can_join = 1;
+ } elseif ($join_member_type == ManjianDict::SELECTED_MEMBER_LEVEL) {//指定会员等级
+ if (in_array($member_info['member_level'], $level_ids)) {
+ $can_join = 1;
+ }
+ } elseif ($join_member_type == ManjianDict::SELECTED_MEMBER_LABEL) {//指定会员标签
+ if (!empty($member_info['member_label']) && !empty(array_intersect($member_info['member_label'], $label_ids))) {
+ $can_join = 1;
+ }
+ }
+ if ($can_join == 0) continue;//不参与
+
+ $condition_type = $value['condition_type'];
+ $condition_match_value = 0;
+ $condition_match_money = 0;
+ $match_sku_ids = [];
+ $match_order_goods_money = 0;
+ foreach ($order->goods_data as $v) {
+ $manjian_goods_count = (new ManjianGoods())->where([
+ ['goods_id', '=', $v['goods_id']],
+ ['sku_id', '=', $v['sku_id']],
+ ['manjian_id', '=', $value['manjian_id']],
+ ['status', '=', ManjianDict::ACTIVE]
+ ])->count();
+ if ($value['goods_type'] == ManjianDict::ALL_GOODS) {//全部商品参与
+ if ($condition_type == ManjianDict::OVER_N_YUAN) {//满N元
+ $condition_match_value += $v['price'] * $v['num'];
+ } else {//满N件
+ $condition_match_value += $v['num'];
+ }
+ $condition_match_money += $v['price'] * $v['num'];
+ $match_sku_ids[] = $v['sku_id'];
+ $match_order_goods_money += ($v['goods_money'] - $v['discount_money']);
+ } elseif ($value['goods_type'] == ManjianDict::SELECTED_GOODS) {//指定商品参与
+ if ($manjian_goods_count > 0) {
+ if ($condition_type == ManjianDict::OVER_N_YUAN) {//满N元
+ $condition_match_value += $v['price'] * $v['num'];
+ } else {//满N件
+ $condition_match_value += $v['num'];
+ }
+ $condition_match_money += $v['price'] * $v['num'];
+ $match_sku_ids[] = $v['sku_id'];
+ $match_order_goods_money += ($v['goods_money'] - $v['discount_money']);
+ }
+ } elseif ($value['goods_type'] == ManjianDict::SELECTED_GOODS_NOT) {//指定商品不参与
+ if ($manjian_goods_count == 0) {
+ if ($condition_type == ManjianDict::OVER_N_YUAN) {//满N元
+ $condition_match_value += $v['price'] * $v['num'];
+ } else {//满N件
+ $condition_match_value += $v['num'];
+ }
+ $condition_match_money += $v['price'] * $v['num'];
+ $match_sku_ids[] = $v['sku_id'];
+ $match_order_goods_money += ($v['goods_money'] - $v['discount_money']);
+ }
+ }
+ }
+
+ $discount_money = 0;//优惠金额
+ $is_free_shipping = 0;//是否免邮
+ $gift = [];//赠品
+ $level = -1;//优惠层级
+
+ $rule_type = $value['rule_type'];
+ $rule_json = $value['rule_json'];
+ foreach ($rule_json as $key => $rule) {
+ if ($condition_match_value >= $rule['limit']) {
+ if ($rule_type == ManjianDict::LADDER) {//阶梯优惠
+ //满减优惠券
+ $discount_type = $rule['discount_type'];
+ if ($discount_type == 1) {//减
+ $discount_money = $rule['discount_money'] ?? 0;
+ } else {//折
+ $discount_money = $order->moneyFormat($condition_match_money * (1 - ($rule['discount_money'] ?? 0) / 10));
+ }
+
+ if (!$rule['is_discount']) {
+ $rule_json[$key]['discount_money'] = 0;
+ $discount_money = 0;
+ }
+ //积分
+ $gift['point'] = $rule['point'] ?? 0;
+
+ if (!$rule['is_give_point']) {
+ $rule_json[$key]['point'] = 0;
+ $gift['point'] = 0;
+ }
+ //余额
+ $gift['balance'] = $rule['balance'] ?? 0;
+
+ if (!$rule['is_give_balance']) {
+ $rule_json[$key]['balance'] = 0;
+ $gift['balance'] = 0;
+ }
+ //优惠券
+ $gift_coupon = $rule['coupon'] ?? [];
+ if ($gift_coupon) {
+ foreach ($gift_coupon as $coupon_key => &$coupon) {
+ $coupon_info = (new Coupon())->field('price,min_condition_money')->where([
+ ['id', '=', $coupon['coupon_id']],
+ ['status', '=', CouponDict::NORMAL],
+ ])->findOrEmpty()->toArray();
+ if (!empty($coupon_info)) {
+ if ($coupon_info['min_condition_money'] == '0.00') {
+ $coupon_name = $coupon_info['price'] . "元无门槛券";
+ } else {
+ $coupon_name = "满" . $coupon_info['min_condition_money'] . "元减" . $coupon_info['price'] . "元券";
+ }
+ $coupon['coupon_name'] = $coupon_name;
+ } else {
+ unset($gift_coupon[$coupon_key]);
+ }
+ }
+ $gift_coupon = array_values($gift_coupon);
+ $rule_json[$key]['coupon'] = $gift_coupon;
+ }
+ $gift['coupon'] = $gift_coupon;
+
+ if (!$rule['is_give_coupon']) {
+ $rule_json[$key]['coupon'] = [];
+ $gift['coupon'] = [];
+ }
+ //赠品
+ $gift_goods = $rule['goods'] ?? [];
+ if ($gift_goods) {
+ foreach ($gift_goods as $goods_key => &$goods) {
+ $sku_info = (new GoodsSku())->field('goods_id,sku_name,sku_image,price,stock')->where([
+ ['goods_id', '=', $goods['goods_id']],
+ ['sku_id', '=', $goods['sku_id']],
+ ['stock', '>', 0],
+ ])->with(['goods'])->findOrEmpty()->toArray();
+ if (!empty($sku_info) && !empty($sku_info['goods']) && $sku_info['goods']['status'] == 1) {
+ $goods['goods_name'] = $sku_info['goods']['goods_name'];
+ $goods['sku_name'] = $sku_info['sku_name'];
+ $goods['sku_image'] = $sku_info['sku_image'];
+ $goods['price'] = $sku_info['price'];
+
+ if (empty($gift_goods_all)) {
+ // 库存小于赠送数量时,取剩余库存
+ $num = $sku_info['stock'] >= $goods['num'] ? $goods['num'] : $sku_info['stock'];
+ $goods['num'] = $num;
+ } else {
+ // 计算剩余库存
+ $leave_num = $sku_info['stock'];
+ foreach ($gift_goods_all as $gift_goods_item) {
+ if ($gift_goods_item['goods_id'] == $goods['goods_id'] && $gift_goods_item['sku_id'] == $goods['sku_id']) {
+ if ($leave_num - $gift_goods_item['num'] >= 0) {
+ $leave_num = $leave_num - $gift_goods_item['num'];
+ } else {
+ $leave_num = 0;
+ }
+ }
+ }
+ $goods['num'] = $leave_num >= $goods['num'] ? $goods['num'] : $leave_num;
+ }
+
+ if ($goods['num'] == 0) {
+ unset($gift_goods[$goods_key]);
+ }
+
+ } else {
+ unset($gift_goods[$goods_key]);
+ }
+ }
+ $gift_goods = array_values($gift_goods);
+ $gift_goods_all = array_merge($gift_goods_all, $gift_goods);
+ $rule_json[$key]['goods'] = $gift_goods;
+ }
+ $gift['goods'] = $gift_goods;
+
+ if (!$rule['is_give_goods']) {
+ $rule_json[$key]['goods'] = [];
+ $gift['goods'] = [];
+ }
+ } else {//循环优惠
+ $cycle_num = intdiv($condition_match_value, $rule['limit']);
+ $rule_json[$key]['limit'] = $rule['limit'] * $cycle_num;
+ if ($rule['is_discount']) {
+ if ($rule['limit'] == 0) {
+ $discount_money = 0;
+ } else {
+ $discount_money = $order->moneyFormat($cycle_num * ($rule['discount_money'] ?? 0));
+ }
+ $rule_json[$key]['discount_money'] = $discount_money;
+ }
+ if ($rule['is_give_point']) {
+ $rule_json[$key]['point'] = ($rule['point'] ?? 0) * $cycle_num;
+ $gift['point'] = ($rule['point'] ?? 0) * $cycle_num;
+ }
+ if ($rule['is_give_balance']) {
+ $rule_json[$key]['balance'] = ($rule['balance'] ?? 0) * $cycle_num;
+ $gift['balance'] = ($rule['balance'] ?? 0) * $cycle_num;
+ }
+ if ($rule['is_give_coupon']) {
+ $gift_coupon = $rule['coupon'] ?? [];
+ if ($gift_coupon) {
+ foreach ($gift_coupon as $coupon_key => &$coupon) {
+ $coupon['num'] = intval($coupon['num']) * $cycle_num;
+ $coupon_info = (new Coupon())->field('price,min_condition_money')->where([
+ ['id', '=', $coupon['coupon_id']],
+ ['status', '=', CouponDict::NORMAL],
+ ])->findOrEmpty()->toArray();
+ if (!empty($coupon_info)) {
+ if ($coupon_info['min_condition_money'] == '0.00') {
+ $coupon_name = $coupon_info['price'] . "元无门槛券";
+ } else {
+ $coupon_name = "满" . $coupon_info['min_condition_money'] . "元减" . $coupon_info['price'] . "元券";
+ }
+ $coupon['coupon_name'] = $coupon_name;
+ } else {
+ unset($gift_coupon[$coupon_key]);
+ }
+ }
+ $gift_coupon = array_values($gift_coupon);
+ $rule_json[$key]['coupon'] = $gift_coupon;
+ }
+ $gift['coupon'] = $gift_coupon;
+ }
+ if ($rule['is_give_goods']) {
+ $gift_goods = $rule['goods'] ?? [];
+ if ($gift_goods) {
+ foreach ($gift_goods as $goods_key => &$goods) {
+ $goods['num'] = intval($goods['num']) * $cycle_num;
+ $sku_info = (new GoodsSku())->field('goods_id,sku_name,sku_image,price,stock')->where([
+ ['goods_id', '=', $goods['goods_id']],
+ ['sku_id', '=', $goods['sku_id']],
+ ['stock', '>', 0],
+ ])->with(['goods'])->findOrEmpty()->toArray();
+ if (!empty($sku_info) && !empty($sku_info['goods']) && $sku_info['goods']['status'] == 1) {
+ $goods['goods_name'] = $sku_info['goods']['goods_name'];
+ $goods['sku_name'] = $sku_info['sku_name'];
+ $goods['sku_image'] = $sku_info['sku_image'];
+ $goods['price'] = $sku_info['price'];
+
+ if (empty($gift_goods_all)) {
+ // 库存小于赠送数量时,取剩余库存
+ $num = $sku_info['stock'] >= $goods['num'] ? $goods['num'] : $sku_info['stock'];
+ $goods['num'] = $num;
+ } else {
+ // 计算剩余库存
+ $leave_num = $sku_info['stock'];
+ foreach ($gift_goods_all as $gift_goods_item) {
+ if ($gift_goods_item['goods_id'] == $goods['goods_id'] && $gift_goods_item['sku_id'] == $goods['sku_id']) {
+ if ($leave_num - $gift_goods_item['num'] >= 0) {
+ $leave_num = $leave_num - $gift_goods_item['num'];
+ } else {
+ $leave_num = 0;
+ }
+ }
+ }
+ $goods['num'] = $leave_num >= $goods['num'] ? $goods['num'] : $leave_num;
+ }
+
+ if ($goods['num'] == 0) {
+ unset($gift_goods[$goods_key]);
+ }
+
+ } else {
+ unset($gift_goods[$goods_key]);
+ }
+ }
+ $gift_goods = array_values($gift_goods);
+ $gift_goods_all = array_merge($gift_goods_all, $gift_goods);
+ $rule_json[$key]['goods'] = $gift_goods;
+ }
+ $gift['goods'] = $gift_goods;
+ }
+ }
+ $is_free_shipping = $rule['is_free_shipping'] ?? 0;
+ $level = $key;
+ }
+ }
+
+ if ($level >= 0) {
+ foreach ($match_sku_ids as $sku_id) {
+ $value['rule'] = $rule_json[$level];
+ if ($value['rule']['is_discount'] || $value['rule']['is_free_shipping'] || $value['rule']['is_give_point'] || $value['rule']['is_give_balance'] || !empty($value['rule']['coupon']) || !empty($value['rule']['goods'])) {
+ $order->goods_data[$sku_id]['manjian_info'][] = $value;
+ }
+ }
+ }
+
+ //填充满减商品优惠信息
+ $manjian_one_discount_money = 0;
+ if ($level >= 0) {
+ $this->manjianGoodsCalculate($order, $is_free_shipping, $discount_money, $match_sku_ids, $match_order_goods_money, $manjian_one_discount_money);
+ }
+ if ($manjian_one_discount_money > 0) {
+ $manjian_discount_money = bcadd($manjian_discount_money, $manjian_one_discount_money, 2);
+ $order->discount['manjian'][$value['manjian_id']][] = $order->discountFormat(
+ $match_sku_ids,
+ OrderDiscountDict::DISCOUNT,
+ count($match_sku_ids),
+ $manjian_one_discount_money,
+ 'manjian',
+ $value['manjian_id'],
+ '',
+ $value['manjian_name']
+ );
+ }
+ //获取满减活动商品赠品内容
+ if (!empty($gift)) {
+ $this->getGiftContent($order, $gift, $value['manjian_id'], $level, $match_sku_ids);
+ }
+ }
+
+ if ($manjian_discount_money > 0) {
+ $order->basic['discount_money'] = bcadd($order->basic['discount_money'], $manjian_discount_money, 2);
+ $order->basic['manjian_discount_money'] = $order->moneyFormat($manjian_discount_money);
+ }
+ }
+ }
+
+ /**
+ * 满减活动商品计算
+ * @param $order
+ * @param $is_free_shipping
+ * @param $discount_money
+ * @param $match_sku_ids
+ * @param $match_order_goods_money
+ * @param $manjian_one_discount_money
+ * @return void
+ */
+ public function manjianGoodsCalculate(&$order, $is_free_shipping, $discount_money, $match_sku_ids, $match_order_goods_money, &$manjian_one_discount_money)
+ {
+ if ($discount_money > $match_order_goods_money) {//优惠金额大于订单商品总金额,则优惠金额等于订单商品总金额
+ $discount_money = $match_order_goods_money;
+ }
+ $surplus_money = $discount_money;
+ $match_sku_ids = array_filter($match_sku_ids, function ($item) use ($order) {
+ return ($order->goods_data[$item]['goods_money'] - $order->goods_data[$item]['discount_money']) !== 0;
+ });
+ $match_count = count($match_sku_ids);
+ foreach ($match_sku_ids as $sku_key => $sku_id) {
+ $item_order_goods_money = $order->goods_data[$sku_id]['goods_money'] - $order->goods_data[$sku_id]['discount_money'];
+ if ($is_free_shipping) {
+ $order->goods_data[$sku_id]['goods']['is_free_shipping'] = 1;
+ $order->goods_data[$sku_id]['goods']['delivery_money'] = 0;
+ }
+
+ //订单项满减优惠计算
+ if ($sku_key == ($match_count - 1)) {
+ $item_discount_money = $surplus_money;
+ } else {
+ if ($match_order_goods_money == 0 || $discount_money == 0) {
+ $item_discount_money = 0;
+ } else {
+ $item_discount_money = $order->moneyFormat($item_order_goods_money / $match_order_goods_money * $discount_money);
+ if ($item_discount_money == 0) {
+ $item_discount_money = $item_order_goods_money;
+ }
+ if ($item_discount_money > $surplus_money) {
+ $item_discount_money = $surplus_money;
+ }
+ }
+ }
+ $order->goods_data[$sku_id]['discount_money'] = bcadd($order->goods_data[$sku_id]['discount_money'], $item_discount_money, 2);
+ $manjian_one_discount_money = bcadd($manjian_one_discount_money, $item_discount_money, 2);
+ $surplus_money = bcsub($surplus_money, $item_discount_money, 2);
+ }
+ }
+
+ /**
+ * 满减活动商品赠品内容
+ * @param $order
+ * @param $gift
+ * @param $manjian_id
+ * @param $level
+ * @param $sku_ids
+ * @return void
+ */
+ public function getGiftContent(&$order, $gift, $manjian_id, $level, $sku_ids)
+ {
+ foreach ($gift as $k => $v) {
+ switch ($k) {
+ case 'balance':
+ case 'point':
+ if ($v > 0) {
+ $gift[$k] = $v;
+ } else {
+ unset($gift[$k]);
+ }
+ break;
+ case 'coupon':
+ if (!empty($v) && is_array($v)) {
+ foreach ($v as $kk => $vv) {
+ $coupon_count = (new Coupon())->where([
+ ['id', '=', $vv['coupon_id']],
+ ['status', '=', CouponDict::NORMAL],
+ ])->count();
+ if ($coupon_count == 0) {
+ unset($v[$kk]);
+ }
+ }
+ $v = array_values($v);
+ if (!empty($v) && is_array($v)) {
+ $gift[$k] = $v;
+ } else {
+ unset($gift[$k]);
+ }
+ }
+ break;
+ case 'goods':
+ if (!empty($v) && is_array($v)) {
+ foreach ($v as $kk => $vv) {
+ $sku_info = (new GoodsSku())->field('sku_id, sku_name, sku_image, goods_id, price, stock, weight, volume,sku_id, sku_spec_format,member_price, sale_price')->where([
+ ['goods_id', '=', $vv['goods_id']],
+ ['sku_id', '=', $vv['sku_id']],
+ ['stock', '>', 0],
+ ])->with(['goods'])->findOrEmpty()->toArray();
+ if (!empty($sku_info) && !empty($sku_info['goods']) && $sku_info['goods']['status'] == 1) {
+ if (isset($order->gift_goods[$vv['sku_id']])) {
+ $order->gift_goods[$vv['sku_id']]['num'] += $vv['num'];
+ } else {
+ $sku_info['original_price'] = $sku_info['price'];
+ $sku_info['price'] = 0;
+ $sku_info['num'] = $vv['num'];
+ $sku_info['goods_money'] = 0;
+ $sku_info['discount_money'] = 0;
+ $sku_info['is_gift'] = 1;
+ $order->gift_goods[$vv['sku_id']] = $sku_info;
+ }
+ } else {
+ unset($v[$kk]);
+ }
+ }
+ $v = array_values($v);
+ if (!empty($v) && is_array($v)) {
+ $gift[$k] = $v;
+ } else {
+ unset($gift[$k]);
+ }
+ }
+ break;
+ }
+ }
+ if (!empty($gift)) {
+ $order->gift['manjian'][$manjian_id]['gift'] = $gift;
+ $order->gift['manjian'][$manjian_id]['level'] = $level;
+ $order->gift['manjian'][$manjian_id]['sku_ids'] = $sku_ids;
+ }
+ }
+
+ /**
+ * 添加满减活动赠送记录
+ * @param $data
+ * @return true
+ */
+ public function addGiveRecords($data)
+ {
+ $discount = $data['basic']['gift'];
+ $order_data = $data['order_data'];
+ if (!empty($discount) && !empty($discount['manjian'])) {
+ $manjian_give_records_model = new ManjianGiveRecords();
+ $core_manjian_stat_service = new CoreManjianStatService();
+ foreach ($discount['manjian'] as $manjian_id => $v) {
+ if (!empty($v['gift'])) {
+ $gift = $v['gift'];
+ $level = $v['level'];
+ $sku_ids = $v['sku_ids'];
+ $coupon_json = [];
+ if (!empty($gift['coupon'])) {
+ foreach ($gift['coupon'] as $vv) {
+ $coupon_json[] = [
+ 'coupon_id' => $vv['coupon_id'],
+ 'num' => $vv['num']
+ ];
+ }
+ }
+ $goods_json = [];
+ if (!empty($gift['goods'])) {
+ foreach ($gift['goods'] as $vv) {
+ $goods_json[] = [
+ 'goods_id' => $vv['goods_id'],
+ 'sku_id' => $vv['sku_id'],
+ 'num' => $vv['num']
+ ];
+ }
+ }
+ $give_data[] = [
+ 'member_id' => $order_data['member_id'],
+ 'order_id' => $order_data['order_id'],
+ 'manjian_id' => $manjian_id,
+ 'level' => $level,
+ 'point' => $gift['point'] ?? 0,
+ 'balance' => $gift['balance'] ?? 0,
+ 'coupon_json' => $coupon_json,
+ 'goods_json' => $goods_json,
+ 'sku_ids' => $sku_ids
+ ];
+ }
+ //会员满减活动参与次数
+ $join_count = $manjian_give_records_model->where([
+ ['member_id', '=', $order_data['member_id']],
+ ['manjian_id', '=', $manjian_id],
+ ])->count();
+ //满减活动数据统计
+ $stat_data = [
+ 'order_num' => 1,
+ 'member_num' => $join_count == 0 ? 1 : 0,
+ ];
+ $core_manjian_stat_service->stat($manjian_id, $stat_data);
+ }
+ if (!empty($give_data)) {
+ $manjian_give_records_model->saveAll($give_data);
+ }
+ }
+ return true;
+ }
+
+ /**
+ * 满减活动赠品发放
+ * @param $data
+ * @return true
+ */
+ public function giftGrant($data)
+ {
+ $give_records = (new ManjianGiveRecords())->where([
+ ['order_id', '=', $data['order_id']],
+ ['member_id', '=', $data['member_id']],
+ ])->field('member_id,manjian_id,point,balance,coupon_json,goods_json')->select()->toArray();
+ Log::write('满减送活动赠品发放:' . json_encode($give_records));
+ if (!empty($give_records)) {
+ $core_member_account = new CoreMemberAccountService();
+ $core_coupon_member_service = new CoreCouponMemberService();
+ $core_manjian_stat_service = new CoreManjianStatService();
+ foreach ($give_records as $v) {
+ //会员积分发放
+ if ($v['point'] > 0) {
+ $core_member_account->addLog($v['member_id'], MemberAccountTypeDict:: POINT, $v['point'], 'manjian_gift_give', '满减送活动赠送', $v['manjian_id']);
+ }
+ //会员余额发放
+ if ($v['balance'] > 0) {
+ $core_member_account->addLog($v['member_id'], MemberAccountTypeDict:: BALANCE, $v['balance'], 'manjian_gift_give', '满减送活动赠送', $v['manjian_id']);
+ }
+ if (!empty($v['coupon_json'])) {
+ $coupon_num = 0;
+ foreach ($v['coupon_json'] as $coupon) {
+ try {
+ $core_coupon_member_service->sendCoupon($v['member_id'], $coupon['coupon_id'], $coupon['num']);
+ $coupon_num += $coupon['num'];
+ } catch (CommonException $e) {
+ Log::write('满减赠送优惠券“' . $coupon['coupon_id'] . '”发放失败,错误原因:' . $e->getMessage() . $e->getFile() . $e->getLine());
+ }
+ }
+ }
+ if (!empty($v['goods_json'])) {
+ $nums = array_column($v['goods_json'], 'num');
+ $goods_num = array_sum($nums);
+ }
+
+ //满减活动数据统计
+ $stat_data = [
+ 'order_money' => $data['order_money'],
+ 'point' => $v['point'],
+ 'balance' => $v['balance'],
+ 'coupon_num' => $coupon_num ?? 0,
+ 'goods_num' => $goods_num ?? 0
+ ];
+ $core_manjian_stat_service->stat($v['manjian_id'], $stat_data);
+ }
+ }
+ return true;
+ }
+
+ /**
+ * 满减活动退款校验
+ * @return array
+ */
+ public function refundCheck($data)
+ {
+ $order_goods_model = new OrderGoods();
+ //查询订单是否全部退款
+ $order_goods_list = $order_goods_model->where([
+ ['order_id', '=', $data['order_id']],
+ ['member_id', '=', $data['member_id']],
+ ['status', '<>', OrderGoodsDict::REFUND_FINISH],
+ ['is_gift', '=', 0]
+ ])->column('order_goods_id,goods_id,sku_id,num,goods_money,extend', 'order_goods_id');
+
+ $give_records = (new ManjianGiveRecords())->where([
+ ['order_id', '=', $data['order_id']],
+ ['member_id', '=', $data['member_id']],
+ ])->field('manjian_id,level,point,balance,coupon_json,goods_json')->select()->toArray();
+
+ $refund_gift_list = [];
+ foreach ($give_records as $value) {
+ $manjian_info = $this->model->where([
+ ['manjian_id', '=', $value['manjian_id']]
+ ])->findOrEmpty()->toArray();
+ if (empty($manjian_info)) continue;
+
+ $condition_type = $manjian_info['condition_type'];
+ $condition_match_value = 0;
+
+ if (!empty($order_goods_list)) {
+ foreach ($order_goods_list as $v) {
+ $manjian_goods_count = (new ManjianGoods())->where([
+ ['goods_id', '=', $v['goods_id']],
+ ['sku_id', '=', $v['sku_id']],
+ ['manjian_id', '=', $value['manjian_id']],
+ ['status', '=', ManjianDict::ACTIVE]
+ ])->count();
+ if ($manjian_info['goods_type'] == ManjianDict::ALL_GOODS) {//全部商品参与
+ if ($condition_type == ManjianDict::OVER_N_YUAN) {//满N元
+ $condition_match_value += $v['goods_money'];
+ } else {//满N件
+ $condition_match_value += $v['num'];
+ }
+
+ } elseif ($manjian_info['goods_type'] == ManjianDict::SELECTED_GOODS) {//指定商品参与
+ if ($manjian_goods_count > 0) {
+ if ($condition_type == ManjianDict::OVER_N_YUAN) {//满N元
+ $condition_match_value += $v['goods_money'];
+ } else {//满N件
+ $condition_match_value += $v['num'];
+ }
+
+ }
+ } elseif ($manjian_info['goods_type'] == ManjianDict::SELECTED_GOODS_NOT) {//指定商品不参与
+ if ($manjian_goods_count == 0) {
+ if ($condition_type == ManjianDict::OVER_N_YUAN) {//满N元
+ $condition_match_value += $v['goods_money'];
+ } else {//满N件
+ $condition_match_value += $v['num'];
+ }
+ }
+ }
+ }
+ }
+
+ $gift = [];//赠品
+ $level = -1;//优惠层级
+ $rule_type = $manjian_info['rule_type'];
+ $rule_json = $manjian_info['rule_json'];
+ foreach ($rule_json as $key => $rule) {
+ if ($condition_match_value >= $rule['limit']) {
+ if ($rule_type == ManjianDict::LADDER) {//阶梯优惠
+ //积分
+ $gift['point'] = $rule['point'] ?? 0;
+
+ if (!$rule['is_give_point']) {
+ $gift['point'] = 0;
+ }
+ //余额
+ $gift['balance'] = $rule['balance'] ?? 0;
+
+ if (!$rule['is_give_balance']) {
+ $gift['balance'] = 0;
+ }
+ //优惠券
+ $gift['coupon'] = $rule['coupon'] ?? [];
+
+ if (!$rule['is_give_coupon']) {
+ $gift['coupon'] = [];
+ }
+ //赠品
+ $gift['goods'] = $rule['goods'] ?? [];
+
+ if (!$rule['is_give_goods']) {
+ $gift['goods'] = [];
+ }
+ } else {//循环优惠
+ $cycle_num = intdiv($condition_match_value, $rule['limit']);
+ if ($rule['is_give_point']) $gift['point'] = ($rule['point'] ?? 0) * $cycle_num;
+ if ($rule['is_give_balance']) $gift['balance'] = ($rule['balance'] ?? 0) * $cycle_num;
+ if ($rule['is_give_coupon']) {
+ $gift_coupon = $rule['coupon'] ?? [];
+ if ($gift_coupon) {
+ foreach ($gift_coupon as &$coupon) {
+ $coupon['num'] = intval($coupon['num']) * $cycle_num;
+ }
+ }
+ $gift['coupon'] = $gift_coupon;
+ }
+ if ($rule['is_give_goods']) {
+ $gift_goods = $rule['goods'] ?? [];
+ if ($gift_goods) {
+ foreach ($gift_goods as &$goods) {
+ $goods['num'] = intval($goods['num']) * $cycle_num;
+ }
+ }
+ $gift['goods'] = $gift_goods;
+ }
+ }
+ $level = $key;
+ }
+ }
+
+ if ($level < $value['level'] || empty($order_goods_list)) {//优惠层级降级或订单全部退款,退还全部赠品
+ if ($value['point'] > 0) {
+ $refund_gift_list[$value['manjian_id']]['point'] = $value['point'];
+ }
+ if ($value['balance'] > 0) {
+ $refund_gift_list[$value['manjian_id']]['balance'] = $value['balance'];
+ }
+ if (!empty($value['coupon_json'])) {
+ $refund_gift_list[$value['manjian_id']]['coupon'] = $value['coupon_json'];
+ }
+ if (!empty($value['goods_json'])) {
+ $refund_gift_list[$value['manjian_id']]['goods'] = $value['goods_json'];
+ }
+ } else {
+ if ($rule_type == ManjianDict::CYCLE) {//循环优惠
+ if ($value['point'] > 0) {
+ if (!empty($gift) && !empty($gift['point'])) {
+ if ($value['point'] > $gift['point']) {
+ $value['point'] -= $gift['point'];
+ $refund_gift_list[$value['manjian_id']]['point'] = $value['point'];
+ }
+ }
+ }
+ if ($value['balance'] > 0) {
+ if (!empty($gift) && !empty($gift['balance'])) {
+ if ($value['balance'] > $gift['balance']) {
+ $value['balance'] -= $gift['balance'];
+ $refund_gift_list[$value['manjian_id']]['balance'] = $value['balance'];
+ }
+ }
+ }
+ if (!empty($value['coupon_json'])) {
+ foreach ($value['coupon_json'] as $coupon) {
+ if (!empty($gift) && !empty($gift['coupon'])) {
+ if ($coupon['num'] > $gift['coupon']['num']) {
+ $coupon['num'] -= $gift['coupon']['num'];
+ $refund_gift_list[$value['manjian_id']]['coupon'][] = $coupon;
+ }
+ }
+ }
+ }
+ if (!empty($value['goods_json'])) {
+ foreach ($value['goods_json'] as $goods) {
+ if (!empty($gift) && !empty($gift['goods'])) {
+ if ($goods['num'] > $gift['goods']['num']) {
+ $goods['num'] -= $gift['goods']['num'];
+ $refund_gift_list[$value['manjian_id']]['goods'][] = $goods;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return $refund_gift_list;
+ }
+
+ /**
+ * 订单退款后退还赠品
+ * @return true
+ */
+ public function refundGift($data)
+ {
+ $refund_gift_list = $this->refundCheck($data);
+ if (!empty($refund_gift_list)) {
+ $core_member_account = new CoreMemberAccountService();
+ $core_coupon_member_service = new CoreCouponMemberService();
+ $coupon_member_model = new CouponMember();
+ $member_model = new Member();
+ $coupon_model = new Coupon();
+ $order_goods_model = new OrderGoods();
+ $core_goods_stock_service = new CoreGoodsStockService();
+ $manjian_give_records_service = new ManjianGiveRecords();
+ $core_manjian_stat_service = new CoreManjianStatService();
+ foreach ($refund_gift_list as $manjian_id => $v) {
+ $manjian_give_where = [
+ ['member_id', '=', $data['member_id']],
+ ['order_id', '=', $data['order_id']],
+ ['manjian_id', '=', $manjian_id],
+ ];
+ $give_records = $manjian_give_records_service->field('coupon_json,goods_json')->where($manjian_give_where)->findOrEmpty()->toArray();
+ $member_info = $member_model->field('point,balance')->where([
+ ['member_id', '=', $data['member_id']],
+ ])->findOrEmpty()->toArray();
+ if (isset($v['point']) && $v['point'] > 0) {
+ //会员积分扣除
+ if ($member_info['point'] >= $v['point']) {//剩余积分足够才扣除
+ $core_member_account->addLog($data['member_id'], MemberAccountTypeDict:: POINT, -$v['point'], 'manjian_gift_back', '满减送活动订单退款退还赠送积分', $manjian_id);
+ $manjian_give_records_service->where($manjian_give_where)->update(['point' => Db::raw('point - ' . $v['point'])]);
+ }
+ }
+ if (isset($v['balance']) && $v['balance'] > 0) {
+ //会员余额扣除
+ if ($member_info['balance'] >= $v['balance']) {//剩余余额足够才扣除
+ $core_member_account->addLog($data['member_id'], MemberAccountTypeDict:: BALANCE, -$v['balance'], 'manjian_gift_back', '满减送活动订单退款退还赠送余额', $manjian_id);
+ $manjian_give_records_service->where($manjian_give_where)->update(['balance' => Db::raw('balance - ' . $v['balance'])]);
+ }
+ }
+ if (!empty($v['coupon']) && !empty($give_records)) {
+ //会员优惠券失效
+ $coupon_json = [];
+ foreach ($v['coupon'] as $coupon) {
+ $coupon_info = $coupon_model->where([['id', '=', $coupon['coupon_id']]])->findOrEmpty();
+ if (!$coupon_info->isEmpty()) {
+ $ids = $coupon_member_model->where([
+ ['member_id', '=', $data['member_id']],
+ ['coupon_id', '=', $coupon['coupon_id']],
+ ['status', '=', CouponMemberDict::WAIT_USE]
+ ])->limit($coupon['num'])->order('create_time desc')->column('id');
+ if (!empty($ids)) {
+ $core_coupon_member_service->invalid($ids);
+ $coupon_info->give_count -= $coupon['num'];
+ $coupon_info->save();
+ }
+ if (!empty($give_records['coupon_json'])) {
+ $coupon_array = array_column($give_records['coupon_json'], 'num', 'coupon_id');
+ if ($coupon_array[$coupon['coupon_id']] > $coupon['num']) {
+ $coupon_json[]['coupon_id'] = $coupon['coupon_id'];
+ $coupon_json[]['num'] = $coupon_array[$coupon['coupon_id']] - $coupon['num'];
+ }
+ }
+ }
+ }
+ $manjian_give_records_service->where($manjian_give_where)->update(['coupon_json' => $coupon_json]);
+ $nums = array_column($v['coupon'], 'num');
+ $coupon_num = array_sum($nums);
+ }
+ if (!empty($v['goods']) && !empty($give_records)) {
+ //赠品退款或扣除赠送数量
+ $goods_json = [];
+ foreach ($v['goods'] as $goods) {
+ $order_goods_where = [
+ ['member_id', '=', $data['member_id']],
+ ['order_id', '=', $data['order_id']],
+ ['goods_id', '=', $goods['goods_id']],
+ ['sku_id', '=', $goods['sku_id']],
+ ['is_gift', '=', 1]
+ ];
+ $order_goods_info = $order_goods_model->field('num')->where($order_goods_where)->findOrEmpty()->toArray();
+ if (!empty($order_goods_info)) {
+ if ($goods['num'] >= $order_goods_info['num']) {//赠送数量全部扣除,赠品订单项退款完成
+ $order_goods_model->where($order_goods_where)->update([
+ 'status' => OrderGoodsDict::REFUND_FINISH,
+ 'is_enable_refund' => 0,//禁用退款
+ ]);
+ } else {//没有全部扣除,只减去需要扣除的赠送数量,不改变退款状态
+ $order_goods_model->where($order_goods_where)->update(['num' => Db::raw('num - ' . $goods['num'])]);
+ }
+ //增加赠品库存
+ $core_goods_stock_service->inc([
+ 'num' => $goods['num'],
+ 'goods_id' => $goods['goods_id'],
+ 'sku_id' => $goods['sku_id']
+ ]);
+ }
+ if (!empty($give_records['goods_json'])) {
+ $goods_array = array_column($give_records['goods_json'], 'num', 'sku_id');
+ if ($goods_array[$goods['sku_id']] > $goods['num']) {
+ $goods_json[]['goods_id'] = $goods['goods_id'];
+ $goods_json[]['sku_id'] = $goods['sku_id'];
+ $goods_json[]['num'] = $goods_array[$goods['sku_id']] - $goods['num'];
+ }
+ }
+ }
+ $manjian_give_records_service->where($manjian_give_where)->update(['goods_json' => $goods_json]);
+ $nums = array_column($v['goods'], 'num');
+ $goods_num = array_sum($nums);
+ }
+ //满减活动数据统计
+ $stat_data = [
+ 'order_money' => -$data['money'],
+ 'point' => -($v['point'] ?? 0),
+ 'balance' => -($v['balance'] ?? 0),
+ 'coupon_num' => -($coupon_num ?? 0),
+ 'goods_num' => -($goods_num ?? 0)
+ ];
+ $core_manjian_stat_service->stat($manjian_id, $stat_data);
+ }
+ }
+ return true;
+ }
+
+ /**
+ * 获取满减送订单项赠送信息
+ * @return void
+ */
+ public function getOrderGoodsGiveInfo(&$order_goods_info, $order_goods_list, $member_id)
+ {
+ $manjian_records = (new ManjianGiveRecords())->field('manjian_id,level,point,balance,coupon_json,goods_json,sku_ids')->where([
+ ['member_id', '=', $member_id],
+ ['order_id', '=', $order_goods_info['order_id']],
+ ])->select()->toArray();
+ if (!empty($manjian_records)) {
+ foreach ($manjian_records as $kk => $vv) {
+ $manjian_list = (new Manjian())->field('manjian_id,manjian_name,condition_type,goods_type,join_member_type,rule_type,rule_json')->where([
+ ['manjian_id', '=', $vv['manjian_id']]
+ ])->select()->toArray();
+ foreach ($manjian_list as $manjian_info) {
+ $condition_match_value = 0;
+ foreach ($order_goods_list as $k => $v) {
+ if ($v['is_gift'] == 0) {
+ if (in_array($v['sku_id'], $vv['sku_ids'])) {
+ if (!empty($manjian_info)) {
+ if ($manjian_info['condition_type'] == ManjianDict::OVER_N_YUAN) {
+ $condition_match_value += $v['goods_money'];
+ } else {
+ $condition_match_value += $v['num'];
+ }
+ }
+ }
+ }
+ }
+ if (in_array($order_goods_info['sku_id'], $vv['sku_ids'])) {
+ if (!empty($manjian_info) && !empty($manjian_info['rule_json'])) {
+ $rule_json = $manjian_info['rule_json'][$vv['level']];
+ $cycle_num = 0;
+ if ($manjian_info['rule_type'] == ManjianDict::CYCLE) {
+ $cycle_num = intdiv($condition_match_value, $rule_json['limit']);
+ $rule_json['limit'] = $rule_json['limit'] * $cycle_num;
+ if (!empty($rule_json['discount_money'])) {
+ $rule_json['discount_money'] = bcmul($cycle_num, $rule_json['discount_money'], 2);
+ }
+ if (!empty($rule_json['point'])) {
+ $rule_json['point'] = intval($rule_json['point']) * $cycle_num;
+ }
+ if (!empty($rule_json['balance'])) {
+ $rule_json['balance'] = bcmul($cycle_num, $rule_json['balance'], 2);
+ }
+ }
+
+ if (!empty($rule_json['coupon'])) {
+ foreach ($rule_json['coupon'] as &$coupon) {
+ if ($manjian_info['rule_type'] == ManjianDict::CYCLE && $cycle_num > 0) {
+ $coupon['num'] = intval($coupon['num']) * $cycle_num;
+ }
+ $coupon_info = (new Coupon())->field('price,min_condition_money')->where([
+ ['id', '=', $coupon['coupon_id']]
+ ])->findOrEmpty()->toArray();
+ if (!empty($coupon_info)) {
+ if ($coupon_info['min_condition_money'] == '0.00') {
+ $coupon_name = $coupon_info['price'] . "元无门槛券";
+ } else {
+ $coupon_name = "满" . $coupon_info['min_condition_money'] . "元减" . $coupon_info['price'] . "元券";
+ }
+ $coupon['coupon_name'] = $coupon_name;
+ }
+ }
+ }
+ if (!empty($rule_json['goods'])) {
+ foreach ($rule_json['goods'] as &$goods) {
+ if ($manjian_info['rule_type'] == ManjianDict::CYCLE && $cycle_num > 0) {
+ $goods['num'] = intval($goods['num']) * $cycle_num;
+ }
+ $sku_info = (new GoodsSku())->field('goods_id,sku_name,sku_image,price')->where([
+ ['goods_id', '=', $goods['goods_id']],
+ ['sku_id', '=', $goods['sku_id']]
+ ])->with(['goods'])->findOrEmpty()->toArray();
+ if (!empty($sku_info) && !empty($sku_info['goods'])) {
+ $goods['goods_name'] = $sku_info['goods']['goods_name'];
+ $goods['sku_name'] = $sku_info['sku_name'];
+ $goods['sku_image'] = $sku_info['sku_image'];
+ $goods['price'] = $sku_info['price'];
+ }
+ }
+ }
+ $manjian_info['rule'] = $rule_json;
+ if ($manjian_info['rule']['is_discount'] || $manjian_info['rule']['is_free_shipping'] || $manjian_info['rule']['is_give_point'] || $manjian_info['rule']['is_give_balance'] || $manjian_info['rule']['is_give_coupon'] || $manjian_info['rule']['is_give_goods']) {
+ $order_goods_info['manjian_info'][] = $manjian_info;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * 满减优惠
+ * @param $data
+ * @return mixed
+ */
+ public function manjianPromotion($data, $member_id)
+ {
+ $promotion_money = $data['promotion_money'] ?? 0;
+ //先查询全部商品的满减套餐 进行中
+ $manjian_model = new Manjian();
+ $all_info = $manjian_model
+ ->field('manjian_id,manjian_name,goods_type,goods_ids,rule_json,rule_type,join_member_type,level_ids,label_ids,condition_type')
+ ->where([['goods_type', '=', ManjianDict::ALL_GOODS], ['status', '=', ManjianDict::ACTIVE]])
+ ->findOrEmpty()->toArray();
+
+ $goods_list = $data['goods_list'];
+ //存在全场满减
+ //验证当前用户是否可参与活动
+ if (!empty($all_info)) {
+ $can_join = $this->canJoinManjian($all_info, $member_id);
+ if ($can_join) {
+ //获取折扣价格
+ $discount_array = $this->getManjianDiscountMoney($all_info, $data);
+ $all_info['discount_array'] = $discount_array;
+
+ $discount_money = $discount_array['discount_money'];
+ $promotion_money = bcadd($promotion_money, $discount_money, 2);
+ if (!empty($discount_array['rule'])) {
+ $goods_list = array_map(function ($item) use ($all_info) {
+ $item['promotion']['manjian'][] = $all_info;
+ return $item;
+ }, $goods_list);
+ }
+ }
+ }
+
+ //指定不参与
+ $not_select_list = $manjian_model
+ ->field('manjian_id,manjian_name,goods_type,goods_ids,rule_json,rule_type,join_member_type,level_ids,label_ids,condition_type')
+ ->with(['activeGoods'])
+ ->where([['goods_type', '=', ManjianDict::SELECTED_GOODS_NOT], ['status', '=', ManjianDict::ACTIVE]])
+ ->select()->toArray();
+ if (!empty($not_select_list)) {
+ foreach ($not_select_list as $not_select_info) {
+ //验证当前用户是否可参与活动
+ $can_join = $this->canJoinManjian($not_select_info, $member_id);
+ if ($can_join) {
+ $not_select_goods_sku_id = [];
+ $item_goods_data = [
+ 'goods_money' => 0,
+ 'goods_num' => 0
+ ];
+ $item_goods_list = [];
+ $sku_ids = [];
+ $discount_money = 0;
+ if (isset($not_select_info['activeGoods']) && !empty($not_select_info['activeGoods'])) {
+ $not_select_goods_sku_id = array_column($not_select_info['activeGoods'], 'sku_id');
+ }
+
+ foreach ($goods_list as $goods_k => $goods_item) {
+ if (!in_array($goods_item['sku_id'], $not_select_goods_sku_id)) {
+ $item_goods_data['goods_money'] += $goods_item['goods_money'];
+ $item_goods_data['goods_num'] += $goods_item['num'];
+ $item_goods_list[] = $goods_item;
+ array_push($sku_ids, $goods_item['sku_id']);
+ }
+ }
+ $discount_array = $this->getManjianDiscountMoney($not_select_info, $item_goods_data);
+
+ $not_select_info['discount_array'] = $discount_array;
+ $discount_money = bcadd($discount_money, $discount_array['discount_money'], 2);
+
+ if (!empty($discount_array['rule'])) {
+ $goods_list = array_map(function ($item) use ($sku_ids, $not_select_info) {
+ if (in_array($item['sku_id'], $sku_ids)) {
+ $item['promotion']['manjian'][] = $not_select_info;
+ }
+ return $item;
+ }, $goods_list);
+ }
+ $promotion_money = bcadd($promotion_money, $discount_money, 2);
+ }
+ }
+
+
+ //指定参与
+ $goods_ids = array_unique(array_column($data['goods_list'], 'goods_id'));
+ $manjian_goods_list = (new ManjianGoods())
+ ->where([['status', '=', ManjianDict::ACTIVE], ['goods_id', 'in', $goods_ids]])
+ ->column('manjian_id');
+ if (!empty($manjian_goods_list)) {
+ $discount_money = 0;
+ $manjian_ids = array_unique($manjian_goods_list); //去重
+ sort($manjian_ids);
+ $manjian_list = $manjian_model
+ ->field('manjian_id,manjian_name,goods_type,goods_ids,rule_json,rule_type,join_member_type,level_ids,label_ids,condition_type')
+ ->with(['activeGoods'])
+ ->where([['goods_type', '=', ManjianDict::SELECTED_GOODS], ['status', '=', ManjianDict::ACTIVE], ['manjian_id', 'in', $manjian_ids]])
+ ->select()->toArray();
+ foreach ($manjian_list as $k => $v) {
+ //验证当前用户是否可参与活动
+ $can_join = $this->canJoinManjian($v, $member_id);
+ if (!$can_join) {
+ continue;
+ }
+ $manjian_goods_sku_ids = [];
+ if (isset($v['activeGoods']) && !empty($v['activeGoods'])) {
+ $manjian_goods_sku_ids = array_column($v['activeGoods'], 'sku_id');
+ }
+ $item_goods_data = [
+ 'goods_money' => 0,
+ 'goods_num' => 0
+ ];
+ $item_goods_list = [];
+ $sku_ids = [];
+ foreach ($goods_list as $goods_k => $goods_item) {
+ if (in_array($goods_item['sku_id'], $manjian_goods_sku_ids)) {
+ $item_goods_data['goods_money'] += $goods_item['goods_money'];
+ $item_goods_data['goods_num'] += $goods_item['num'];
+ $item_goods_list[] = $goods_item;
+ array_push($sku_ids, $goods_item['sku_id']);
+ $goods_list[$goods_k] = $goods_item;
+ }
+ }
+ $discount_array = $this->getManjianDiscountMoney($v, $item_goods_data);
+
+ $discount_money = bcadd($discount_money, $discount_array['discount_money'], 2);
+
+ if (!empty($discount_array['rule'])) {
+ $goods_list = array_map(function ($item) use ($sku_ids, $v, $discount_array) {
+ if (in_array($item['sku_id'], $sku_ids)) {
+ $temp = $v;
+ $temp['discount_array'] = $discount_array;
+ $item['promotion']['manjian'][] = $temp;
+ }
+ return $item;
+ }, $goods_list);
+ }
+ }
+
+ $promotion_money = bcadd($promotion_money, $discount_money, 2);
+ }
+ }
+ $data['goods_list'] = $goods_list;
+ $data['promotion_money'] = $promotion_money;
+ return $data;
+ }
+
+ /**
+ * 满减优惠金额
+ * @param $manjian_info
+ * @param $data
+ * @return array
+ */
+ public function getManjianDiscountMoney($manjian_info, $data)
+ {
+ $goods_money = $data['goods_money'];
+ if ($manjian_info['condition_type'] == ManjianDict::OVER_N_YUAN) {
+ $value = $data['goods_money'];
+ } else {
+ $value = $data['goods_num'];
+ }
+ //阶梯计算优惠
+ $rule_item = $manjian_info['rule_json'];
+ $discount_money = 0;
+ $money = 0;
+ $rule = []; // 符合条件的优惠规则
+ $level = -1; // 优惠层级
+ if ($manjian_info['rule_type'] == ManjianDict::LADDER) {
+ foreach ($rule_item as $k => $v) {
+ if ($value >= $v['limit']) {
+ $rule = $v;
+ if (isset($v['is_discount']) && $v['is_discount'] == 1) {
+ if ($v['discount_type'] == 1) {//减
+ $discount_money = $v['discount_money'] ?? 0;
+ } else {//折
+ $discount_money = bcsub($goods_money, bcmul(bcdiv(($v['discount_money'] ?? 0), 10, 2), $goods_money, 2), 2);
+ }
+ }
+ $money = $v['limit'] ?? 0;
+ $level = $k;
+ }
+ }
+ } elseif ($manjian_info['rule_type'] == ManjianDict::CYCLE) {
+ foreach ($rule_item as $k => $v) {
+ if ($value >= $v['limit']) {
+ $rule = $v;
+ $cycle_num = intdiv($value, $v['limit']);
+ if (isset($v['is_discount']) && $v['is_discount'] == 1) {
+ if ($v['limit'] == 0) {
+ $discount_money = 0;
+ } else {
+ $discount_money = bcmul($cycle_num, ($v['discount_money'] ?? 0), 2);
+ }
+ }
+ $level = $k;
+ }
+ }
+ }
+ return ['discount_money' => $discount_money, 'money' => $money, 'rule' => $rule, 'level' => $level];
+ }
+
+ /**
+ * 是否可参加活动
+ * @param $manjian_info
+ * @param $member_id
+ * @return bool
+ */
+ public function canJoinManjian($manjian_info, $member_id)
+ {
+ //判断会员是否有参与资格
+ $can_join = FALSE;
+ $join_member_type = $manjian_info['join_member_type'];
+ $level_ids = $manjian_info['level_ids'];
+ $label_ids = $manjian_info['label_ids'];
+ $member_info = (new Member())->field('member_level,member_label')->where([
+ ['member_id', '=', $member_id]
+ ])->findOrEmpty()->toArray();
+ if ($join_member_type == ManjianDict::ALL_MEMBER) {//所有会员参与
+ $can_join = TRUE;
+ } elseif ($join_member_type == ManjianDict::SELECTED_MEMBER_LEVEL) {//指定会员等级
+ if (in_array($member_info['member_level'], $level_ids)) {
+ $can_join = TRUE;
+ }
+ } elseif ($join_member_type == ManjianDict::SELECTED_MEMBER_LABEL) {//指定会员标签
+ if (!empty($member_info['member_label']) && !empty(array_intersect($member_info['member_label'], $label_ids))) {
+ $can_join = TRUE;
+ }
+ }
+ return $can_join;
+ }
+
+ /**
+ * 获取满减信息
+ * @return array
+ */
+ public function getManjianInfo($data)
+ {
+ $member_id = $data['member_id'];
+ $goods_id = $data['goods_id'];
+ $sku_id = $data['sku_id'];
+ $gift_goods = $data['gift_goods'] ?? [];
+ if ($sku_id == 0 && $goods_id == 0) {
+ return [];
+ }
+ if (empty($sku_id) && !empty($goods_id)) {
+ // 查询默认规格项
+ $default_sku_info = (new GoodsSku())->where([['goods_id', '=', $goods_id], ['is_default', '=', 1]], 'sku_id')
+ ->field('sku_id')->findOrEmpty()->toArray();
+ if (!empty($default_sku_info)) {
+ $sku_id = $default_sku_info['sku_id'];
+ }
+ }
+
+ $field = 'manjian_id,manjian_name,condition_type,rule_type,rule_json,join_member_type,level_ids,label_ids,start_time,end_time,remark';
+ $common_where = [
+ ['status', '=', ManjianDict::ACTIVE],
+ ['start_time', '<=', time()],
+ ['end_time', '>', time()]
+ ];
+ $manjian_info_all_goods = $this->model->field($field)->where($common_where)->where([['goods_type', '=', ManjianDict::ALL_GOODS]])->findOrEmpty()->toArray();
+ $all_manjian_info = [];
+ if (!empty($manjian_info_all_goods)) {//全部商品参与
+ $manjian_info = $manjian_info_all_goods;
+ $can_join = $this->canJoinManjian($manjian_info, $member_id);
+ if ($can_join) {
+ $rule_content = $this->getRuleContent($manjian_info, $gift_goods);
+ $manjian_info = $rule_content['is_join'] ? $rule_content : [];
+ }
+ $all_manjian_info[] = $manjian_info;
+ }
+
+ $manjian_info_selected_goods_not = $this->model->field($field)
+ ->where($common_where)
+ ->where([['goods_type', '=', ManjianDict::SELECTED_GOODS_NOT]])
+ ->select()->toArray();
+ if (!empty($manjian_info_selected_goods_not)) {//指定商品不参与
+ foreach ($manjian_info_selected_goods_not as $manjian_info) {
+ $can_join = $this->canJoinManjian($manjian_info, $member_id);
+ if ($can_join) {
+ $rule_content = $this->getRuleContent($manjian_info, $gift_goods);
+ $manjian_info = $rule_content['is_join'] ? $rule_content : [];
+ }
+ $all_manjian_info[] = $manjian_info;
+ }
+ }
+ //指定商品参与
+ $manjian_info_selected_goods = $this->model->field($field)->where($common_where)
+ ->where([['goods_type', '=', ManjianDict::SELECTED_GOODS]])
+ ->select()
+ ->toArray();
+ $manjian_goods_info = (new ManjianGoods())->field('manjian_id,goods_type')->where([
+ ['goods_id', '=', $goods_id],
+ ['sku_id', '=', $sku_id],
+ ['status', '=', ManjianDict::ACTIVE]
+ ])->where([['goods_type', '=', ManjianDict::SELECTED_GOODS]])
+ ->findOrEmpty()->toArray();
+ if (!empty($manjian_info_selected_goods) && !empty($manjian_goods_info)) {
+ $manjian_info_selected_goods = array_column($manjian_info_selected_goods, null, 'manjian_id');
+ if (in_array($manjian_goods_info['manjian_id'], array_keys($manjian_info_selected_goods))) {
+ $manjian_info = $manjian_info_selected_goods[$manjian_goods_info['manjian_id']];
+ $can_join = $this->canJoinManjian($manjian_info, $member_id);
+ if ($can_join) {
+ $rule_content = $this->getRuleContent($manjian_info, $gift_goods);
+ $manjian_info = $rule_content['is_join'] ? $rule_content : [];
+ }
+ $all_manjian_info[] = $manjian_info;
+ }
+ }
+ return $all_manjian_info;
+ }
+
+ /**
+ * 获取满减规则内容
+ * @param $manjian_info
+ * @return array
+ */
+ public function getRuleContent($manjian_info, $gift_goods)
+ {
+ if (!empty($manjian_info)) {
+ $is_join = false;
+ $manjian_info['gift_goods'] = $gift_goods;
+ foreach ($manjian_info['rule_json'] as $key => $item) {
+ if ($item['is_discount']) {
+ $is_join = true;
+ }
+ if ($item['is_free_shipping']) {
+ $is_join = true;
+ }
+ if ($item['is_give_point']) {
+ $is_join = true;
+ }
+ if ($item['is_give_balance']) {
+ $is_join = true;
+ }
+ if ($item['is_give_coupon']) {
+ foreach ($item['coupon'] as $coupon_key => &$coupon) {
+ $coupon_info = (new Coupon())->field('price,min_condition_money')->where([
+ ['id', '=', $coupon['coupon_id']],
+ ['status', '=', CouponDict::NORMAL],
+ ])->findOrEmpty()->toArray();
+ if (!empty($coupon_info)) {
+ if ($coupon_info['min_condition_money'] == '0.00') {
+ $coupon_name = $coupon_info['price'] . "元无门槛券";
+ } else {
+ $coupon_name = "满" . $coupon_info['min_condition_money'] . "元减" . $coupon_info['price'] . "元券";
+ }
+ $coupon['coupon_name'] = $coupon_name;
+ } else {
+ unset($item['coupon'][$coupon_key]);
+ }
+ }
+ $item['coupon'] = array_values($item['coupon']);
+ if (!empty($item['coupon'])) {
+ $is_join = true;
+ }
+ }
+ if ($item['is_give_goods']) {
+ foreach ($item['goods'] as $goods_key => &$goods) {
+ $sku_info = (new GoodsSku())->field('goods_id,sku_name,sku_image,price,stock')->where([
+ ['goods_id', '=', $goods['goods_id']],
+ ['sku_id', '=', $goods['sku_id']],
+ ['stock', '>', 0],
+ ])->with(['goods'])->findOrEmpty()->toArray();
+ if (!empty($sku_info) && !empty($sku_info['goods']) && $sku_info['goods']['status'] == 1) {
+ if (empty($gift_goods)) {
+ // 库存小于赠送数量时,取剩余库存
+ $num = $sku_info['stock'] >= $goods['num'] ? $goods['num'] : $sku_info['stock'];
+ $goods['num'] = $num;
+ } else {
+ // 计算剩余库存
+ $leave_num = $sku_info['stock'];
+ foreach ($gift_goods as $gift_goods_item) {
+ if ($gift_goods_item['goods_id'] == $goods['goods_id'] && $gift_goods_item['sku_id'] == $goods['sku_id']) {
+ if ($leave_num - $gift_goods_item['num'] >= 0) {
+ $leave_num = $leave_num - $gift_goods_item['num'];
+ } else {
+ $leave_num = 0;
+ }
+ }
+ }
+ $goods['num'] = $leave_num >= $goods['num'] ? $goods['num'] : $leave_num;
+ }
+ $goods['goods_name'] = $sku_info['goods']['goods_name'];
+ $goods['sku_name'] = $sku_info['sku_name'];
+ $goods['sku_image'] = $sku_info['sku_image'];
+ if (empty($goods['sku_image'])) {
+ $goods['sku_image'] = $sku_info['goods']['goods_cover_thumb_mid'];
+ }
+ $goods['price'] = $sku_info['price'];
+
+ if ($goods['num'] == 0) {
+ unset($item['goods'][$goods_key]);
+ }
+
+ $manjian_info['gift_goods'][] = $goods;
+
+ } else {
+ unset($item['goods'][$goods_key]);
+ }
+ }
+ $item['goods'] = array_values($item['goods']);
+ if (!empty($item['goods'])) {
+ $is_join = true;
+ }
+ }
+ $manjian_info['rule_json'][$key] = $item;
+ }
+ $manjian_info['is_join'] = $is_join;
+ }
+ return $manjian_info;
+ }
+
+ /**
+ * todo 金额格式化 封装调用
+ * @param $money
+ * @return float|int
+ */
+ public function moneyFormat($money)
+ {
+ return floor(strval(($money) * 100)) / 100;
+ }
+
+}
diff --git a/niucloud/addon/shop/app/service/core/marketing/CoreManjianStatService.php b/niucloud/addon/shop/app/service/core/marketing/CoreManjianStatService.php
new file mode 100644
index 000000000..720f7cac0
--- /dev/null
+++ b/niucloud/addon/shop/app/service/core/marketing/CoreManjianStatService.php
@@ -0,0 +1,82 @@
+ $data['order_money'] ?? 0,
+ 'total_order_num' => $data['order_num'] ?? 0,
+ 'total_member_num' => $data['member_num'] ?? 0,
+ 'total_point' => $data['point'] ?? 0,
+ 'total_balance' => $data['balance'] ?? 0,
+ 'total_coupon_num' => $data['coupon_num'] ?? 0,
+ 'total_goods_num' => $data['goods_num'] ?? 0
+ ];
+ self::set($manjian_id, $data);
+ return true;
+ }
+
+ /**
+ * 统计
+ * @param int $manjian_id
+ * @param array $data
+ * @return true
+ */
+ public static function set(int $manjian_id, array $data)
+ {
+ $manjian_model = new Manjian();
+ $condition = [
+ ['manjian_id', '=', $manjian_id],
+ ];
+ $manjian_info = $manjian_model->where($condition)->findOrEmpty();
+ if (!$manjian_info->isEmpty()) {
+ $update_data = [];
+ foreach ($data as $k => $v) {
+ if ($v != 0) {
+ if ($v > 0) {
+ $item_sql = ' + ' . abs($v);
+ } else if ($v < 0) {
+ $item_sql = ' - ' . abs($v);
+ }
+ $update_data[$k] = Db::raw('CASE WHEN '.$k . $item_sql. '>= 0 THEN ' .$k . $item_sql. ' ELSE 0 END');
+ }
+ }
+ if ($update_data) {
+ $manjian_info->save($update_data);
+ }
+ }
+ return true;
+ }
+
+}
diff --git a/niucloud/addon/shop/app/service/core/marketing/CoreNewcomerService.php b/niucloud/addon/shop/app/service/core/marketing/CoreNewcomerService.php
new file mode 100644
index 000000000..687cd9880
--- /dev/null
+++ b/niucloud/addon/shop/app/service/core/marketing/CoreNewcomerService.php
@@ -0,0 +1,228 @@
+model = new Active();
+ }
+
+ /**
+ * 获取新人专享配置
+ * @return array
+ */
+ public function getConfig()
+ {
+ $info = $this->model->field('active_id,active_status,active_value,active_desc')->where([ [ 'active_class', '=', ActiveDict::NEWCOMER_DISCOUNT ] ])->findOrEmpty()->toArray();
+ $value = [
+ 'active_id' => $info[ 'active_id' ] ?? 0,
+ 'active_status' => $info[ 'active_status' ] ?? 'close',
+ 'validity_type' => $info[ 'active_value' ][ 'validity_type' ] ?? 'day',
+ 'validity_day' => $info[ 'active_value' ][ 'validity_day' ] ?? 3,
+ 'validity_time' => date('Y-m-d H:i:s', $info[ 'active_value' ][ 'validity_time' ] ?? time() + 86400 * 3),
+ 'participation_way' => $info[ 'active_value' ][ 'participation_way' ] ?? 'never_order',
+ 'appoint_time' => date('Y-m-d H:i:s', $info[ 'active_value' ][ 'appoint_time' ] ?? time()),
+ 'limit_num' => $info[ 'active_value' ][ 'limit_num' ] ?? 1,
+ 'banner_list' => $info[ 'active_value' ][ 'banner_list' ] ?? [
+ [
+ 'imageUrl' => 'addon/shop/newcomer/banner.jpg',
+ 'toLink' => [
+ 'name' => '',
+ ]
+ ]
+ ]
+ ];
+
+ $default_active_desc = "1、新人价是面向" . $this->getParticipationWayContent($value[ 'participation_way' ]) . "提供的一种专属优惠价格,同一账号仅限享受一次优惠;\n";
+ $default_active_desc .= "2、仅限" . $this->getParticipationWayText($value[ 'participation_way' ], $value[ 'appoint_time' ]) . "可参与;\n";
+ $default_active_desc .= "3、活动有效期:" . $this->getValidityTypeText($value[ 'validity_type' ], $value[ 'validity_day' ], $value[ 'validity_time' ]);
+
+ $value[ 'active_desc' ] = $info[ 'active_desc' ] ?? $default_active_desc;
+ return $value;
+ }
+
+ /**
+ * 获取参与门槛文字描述
+ * @param $participation_way
+ * @return string
+ */
+ public function getParticipationWayContent($participation_way)
+ {
+ switch ($participation_way) {
+ case NewcomerDict::NEVER_ORDER:
+ return '从未下过单的会员';
+ case NewcomerDict::ASSIGN_TIME_ORDER:
+ return '指定时间内未下过单的会员';
+ case NewcomerDict::ASSIGN_TIME_REGISTER:
+ return '指定时间内注册的会员';
+ default:
+ return '';
+ }
+ }
+
+ /**
+ * 获取参与门槛文字描述
+ * @param $participation_way
+ * @param $appoint_time
+ * @return string
+ */
+ public function getParticipationWayText($participation_way, $appoint_time)
+ {
+ switch ($participation_way) {
+ case NewcomerDict::NEVER_ORDER:
+ return '从未下过单的会员';
+ case NewcomerDict::ASSIGN_TIME_ORDER:
+ return $appoint_time . '之前未下过单的会员';
+ case NewcomerDict::ASSIGN_TIME_REGISTER:
+ return $appoint_time . '之后注册的会员';
+ default:
+ return '';
+ }
+ }
+
+ /**
+ * 获取有效期文字描述
+ * @param $validity_type
+ * @param $validity_day
+ * @param $validity_time
+ * @return string
+ */
+ public function getValidityTypeText($validity_type, $validity_day, $validity_time)
+ {
+ switch ($validity_type) {
+ case NewcomerDict::DAY:
+ return '参与活动后' . $validity_day . '天内。';
+ case NewcomerDict::DATE:
+ return $validity_time . '后截止。';
+ default:
+ return '';
+ }
+ }
+
+ /**
+ * 检测当前会员是否满足新人专享活动条件
+ * @param $member_id
+ * @return bool
+ */
+ public function checkIfNewcomer($member_id)
+ {
+ $is_newcomer = false;
+ $config = $this->getConfig();
+ if (!empty($config)) {
+ if ($config[ 'active_status' ] == ActiveDict::ACTIVE) {
+ $appoint_time = strtotime($config[ 'appoint_time' ]);
+
+ $order_model = new Order();
+ $order_where = [
+ [ 'member_id', '=', $member_id ],
+ [ 'status', 'in', [ OrderDict::WAIT_PAY, OrderDict::WAIT_DELIVERY, OrderDict::WAIT_TAKE, OrderDict::FINISH ] ]
+ ];
+ switch ($config[ 'participation_way' ]) {
+ case NewcomerDict::NEVER_ORDER:
+ $order_count = $order_model->where($order_where)->count();
+ if ($order_count == 0) $is_newcomer = true;
+ break;
+ case NewcomerDict::ASSIGN_TIME_ORDER:
+ $order_where[] = [ 'create_time', '<', $appoint_time ];
+ $order_count = $order_model->where($order_where)->count();
+ if ($order_count == 0) $is_newcomer = true;
+ break;
+ case NewcomerDict::ASSIGN_TIME_REGISTER:
+ $member_info = ( new Member() )->field('create_time')->where([
+ [ 'member_id', '=', $member_id ] ])
+ ->findOrEmpty()->toArray();
+ if (!empty($member_info) && strtotime($member_info[ 'create_time' ]) >= $appoint_time) $is_newcomer = true;
+ break;
+ }
+
+ if ($is_newcomer) {
+ $newcomer_records_model = new NewcomerRecords();
+ $newcomerRecords = $newcomer_records_model->field('validity_time,is_join')->where([
+ [ 'member_id', '=', $member_id ]
+ ])->findOrEmpty()->toArray();
+ if (empty($newcomerRecords)) {
+ $validity_time = $this->getNewcomerEndTime($config);
+ $newcomer_records_model->create([
+ 'member_id' => $member_id,
+ 'validity_time' => $validity_time
+ ]);
+ } else {
+ if ($newcomerRecords[ 'validity_time' ] < time() || $newcomerRecords[ 'is_join' ] == 1) {
+ $is_newcomer = false;
+ }
+ }
+ }
+
+ }
+ }
+ return $is_newcomer;
+ }
+
+ /**
+ * 获取新人专享倒计时结束时间
+ * @param $member_id
+ * @param $config
+ * @return int
+ */
+ public function getNewcomerEndTime($config)
+ {
+ $end_time = 0;
+ switch ($config[ 'validity_type' ]) {
+ case NewcomerDict::DAY:
+ $validity_day = $config[ 'validity_day' ];
+ $end_time = time() + $validity_day * 86400;
+ break;
+ case NewcomerDict::DATE:
+ $validity_time = strtotime($config[ 'validity_time' ]);
+ $end_time = $validity_time;
+ break;
+ }
+ return $end_time;
+ }
+
+ /**
+ * 新人专享活动修改后更新会员活动有效期
+ * @return bool
+ */
+ public function afterSave()
+ {
+ $config = $this->getConfig();
+ ( new NewcomerRecords() )->where([
+ [ 'is_join', '=', 0 ],
+ [ 'order_id', '=', 0 ]
+ ])->update(
+ [
+ 'validity_time' => $this->getNewcomerEndTime($config),
+ 'update_time' => time()
+ ]
+ );
+ return true;
+ }
+
+}
diff --git a/niucloud/addon/shop/app/service/core/order/CoreInvoiceService.php b/niucloud/addon/shop/app/service/core/order/CoreInvoiceService.php
new file mode 100644
index 000000000..a56c912cd
--- /dev/null
+++ b/niucloud/addon/shop/app/service/core/order/CoreInvoiceService.php
@@ -0,0 +1,93 @@
+model = new Invoice();
+ }
+
+ /**
+ * 创建关联订单的发票
+ * @param array $data
+ * @return array
+ */
+ public function add($data)
+ {
+ $invoice = $this->model->create($data);
+ return $invoice->id;
+ }
+
+ /**
+ * 发票启用
+ * @param $id
+ * @return void
+ */
+ public function open($id)
+ {
+ $this->model->where(
+ [
+ ['id', '=', $id]
+ ]
+ )->update([
+ 'status' => InvoiceDict::OPEN
+ ]);
+ return true;
+ }
+
+ /**
+ * 发票审核
+ * @param $id
+ * @return void
+ */
+ public function audit($ids)
+ {
+ $this->model->where(
+ [
+ ['id', 'in', $ids],
+ ['is_invoice', '=', InvoiceDict::WAIT_AUDIT]
+ ]
+ )->update([
+ 'is_invoice' => InvoiceDict::WAIT_INVOICE
+ ]);
+ return true;
+ }
+
+ /**
+ * 发票关闭
+ * @param $id
+ * @return true
+ */
+ public function close($id)
+ {
+ $this->model->where(
+ [
+ ['id', '=', $id]
+ ]
+ )->update([
+ 'status' => InvoiceDict::WAIT_OPEN
+ ]);
+ return true;
+ }
+
+}
diff --git a/niucloud/addon/shop/app/service/core/order/CoreOrderBatchDeliveryService.php b/niucloud/addon/shop/app/service/core/order/CoreOrderBatchDeliveryService.php
new file mode 100644
index 000000000..787f37e6e
--- /dev/null
+++ b/niucloud/addon/shop/app/service/core/order/CoreOrderBatchDeliveryService.php
@@ -0,0 +1,339 @@
+model = new OrderBatchDelivery();
+ }
+
+
+ public function add($data)
+ {
+ //记录
+ $data[ 'status' ] = OrderBatchDeliveryDict::PROCESSING;//进行中
+ $batch = $this->model->create($data);
+ //发布任务
+// (new CoreOrderBatchDeliveryService())->execute($batch['id']);
+ OrderBatchDeliveryJob::dispatch([ 'data' => $batch->toArray() ]);
+ return true;
+ }
+
+ /**
+ * 执行任务
+ * @param $id
+ * @return void
+ */
+ public function execute($id)
+ {
+ $where = [ 'id' => $id ];
+ //获取订单
+ $batch = $this->model->where($where)->findOrEmpty();
+ if ($batch->isEmpty()) throw new CommonException("任务不存在");
+ if ($batch[ 'status' ] != OrderBatchDeliveryDict::PROCESSING) throw new CommonException("任务已经完成");
+ $type = $batch[ 'type' ];
+ switch ($type) {
+ case 'delivery':
+ //订单批量发货
+ $result = $this->delivery($batch);
+ break;
+ }
+ $fail_remark = $result[ 'fail_remark' ] ?? '';
+ if (empty($fail_remark)) {
+ $status = OrderBatchDeliveryDict::FINISH;
+ } else {
+ $status = OrderBatchDeliveryDict::FAIL;
+ }
+ //todo 完成或失败后,记录日志
+ $update_data = [
+ 'status' => $status,
+ 'total_num' => $result[ 'total_num' ],
+ 'success_num' => $result[ 'success_num' ],
+ 'fail_num' => $result[ 'fail_num' ],
+ 'fail_remark' => $result[ 'fail_remark' ]
+ ];
+ $total_list = $result[ 'total_list' ];
+ //将完整记录写入excel
+ if (!empty($total_list)) {
+ $output_dir = public_path() . 'upload' . DIRECTORY_SEPARATOR . 'batch' . DIRECTORY_SEPARATOR . 'output' . DIRECTORY_SEPARATOR;
+ if (!is_dir($output_dir) && !mkdir($output_dir, 0777, true) && !is_dir($output_dir)) {
+
+ } else {
+ $output = $output_dir . create_no() . '.csv';
+ $file = fopen($output, 'wb');
+ foreach ($total_list as $row) {
+ fputcsv($file, $row, ',', '"');
+ }
+ fclose($file);
+ $update_data[ 'output' ] = str_replace(public_path(), '', $output);
+ }
+ }
+
+ //将失败记录写入excel
+ $fail_list = $result[ 'fail_list' ];
+ if (!empty($fail_list)) {
+ $fail_output_dir = public_path() . 'upload' . DIRECTORY_SEPARATOR . 'batch' . DIRECTORY_SEPARATOR . 'fail_output' . DIRECTORY_SEPARATOR;
+ if (!is_dir($fail_output_dir) && !mkdir($fail_output_dir, 0777, true) && !is_dir($fail_output_dir)) {
+
+ } else {
+ $fail_output = $fail_output_dir . create_no() . '.csv';
+ $fail_file = fopen($fail_output, 'wb');
+ foreach ($fail_list as $row) {
+ fputcsv($fail_file, $row, ',', '"');
+ }
+ fclose($fail_file);
+ $update_data[ 'fail_output' ] = str_replace(public_path(), '', $fail_output);
+ }
+ }
+ $this->model->where('id', $id)->update($update_data);
+ return $result;
+ }
+
+ /**
+ * 批量发货
+ * @param $params
+ * @return int[]
+ * @throws \PhpOffice\PhpSpreadsheet\Exception
+ */
+ public function delivery($params)
+ {
+ $order_delivery_data = [];//以订单编号为key分配数据
+ $core_order_delivery_service = new CoreOrderDeliveryService();
+ $order_model = new Order();
+ $order_goods_model = new OrderGoods();
+ $main_id = $params[ 'main_id' ];
+ $order_id_list_map = [];
+
+ $express_company_column = ( new Company() )->where([ [ 'company_id', '>', 0 ] ])->column('company_id', 'company_name');
+
+ $total_num = 0;
+ $success_num = 0;
+ $fail_count = 0;
+ $total_list = [];
+
+ if (empty($params[ 'order_ids' ])) {
+ $data = $params[ 'data' ];
+ //读取导入文件
+ $path = public_path() . $data[ 'path' ];
+ if (is_file($path)) {
+ try {
+ //复制一个新文件
+ $type = $data[ 'type' ];
+ //将文件内容读取出来
+ $spreadsheet = IOFactory::load($path);
+ // 选择要操作的工作表,这里选择第一个工作表
+ $sheet = $spreadsheet->getSheet(0);
+
+ // 获取行和列的数据
+ $highestRow = $sheet->getHighestRow(); // 取得总行数
+ $highestColumn = $sheet->getHighestColumn(); // 取得总列数
+ if ($type == 'order') {//整单发货
+ $sheet->setCellValue('D' . 1, '结果');
+ $sheet->setCellValue('E' . 1, '描述');
+ $total_list = [
+ [
+ '订单编号', '物流公司', '物流单号', '结果', '描述'
+ ]
+ ];
+ $fail_list = [
+ [
+ '订单编号', '物流公司', '物流单号', '结果', '描述'
+ ]
+ ];
+
+ } else {
+ $sheet->setCellValue('E' . 1, '结果');
+ $sheet->setCellValue('F' . 1, '描述');
+ $total_list = [
+ [
+ '订单编号', '订单项ID', '物流公司', '物流单号', '结果', '描述'
+ ]
+ ];
+ $fail_list = [
+ [
+ '订单编号', '订单项ID', '物流公司', '物流单号', '结果', '描述'
+ ]
+ ];
+ }
+ // 循环读取每一行的数据
+ for ($row = 2; $row <= $highestRow; ++$row) {
+ // 读取一行数据
+ $rowData = $sheet->rangeToArray('A' . $row . ':' . $highestColumn . $row, NULL, TRUE, FALSE);
+ // 根据需要处理$rowData
+ $item_data = $rowData[ 0 ];
+ $item_data = array_map(function($value) { return trim($value); }, $item_data);
+
+ $error = '';
+ try {
+ $item_order_no = $item_data[ 0 ];
+
+ if (empty($item_order_no)) continue;
+ $total_num++;
+ $item_data[ 0 ] = (string) $item_data[ 0 ] . "\t";
+ $temp_item_data = [];
+ $item_order_id = $order_id_list_map[ $item_order_no ] ?? 0;
+ if ($item_order_id == 0) {
+ $temp_order = $order_model->where([ 'order_no' => $item_order_no ])->findOrEmpty();
+ if (!$temp_order->isEmpty()) {
+ $order_id_list_map[ $item_order_no ] = $temp_order[ 'order_id' ];
+ $item_order_id = $temp_order[ 'order_id' ];
+ $order_id_list_map[ $item_order_no ] = $item_order_id;
+ }
+ }
+
+ if ($item_order_id > 0) {
+ if ($type == 'order') {//整单发货
+ $item_express_company_name = $item_data[ 1 ];
+ $express_number = $item_data[ 2 ] ?? '';
+ if ($item_express_company_name != '无需物流') {
+ $delivery_type = OrderDeliveryDict::EXPRESS;
+ $item_express_company_id = $express_company_column[ $item_express_company_name ] ?? 0;
+ if ($item_express_company_id == 0) {
+// $error = '物流公司不存在';
+ throw new CommonException('物流公司不存在');
+ }
+ } else {
+ $delivery_type = OrderDeliveryDict::NONE_EXPRESS;
+ $item_express_company_id = 0;
+ $express_number = '';
+ }
+
+
+ $item_order_goods_ids = $order_goods_model->where([ 'order_id' => $item_order_id ])->column('order_goods_id');
+ $core_order_delivery_service->delivery([
+ 'main_type' => OrderLogDict::SYSTEM,
+ 'main_id' => $main_id,
+ 'order_id' => $item_order_id,//订单编号
+ 'order_goods_ids' => $item_order_goods_ids,//订单项ids
+ 'delivery_type' => $delivery_type,//配送方式
+ 'delivery_way' => 'manual_write',//发货方式,manual_write:手动填写,electronic_sheet:电子面单
+ 'express_company_id' => $item_express_company_id,//物流公司
+ 'express_number' => $express_number,//物流单号
+ 'remark' => '',
+ 'electronic_sheet_id' => ''//电子面单模板
+ ]);
+
+ } else {
+ $item_express_company_name = $item_data[ 2 ];
+ $express_number = $item_data[ 3 ] ?? '';
+ if ($item_express_company_name != '无需物流') {
+ $delivery_type = OrderDeliveryDict::EXPRESS;
+ $item_express_company_id = $express_company_column[ $item_express_company_name ] ?? 0;
+ if ($item_express_company_id == 0) {
+// $error = '物流公司不存在';
+ throw new CommonException('物流公司不存在');
+ }
+ } else {
+ $delivery_type = OrderDeliveryDict::NONE_EXPRESS;
+ $item_express_company_id = 0;
+ $express_number = '';
+ }
+
+ $core_order_delivery_service->delivery([
+ 'main_type' => OrderLogDict::SYSTEM,
+ 'main_id' => $main_id,
+ 'order_id' => $item_order_id,//订单编号
+ 'order_goods_ids' => [ $item_data[ 1 ] ],//订单项ids
+ 'delivery_type' => $delivery_type,//配送方式
+ 'delivery_way' => 'manual_write',//发货方式,manual_write:手动填写,electronic_sheet:电子面单
+ 'express_company_id' => $item_express_company_id,//物流公司
+ 'express_number' => $express_number,//物流单号
+ 'remark' => '',
+ 'electronic_sheet_id' => ''//电子面单模板
+ ]);
+
+ }
+ } else {
+ $error = '订单不存在';
+ }
+ } catch (\Exception $e) {
+ $error = get_lang($e->getMessage());
+ }
+ if ($type == 'order') {//整单发货
+ $temp_item_data = [
+ $item_data[ 0 ],
+ $item_data[ 1 ],
+ $item_data[ 2 ]
+ ];
+ } else {
+ $temp_item_data = [
+ $item_data[ 0 ],
+ $item_data[ 1 ],
+ $item_data[ 2 ],
+ $item_data[ 3 ]
+ ];
+ }
+ if (!$error) {
+ $temp_item_data[] = '成功';
+ $total_list[] = $temp_item_data;
+ $success_num++;
+ } else {
+ $temp_item_data[] = '失败';
+ $temp_item_data[] = $error;
+ $total_list[] = $temp_item_data;
+ $fail_list[] = $temp_item_data;
+ $fail_count++;
+ }
+
+ }
+ } catch (\Exception $e) {
+ $fail_remark = get_lang($e->getMessage());
+ }
+ } else {
+ $fail_remark = '文件不存在';
+ }
+ }
+ return [
+ 'success_num' => $success_num,
+ 'fail_num' => $fail_count,
+ 'total_num' => $total_num,
+ 'total_list' => $total_list ?? [],
+ 'fail_list' => $fail_list ?? [],
+ 'fail_remark' => $fail_remark ?? ''
+ ];
+ }
+
+
+ public function batchDelivery($data)
+ {
+
+ }
+
+ /**
+ * 获取正在进行的任务
+ * @return void
+ */
+ public function getProcessingList()
+ {
+ return $this->model->where('status', OrderBatchDeliveryDict::PROCESSING)->select();
+ }
+}
diff --git a/niucloud/addon/shop/app/service/core/order/CoreOrderCloseService.php b/niucloud/addon/shop/app/service/core/order/CoreOrderCloseService.php
new file mode 100644
index 000000000..9ea48de9e
--- /dev/null
+++ b/niucloud/addon/shop/app/service/core/order/CoreOrderCloseService.php
@@ -0,0 +1,133 @@
+model = new Order();
+ }
+
+ /**
+ * 订单关闭
+ * @param array $data
+ * @return void
+ */
+ public function close(array $data)
+ {
+ try {
+ $order_data = $this->model->where([
+ ['order_id', '=', $data['order_id']],
+ ])->findOrEmpty()->toArray();
+ if (empty($order_data)) throw new CommonException('SHOP_ORDER_NOT_FOUND');//订单不存在
+ if ($order_data['status'] == OrderDict::CLOSE) throw new CommonException('SHOP_ORDER_IS_CLOSED');
+ if ($data['close_type'] == OrderDict::SHOP_CLOSE && !in_array($order_data['status'], [ OrderDict::WAIT_PAY, OrderDict::CLOSE ])) {
+ throw new CommonException('SHOP_ORDER_IS_PAY_FINISH');//订单已支付
+ }
+ if ($data['close_type'] != OrderDict::REFUND_CLOSE) {
+ //关闭相关的支付 todo 封装订单专用的关闭支付相关
+ try {
+ (new CorePayService())->closeByTrade(OrderDict::TYPE, $order_data['order_id']);
+ } catch ( \Exception $e ) {
+
+ }
+ }
+
+ //关闭订单
+ $this->model->where([
+ [
+ ['order_id', '=', $order_data['order_id']]
+ ]
+ ])->update(
+ [
+ 'status' => OrderDict::CLOSE,
+ 'close_type' => $data['close_type'],
+ 'close_remark' => $data['close_remark'] ?? '',
+ 'is_enable_refund' => 0,
+ 'timeout' => 0
+ ]
+ );
+ $data['order_data'] = $order_data;
+// //订单关闭后操作
+// event('AfterShopOrderClose', $data);
+
+ //订单关闭操作
+ CoreOrderEventService::orderClose($data);
+ //订单关闭后操作
+ CoreOrderEventService::orderCloseAfter($data);
+ return true;
+ } catch ( \Exception $e ) {
+ throw new CommonException($e->getMessage());
+ }
+ }
+
+ /**
+ * 校验一下是否全部退款
+ * @param $data
+ * @return void
+ * @throws \think\db\exception\DbException
+ */
+ public function checkAllClose($data)
+ {
+ $order_id = $data['order_id'];
+ //检测一下订单下的订单项是否全部退款完毕
+ $where = array(
+ ['order_id', '=', $order_id],
+ ['status', '<>', OrderGoodsDict::REFUND_FINISH]
+ );
+ if ((new OrderGoods())->where($where)->count() == 0) {
+ $data = [];
+// $data['main_type'] = OrderLogDict::SYSTEM;
+// $data['main_id'] = 0;
+// $data['close_type'] = OrderDict::REFUND_CLOSE;
+// $data['order_id'] = $order_id;
+// $this->close($data);
+
+ //判断订单总额是否全部扣除
+ $order = (new Order())->where([['order_id', '=', $order_id]])->findOrEmpty();
+ $total_refund_money = (new OrderRefund())->where([['order_id', '=', $order_id], ['status', '=', OrderRefundDict::FINISH]])->sum('money');
+ if ($total_refund_money >= $order['order_money']) {
+ $data['main_type'] = OrderLogDict::SYSTEM;
+ $data['main_id'] = 0;
+ $data['close_type'] = OrderDict::REFUND_CLOSE;
+ $data['order_id'] = $order_id;
+ $this->close($data);
+ }else{//订单项全部关闭,但是订单总额为完全退款,订单直接完成
+ //调用订单直接完成
+ $data['main_type'] = OrderLogDict::SYSTEM;
+ $data['main_id'] = 0;
+ $data['order_id'] = $order_id;
+ (new CoreOrderFinishService())->finish($data);
+ }
+ event('AfterShopOrderAllRefundFinish', $data);
+ }
+ return true;
+ }
+
+}
diff --git a/niucloud/addon/shop/app/service/core/order/CoreOrderConfigService.php b/niucloud/addon/shop/app/service/core/order/CoreOrderConfigService.php
new file mode 100644
index 000000000..7bec9b1e6
--- /dev/null
+++ b/niucloud/addon/shop/app/service/core/order/CoreOrderConfigService.php
@@ -0,0 +1,249 @@
+core_config_service = new CoreConfigService();
+ }
+
+ /**
+ * 设置交易配置
+ * @param array $params
+ * @return array
+ */
+ public function setConfig($params)
+ {
+ $value[ 'order_close' ] = [
+ 'is_close' => $params[ 'is_close' ],
+ 'close_length' => $params[ 'close_length' ]
+ ];
+ $value[ 'order_finish' ] = [
+ 'is_finish' => $params[ 'is_finish' ],
+ 'finish_length' => $params[ 'finish_length' ]
+ ];
+ $value[ 'order_refund' ] = [
+ 'no_allow_refund' => $params[ 'no_allow_refund' ],
+ 'refund_length' => $params[ 'refund_length' ]
+ ];
+ $value[ 'evaluate' ] = [
+ 'is_evaluate' => $params[ 'is_evaluate' ],
+ 'evaluate_is_to_examine' => $params[ 'evaluate_is_to_examine' ],
+ 'evaluate_is_show' => $params[ 'evaluate_is_show' ]
+ ];
+ $value[ 'form_id' ] = $params[ 'form_id' ];
+
+ $this->core_config_service->setConfig('SHOP_ORDER_CONFIG', $value);
+
+ $invoice = 'SHOP_INVOICE';
+ $invoiceInfo = [
+ 'is_invoice' => $params[ 'is_invoice' ],
+ 'invoice_type' => $params[ 'invoice_type' ],
+ 'invoice_content' => $params[ 'invoice_content' ]
+ ];
+ $this->core_config_service->setConfig($invoice, $invoiceInfo);
+
+ $evaluate = 'SHOP_GOODS_EVALUATE';
+ $evaluateInfo = [
+ 'is_evaluate' => $params[ 'is_evaluate' ],
+ 'evaluate_is_to_examine' => $params[ 'evaluate_is_to_examine' ],
+ 'evaluate_is_show' => $params[ 'evaluate_is_show' ]
+ ];
+ $this->core_config_service->setConfig($evaluate, $evaluateInfo);
+
+ return true;
+ }
+
+ /**
+ * 自动取消订单
+ */
+ public function orderClose()
+ {
+ $data = ( new CoreConfigService() )->getConfigValue('SHOP_ORDER_CONFIG');
+ if (empty($data)) {
+ $closeOrderInfo = [
+ 'is_close' => true,
+ 'close_length' => 120
+ ];
+ } else {
+ $closeOrderInfo = [
+ 'is_close' => $data[ 'order_close' ][ 'is_close' ],
+ 'close_length' => $data[ 'order_close' ][ 'close_length' ]
+ ];
+ }
+ return $closeOrderInfo;
+ }
+
+ /**
+ * 获取交易配置
+ * @return array
+ */
+ public function getConfig()
+ {
+ $data = ( new CoreConfigService() )->getConfigValue('SHOP_ORDER_CONFIG');
+ if (empty($data)) {
+ $data[ 'close_order_info' ] = [
+ 'is_close' => true,
+ 'close_length' => 120
+ ];
+ $data[ 'confirm' ] = [
+ 'is_finish' => true,
+ 'finish_length' => 14
+ ];
+ $data[ 'refund' ] = [
+ 'no_allow_refund' => 1,
+ 'refund_length' => 7
+ ];
+ $data[ 'form_id' ] = '';
+ } else {
+ $data[ 'close_order_info' ] = [
+ 'is_close' => $data[ 'order_close' ][ 'is_close' ],
+ 'close_length' => $data[ 'order_close' ][ 'close_length' ]
+ ];
+ $data[ 'confirm' ] = [
+ 'is_finish' => $data[ 'order_finish' ][ 'is_finish' ],
+ 'finish_length' => $data[ 'order_finish' ][ 'finish_length' ],
+ ];
+ $data[ 'refund' ] = [
+ 'no_allow_refund' => $data[ 'order_refund' ][ 'no_allow_refund' ],
+ 'refund_length' => $data[ 'order_refund' ][ 'refund_length' ],
+ ];
+ $data[ 'form_id' ] = $data[ 'form_id' ] ?? '';
+
+ if(!empty($data[ 'form_id' ])) {
+ $diy_form_model = new DiyForm();
+ $diy_form_count = $diy_form_model->where([
+ [ 'form_id', '=', $data[ 'form_id' ] ]
+ ])->count();
+ if ($diy_form_count == 0) {
+ $data[ 'form_id' ] = '';
+ }
+ }
+ }
+
+ //发票
+ $data[ 'invoice' ] = ( new CoreConfigService() )->getConfigValue('SHOP_INVOICE');
+ if (empty($data[ 'invoice' ])) {
+ $data[ 'invoice' ] = [
+ 'is_invoice' => '2',
+ 'invoice_type' => [],
+ 'invoice_content' => []
+ ];
+ }
+ //评价
+ $data[ 'evaluate' ] = ( new CoreConfigService() )->getConfigValue('SHOP_GOODS_EVALUATE');
+ if (empty($data[ 'evaluate' ])) {
+ $data[ 'evaluate' ] = [
+ 'is_evaluate' => 1,
+ 'evaluate_is_to_examine' => 1,
+ 'evaluate_is_show' => 1
+ ];
+ }
+ return $data;
+ }
+
+ /**
+ * 订单确认收货
+ */
+ public function orderConfirm()
+ {
+ $data = ( new CoreConfigService() )->getConfigValue('SHOP_ORDER_CONFIG');
+ if (empty($data)) {
+ $confirmOrderInfo = [
+ 'is_finish' => true,
+ 'finish_length' => 14
+ ];
+ } else {
+ $confirmOrderInfo = [
+ 'is_finish' => $data[ 'order_finish' ][ 'is_finish' ],
+ 'finish_length' => $data[ 'order_finish' ][ 'finish_length' ]
+ ];
+ }
+ return $confirmOrderInfo;
+ }
+
+ /**
+ * 售后
+ */
+ public function orderRefund()
+ {
+ $data = ( new CoreConfigService() )->getConfigValue('SHOP_ORDER_CONFIG');
+ if (empty($data)) {
+ $refundOrderInfo = [
+ 'no_allow_refund' => 1,
+ 'refund_length' => 7
+ ];
+ } else {
+ $refundOrderInfo = [
+ 'no_allow_refund' => $data[ 'order_refund' ][ 'no_allow_refund' ],
+ 'refund_length' => $data[ 'order_refund' ][ 'refund_length' ]
+ ];
+ }
+ return $refundOrderInfo;
+ }
+
+ /**
+ * 发票信息
+ */
+ public function invoice()
+ {
+ $data = ( new CoreConfigService() )->getConfigValue('SHOP_INVOICE');
+ if (empty($data)) {
+ $invoiceInfo = [
+ 'is_invoice' => '',
+ 'invoice_type' => [],
+ 'invoice_content' => []
+ ];
+ } else {
+ $invoiceInfo = [
+ 'is_invoice' => $data[ 'is_invoice' ],
+ 'invoice_type' => $data[ 'invoice_type' ],
+ 'invoice_content' => $data[ 'invoice_content' ]
+ ];
+ }
+ return $invoiceInfo;
+ }
+
+ /**
+ * 获取评价设置
+ * @return array|int[]|mixed
+ */
+ public function getEvaluateConfig()
+ {
+ $config = ( new CoreConfigService() )->getConfigValue('SHOP_GOODS_EVALUATE');
+ if (empty($config)) {
+ $config = [
+ 'is_evaluate' => 1,
+ 'evaluate_is_to_examine' => 1,
+ 'evaluate_is_show' => 1
+ ];
+ }
+ return $config;
+ }
+}
+
diff --git a/niucloud/addon/shop/app/service/core/order/CoreOrderCreateService.php b/niucloud/addon/shop/app/service/core/order/CoreOrderCreateService.php
new file mode 100644
index 000000000..55d149b6c
--- /dev/null
+++ b/niucloud/addon/shop/app/service/core/order/CoreOrderCreateService.php
@@ -0,0 +1,436 @@
+model = new Order();
+ }
+
+ /**
+ * 订单创建
+ * @param array $data
+ * @return array
+ */
+ public function create(array $data)
+ {
+ //参数赋值
+ $this->setParam($data);
+
+ $member_info = ( new CoreMemberService() )->getInfoByMemberId($data[ 'member_id' ], 'status');
+
+ if (empty($member_info)) throw new CommonException('SHOP_ORDER_BUYER_NOT_FOUND');//无效的账号
+ if ($member_info[ 'status' ] == MemberDict::OFF) throw new CommonException('SHOP_ORDER_BUYER_LOCKED');//账号被锁定
+
+ $order_key = $this->param[ 'order_key' ] ?? '';
+ //获取订单缓存缓存
+ $this->getOrderCache($order_key);
+
+ $this->goods_data = array_merge($this->goods_data, $this->gift_goods);
+ $this->form_data = $this->param[ 'form_data' ] ?? []; // 万能表单数据
+ //校验错误
+ $this->checkError();
+ //普通订单校验库存
+ $this->checkStock($this->goods_data);
+ $local_delivery_type = $data[ 'delivery' ]['local_delivery_type'] ?? '';
+ $order_data = [
+ //订单整体
+ 'order_type' => OrderDict::TYPE,
+ 'status' => OrderDict::WAIT_PAY,
+ 'body' => $this->basic[ 'body' ],
+ 'member_id' => $this->member_id,
+ 'goods_money' => $this->basic[ 'goods_money' ],
+ 'delivery_money' => $this->basic[ 'delivery_money' ] ?? 0,
+ 'discount_money' => $this->basic[ 'discount_money' ] ?? 0,
+ 'order_money' => $this->basic[ 'order_money' ],
+ 'has_goods_types' => $this->basic[ 'has_goods_types' ],//包含的商品形式
+// 'invoice_id' => $order_array['invoice_id'] ?? 0,
+
+ //收发货相关
+ 'delivery_type' => $this->delivery[ 'delivery_type' ] ?? '',
+ 'taker_name' => $data[ 'delivery' ][ 'taker_name' ] ?? $this->delivery[ 'take_address' ][ 'name' ] ?? '',
+ 'taker_mobile' => $data[ 'delivery' ][ 'taker_mobile' ] ?? $this->delivery[ 'take_address' ][ 'mobile' ] ?? '',
+ 'buyer_ask_delivery_time' =>$local_delivery_type == 'now' ? "" : $data[ 'delivery' ][ 'buyer_ask_delivery_time' ] ?? '', // 购买者期望的时间
+ 'taker_province' => $this->delivery[ 'take_address' ][ 'province_id' ] ?? 0,
+ 'taker_city' => $this->delivery[ 'take_address' ][ 'city_id' ] ?? 0,
+ 'taker_district' => $this->delivery[ 'take_address' ][ 'district_id' ] ?? 0,
+ 'taker_address' => $this->delivery[ 'take_address' ][ 'address' ] ?? '',
+ 'taker_full_address' => $this->delivery[ 'take_address' ][ 'full_address' ] ?? '',
+ 'taker_longitude' => $this->delivery[ 'take_address' ][ 'lng' ] ?? '',
+ 'taker_latitude' => $this->delivery[ 'take_address' ][ 'lat' ] ?? '',
+ 'take_store_id' => $this->delivery[ 'take_store' ][ 'store_id' ] ?? 0,
+
+ // 附属信息
+ 'member_remark' => $this->param[ 'member_remark' ] ?? '',//买家留言
+ 'relate_id' => $this->extend_data[ 'relate_id' ] ?? 0,//关联id
+ 'activity_type' => $this->extend_data[ 'activity_type' ] ?? '', // 活动类型
+
+ ];//总
+
+ $order_goods_data = [];//项
+ $write_goods_data = array_merge($this->goods_data, $this->impulse_buy_list);
+ foreach ($write_goods_data as $v) {
+ $order_goods_data[] = [
+ 'member_id' => $data[ 'member_id' ],
+ 'goods_id' => $v[ 'goods_id' ],
+ 'sku_id' => $v[ 'sku_id' ],
+ 'goods_name' => $v[ 'goods' ][ 'goods_name' ],
+ 'sku_name' => $v[ 'sku_name' ],
+ 'goods_image' => $v[ 'goods' ][ 'goods_cover' ],
+ 'sku_image' => $v[ 'sku_image' ],
+ 'price' => $v[ 'price' ],
+ 'original_price' => $v[ 'original_price' ] ?? 0,
+ 'num' => $v[ 'num' ],
+ 'goods_money' => $v[ 'goods_money' ],
+ 'goods_type' => $v[ 'goods' ][ 'goods_type' ],
+ 'order_id' => &$this->order_id,
+ 'discount_money' => $v[ 'discount_money' ] ?? 0,
+ 'status' => OrderGoodsDict::NORMAL,
+ 'extend' => $v[ 'extend' ] ?? '',
+ 'is_gift' => $v[ 'is_gift' ] ?? 0,
+ ];
+ }
+ $create_order_data = array(
+ 'order_data' => $order_data,
+ 'order_goods_data' => $order_goods_data,
+ );
+ return $this->createOrder($create_order_data);
+ }
+
+ /**
+ * 整理
+ * @param array $data
+ * @return void
+ */
+ public function calculate(array $data)
+ {
+ //参数赋值
+ $this->setParam($data);
+ $this->order_key = $this->param[ 'order_key' ] ?? '';
+ $is_need_recalculate = $data[ 'is_need_recalculate' ] ?? 0;
+ if (empty($this->order_key) || $is_need_recalculate == 1) {
+ $this->confirm($this->order_key);
+ }
+ //获取订单数据的缓存
+ $this->getOrderCache($this->order_key . '_basic');
+ //计算优惠和营销
+ $this->calculateDiscount();
+ $this->setOrderCache($this->order_key);
+ //计算运费
+ $this->calculateDelivery();
+ //检测限购
+ $this->checkGoodsLimitBuy();
+
+ //金额格式化
+ $discount_money = $this->moneyFormat($this->basic[ 'discount_money' ] ?? 0);//优惠金额
+ $delivery_money = $this->moneyFormat($this->basic[ 'delivery_money' ] ?? 0);
+ $goods_money = $this->moneyFormat($this->basic[ 'goods_money' ] ?? 0);
+ $order_money = $this->moneyFormat($this->basic[ 'order_money' ] ?? 0);
+
+ $order_money = $this->moneyFormat($this->moneyCalculate($order_money, $delivery_money, $goods_money, -$discount_money));
+ $this->basic[ 'discount_money' ] = $discount_money;
+ $this->basic[ 'delivery_money' ] = $delivery_money;
+ $this->basic[ 'goods_money' ] = $goods_money;
+ //todo 校验控制,不能小于0
+ $order_money = $order_money < 0 ? 0 : $order_money;
+ $this->basic[ 'order_money' ] = $order_money;
+// $this->basic['pay_money'] = $this->basic['pay_money'] ?? $order_money;
+ //订单创建数据写入缓存,并将标识返回给前端
+ $order_cache = get_object_vars($this);
+ unset($order_cache[ 'param' ]);
+ $this->setOrderCache($this->order_key, $order_cache);
+ return $order_cache;
+ }
+
+ /**
+ * 订单确认(基础信息查询并缓存)
+ * @return array|mixed
+ * @throws DataNotFoundException
+ * @throws DbException
+ * @throws ModelNotFoundException
+ */
+ public function confirm($order_key = '')
+ {
+ //查看会员信息
+ $member_id = $this->param[ 'member_id' ];
+ $this->member_id = $member_id;
+ $member_info = ( new CoreMemberService() )->getInfoByMemberId($member_id, 'nickname, headimg, balance, point, member_level,member_label');
+ if (empty($member_info)) throw new CommonException('SHOP_ORDER_BUYER_NOT_FOUND');//无效的账号
+
+ // 查询会员等级信息
+ $member_info['member_level_id'] = $member_info[ 'member_level' ];
+ $member_info[ 'member_level' ] = ( new MemberLevel() )->where([ [ 'level_id', '=', $member_info[ 'member_level' ] ] ])->field('level_id,level_benefits')->findOrEmpty()->toArray();
+
+ //会员账户信息
+ $this->buyer = $member_info;
+
+ $order_config = ( new CoreOrderConfigService() )->getConfig() ?? [];
+ $this->form_id = $order_config[ 'form_id' ];
+
+ //查询商品信息
+ $this->getGoodsData();
+ //配送相关信息
+ $this->getDelivery();
+
+ $order_cache = get_object_vars($this);
+ unset($order_cache[ 'param' ]);
+ unset($order_cache[ 'order_key' ]);
+ if (empty($order_key)) {
+ $order_key = $this->setOrderCache('', $order_cache);
+ }
+ //将基础订单数据单独存放一个缓存
+ $order_basic_key = $order_key . '_basic';
+ $this->setOrderCache($order_basic_key, $order_cache);
+
+ $this->order_key = $order_key;
+ return true;
+ }
+
+ /**
+ * 商品相关数据
+ * @return array
+ * @throws DataNotFoundException
+ * @throws DbException
+ * @throws ModelNotFoundException
+ */
+ public function getGoodsData()
+ {
+ $cart_ids = $this->param[ 'cart_ids' ] ?? [];
+ $this->extend_data = $this->param[ 'extend_data' ] ?? []; //活动扩展数据:[ 'relate_id' => 1, 'activity_type' => 'giftcard' ]
+ if (!empty($cart_ids)) {
+ $this->cart_ids = $cart_ids;
+ //查询购物车
+ $cart = ( new Cart() )->where([ [ 'id', 'in', $cart_ids ] ])->field('goods_id, sku_id, num, market_type, market_type_id')->select();
+ if ($cart->isEmpty()) throw new CommonException('SHOP_ORDER_CARTS_EXPIRE');//无效的数据
+ if ($cart->count() != count($cart_ids)) throw new CommonException('SHOP_ORDER_CARTS_EXPIRE');//无效的商品
+ $sku_data = $cart->toArray();
+ } else {
+ $sku_data = $this->param[ 'sku_data' ] ?? [];
+ if (empty($sku_data)) throw new CommonException('SHOP_ORDER_CARTS_EXPIRE');//无效的数据
+ }
+ $sku_ids = array_column($sku_data, 'sku_id');
+ $sku_condition = array(
+ [ 'sku_id', 'in', $sku_ids ]
+ );
+ $sku_list = ( new GoodsSku() )->where($sku_condition)->with([ 'goods' ])->field('sku_id, sku_name, sku_image, goods_id, price, stock, weight, volume,sku_id, sku_spec_format,member_price, sale_price')->select()->toArray();
+ foreach ($sku_list as &$value){
+ if (empty($value['sku_image']) && isset($value['goods']['goods_cover'])){
+ $value['sku_image'] = $value['goods']['goods_cover'];
+ }
+ }
+ $sku_list = array_column($sku_list, null, 'sku_id');
+ //商品数据 查询商品列表
+ $order_data = [];
+ $goods_list = [];
+ $order_money = $goods_money = $delivery_money = 0;
+ $total_num = 0;
+ $body = '';
+ //订单中包含的商品形式
+ $has_goods_types = [];
+ $activity_type = $this->extend_data[ 'activity_type' ] ?? '';
+ foreach ($sku_data as $v) {
+ $sku_id = $v[ 'sku_id' ];
+ $num = $v[ 'num' ];
+ $total_num += $num;
+ $market_type = $v[ 'market_type' ] ?? '';
+ $market_type_id = $v[ 'market_type_id' ] ?? 0;
+ $sku_info = $sku_list[ $sku_id ] ?? [];
+ if (empty($sku_info)) throw new CommonException('SHOP_ORDER_CARTS_EXPIRE');//无效的商品
+ $sku_info[ 'member_discount' ] = $sku_info[ 'goods' ][ 'member_discount' ] ?? '';
+
+ //商品原价
+ $sku_info[ 'original_price' ] = $sku_info[ 'price' ];
+ //获取活动价格
+ //todo 需仔细看看
+ $sku_info[ 'show_type' ] = 'original_price';
+ $sku_info[ 'active_id' ] = '';
+ $sku_info[ 'member_price' ] = $this->getMemberPrice($sku_info);
+ // $sku_info[ 'price' ] = $sku_info[ 'member_price' ];
+ $goods_active_price_service = (new CoreGoodsActivePriceService());
+ $show_price_data = $goods_active_price_service->getActivePrice($sku_info, $this->member_id);
+ $sku_info[ 'show_type' ] = $show_price_data[ 'show_type' ];
+ $sku_info[ 'price' ] = $show_price_data[ 'show_price' ];
+ $sku_info[ 'active_id' ] = $show_price_data[ 'discount_id' ] ?? '';
+
+
+ //默认金额填充
+ $sku_info[ 'discount_money' ] = 0;
+ $item_goods_type = $sku_info[ 'goods' ][ 'goods_type' ];
+
+ // 商品限购处理
+ if (isset($this->limit_buy[ 'goods_' . $sku_info[ 'goods_id' ] ])) {
+ $this->limit_buy[ 'goods_' . $sku_info[ 'goods_id' ] ][ 'num' ] += $num;
+ } else {
+ $this->limit_buy[ 'goods_' . $sku_info[ 'goods_id' ] ] = [
+ 'goods_id' => $sku_info[ 'goods_id' ],
+ 'goods_name' => $sku_info[ 'goods' ][ 'goods_name' ],
+ 'stock' => $sku_info[ 'goods' ][ 'stock' ],
+ 'num' => $num,
+ 'is_limit' => $sku_info[ 'goods' ][ 'is_limit' ],
+ 'limit_type' => $sku_info[ 'goods' ][ 'limit_type' ],
+ 'max_buy' => $sku_info[ 'goods' ][ 'max_buy' ],
+ 'min_buy' => $sku_info[ 'goods' ][ 'min_buy' ]
+ ];
+ }
+
+ if (!in_array($item_goods_type, $has_goods_types)) $has_goods_types[] = $item_goods_type;
+
+ $sku_info[ 'num' ] = $num;
+ $sku_info[ 'market_type' ] = $market_type;//活动类型
+ $sku_info[ 'market_type_id' ] = $market_type_id;//活动id
+
+ // 计算商品小计
+ $price = $sku_info[ 'price' ];
+ $sku_info[ 'goods_money' ] = $price * $num;
+
+ /****顺手买商品不参与任何其他活动 进行单独计算****/
+ if (!isset($v[ 'impulse_buy_goods_id' ])) {
+ // 活动操纵数据 market_data 活动信息
+ $temp = [];
+ // 过滤活动计算结果,去除空元素
+ $temp_list = array_filter(event('ShopGoodsMarketCalculate', [
+ 'sku_info' => $sku_info,
+ 'sku_data' => $sku_data,
+ 'order_obj' => $this
+ ]));
+
+ // 获取最后一个非空的活动计算结果
+ if (!empty($temp_list)) {
+ $temp = end($temp_list);
+ }
+
+ if (!empty($temp)) {
+ // 更新 SKU 信息
+ $sku_info = $temp[ 'sku_info' ];
+ $sku_info['relate_id'] = $temp[ 'relate_id' ];
+ if (!empty($this->extend_data)) {
+ // 更新扩展数据中的关联 ID 和活动类型
+ $this->extend_data[ 'relate_id' ] = $temp[ 'relate_id' ] ?? 0;
+ $this->extend_data[ 'activity_type' ] = $temp[ 'activity_type' ] ?? '';
+ }
+ if (isset($temp['error']) && !empty($temp['error'])) {
+ if(is_array($temp['error'])){
+ foreach ($temp['error'] as $error){
+ $this->setError($error);
+ }
+ }else{
+ $this->setError($temp['error']);
+ }
+
+ }
+ }
+ }
+
+ $goods_money += $sku_info[ 'goods_money' ];
+ $body = $body ? $body . ( $sku_info[ 'sku_name' ] . $sku_info[ 'goods' ][ 'goods_name' ] ) : ( $sku_info[ 'sku_name' ] . $sku_info[ 'goods' ][ 'goods_name' ] );
+ $goods_list[ $sku_id ] = $sku_info;
+ }
+
+ /*****顺手买开始*****/
+ $impulse_buy_goods = $this->param[ 'impulse_buy_goods' ] ?? [];
+ $impulse_buy_list = [];
+ if (!empty($impulse_buy_goods)) {
+ $temp_list = array_filter(event('ShopImpulseBuyGoodsMarketCalculate', [
+ 'data' => $impulse_buy_goods,
+ 'member_id' => $this->member_id,
+ 'goods_money' => $goods_money,
+ 'order_obj' => $this
+ ]))[ 0 ] ?? [];
+ if (!empty($temp_list)) {
+ $impulse_buy_list = $temp_list[ 'impulse_buy_data' ];
+ $goods_money = $temp_list[ 'goods_money' ];
+ $order_money = $temp_list[ 'order_money' ];
+ $this->basic[ 'order_money' ] += $order_money;
+ }
+ }
+ /*****顺手买结束*****/
+
+ $this->basic[ 'has_goods_types' ] = $has_goods_types;
+ $this->basic[ 'total_num' ] = $total_num;
+ $this->goods_data = $goods_list;
+ $this->impulse_buy_list = $impulse_buy_list;
+ $this->basic[ 'goods_money' ] = $goods_money;
+ $this->basic[ 'body' ] = $body;
+ return $order_data;
+ }
+
+ /**
+ * 获取商品的会员价
+ * @param $sku_info
+ * @return string
+ */
+ public function getMemberPrice($sku_info)
+ {
+ if (empty($sku_info[ 'goods' ][ 'member_discount' ])) {
+ return $sku_info[ 'price' ];
+ }
+
+ // 没有会员等级,排除
+ if (empty($this->buyer[ 'member_level' ])) {
+ return $sku_info[ 'price' ];
+ }
+
+ $price = $sku_info[ 'price' ];
+
+ if ($sku_info[ 'goods' ][ 'member_discount' ] == 'discount') {
+ // 按照会员等级折扣计算
+
+ // 默认按会员享受折扣计算
+ if (isset($this->buyer[ 'member_level' ][ 'level_benefits' ])
+ && isset($this->buyer[ 'member_level' ][ 'level_benefits' ][ 'discount' ])
+ && $this->buyer[ 'member_level' ][ 'level_benefits' ][ 'discount' ][ 'is_use' ]) {
+
+ $price = number_format($price * $this->buyer[ 'member_level' ][ 'level_benefits' ][ 'discount' ][ 'discount' ] / 10, 2, '.', '');
+ }
+
+ } elseif ($sku_info[ 'goods' ][ 'member_discount' ] == 'fixed_price') {
+ // 指定会员价
+ if (!empty($sku_info[ 'member_price' ])) {
+ $sku_info[ 'member_price' ] = json_decode($sku_info[ 'member_price' ], true);
+ if (!empty($sku_info[ 'member_price' ][ 'level_' . $this->buyer[ 'member_level' ][ 'level_id' ] ])) {
+ $member_level_price = $sku_info[ 'member_price' ][ 'level_' . $this->buyer[ 'member_level' ][ 'level_id' ] ];
+ $price = number_format($member_level_price, 2, '.', '');
+ }
+ }
+ }
+
+ return $price;
+ }
+
+}
diff --git a/niucloud/addon/shop/app/service/core/order/CoreOrderCreateTrait.php b/niucloud/addon/shop/app/service/core/order/CoreOrderCreateTrait.php
new file mode 100644
index 000000000..f33198931
--- /dev/null
+++ b/niucloud/addon/shop/app/service/core/order/CoreOrderCreateTrait.php
@@ -0,0 +1,963 @@
+ 0,//优惠金额
+ 'coupon_money' => 0,//优惠券金额
+ 'delivery_money' => 0,
+ 'goods_money' => 0,
+ 'order_money' => 0
+ ];//基本数据处理(整体的数据)
+ public $goods_data = [];//商品数据处理
+ public $impulse_buy_list = [];//顺买商品数据处理
+ public $extend_data = [];//活动数据
+ public $form_data = [];// 万能表单数据
+ public $config = [];//配置集合
+ public $discount = [];//优惠整合
+ public $gift = [];//赠品集合
+ public $gift_goods = [];//赠品商品
+ public $limit_buy = [];//限购
+
+ public $delivery = [];//配送相关
+
+ public $order_id;
+
+ public $invoice = [];
+
+ public $order_key;
+ public $error = [];
+
+ public function createOrder(array $data)
+ {
+ $order_data = $data[ 'order_data' ];
+ $order_goods_data = $data[ 'order_goods_data' ];
+ $order_no = create_no();
+ $order_data[ 'order_no' ] = $order_no;
+ $order_data[ 'order_from' ] = $this->param[ 'order_from' ];//来源渠道
+ $order_data[ 'ip' ] = request()->ip();
+ $main_type = $data[ 'main_type' ] ?? OrderLogDict::MEMBER;
+ $main_id = $data[ 'main_id' ] ?? $order_data[ 'member_id' ];
+
+ // 校验整理发票
+ $this->invoice();
+ Db::startTrans();
+ try {
+ $order = ( new Order() )->create($order_data);
+ $this->order_id = $order[ 'order_id' ];
+ // 添加订单项目表
+ $order_goods_model = new OrderGoods();
+ $order_goods_data = array_map(function($value) {
+ $value[ 'order_goods_money' ] = $this->calculateOrderGoodsMoney($value);
+ return $value;
+ }, $order_goods_data);
+ $order_goods_model->insertAll($order_goods_data);
+
+ // 优惠项
+ $this->useDiscount();
+
+ // 添加万能表单
+ $this->addFormData($this->order_id);
+
+ //处理限时折扣
+ $this->useDiscountActive();
+
+ $order_data[ 'order_id' ] = $this->order_id;
+
+ // 订单创建后事件
+ CoreOrderEventService::orderCreate(['order_id' => $this->order_id, 'order_data' => $order_data, 'order_goods_data' => $order_goods_data, 'cart_ids' => $this->cart_ids, 'basic' => get_object_vars($this), 'main_type' => $main_type, 'main_id' => $main_id, 'time' => time() ]);
+
+ Db::commit();
+
+ // 删除订单缓存
+ $this->delOrderCache($this->order_key);
+
+ // 订单创建后事件
+ CoreOrderEventService::orderCreateAfter([ 'order_id' => $this->order_id, 'order_data' => $order_data, 'order_goods_data' => $order_goods_data, 'cart_ids' => $this->cart_ids, 'basic' => get_object_vars($this), 'main_type' => $main_type, 'main_id' => $main_id, 'time' => time() ]);
+// event('AfterShopOrderCreate', ['order_id' => $this->order_id, 'order_data' => $order_data, 'order_goods_data' => $order_goods_data, 'cart_ids' => $this->cart_ids, 'basic' => get_object_vars($this), 'main_type' => $main_type, 'main_id' => $main_id, 'time' => time()]);
+
+ // 订单金额为0的话,要直接支付
+ if ($order_data[ 'order_money' ] == 0) {
+ ( new CoreOrderPayService() )->pay(['trade_id' => $this->order_id, 'main_type' => $main_type, 'main_id' => $main_id ]);
+ }
+
+ return [
+ 'trade_type' => $order_data[ 'order_type' ],
+ 'order_id' => $this->order_id
+ ];
+
+ } catch (Exception $e) {
+ Db::rollback();
+ throw new CommonException($e->getMessage().$e->getFile().$e->getLine());
+ }
+ }
+
+ /**
+ * 校验库存
+ * @param $order_goods_data
+ * @return void
+ * @throws \think\db\exception\DataNotFoundException
+ * @throws \think\db\exception\DbException
+ * @throws \think\db\exception\ModelNotFoundException
+ */
+ public function checkStock($order_goods_data)
+ {
+ $sku_list = ( new GoodsSku() )->field('sku_id,goods_id,sku_name,stock')->where([ [ 'sku_id', 'in', array_column($order_goods_data, 'sku_id') ] ])
+ ->with([
+ 'goods' => function($query) {
+ $query->field('goods_id,goods_name');
+ }
+ ])->select()->toArray();
+
+ // todo 赠品库存校验
+ $sku_num = [];
+ foreach ($order_goods_data as $v) {
+ if (isset($sku_num[ 'num_' . $v[ 'sku_id' ] ])) {
+ $sku_num[ 'num_' . $v[ 'sku_id' ] ] += $v[ 'num' ];
+ } else {
+ $sku_num[ 'num_' . $v[ 'sku_id' ] ] = $v[ 'num' ];
+ }
+ }
+
+ foreach ($sku_list as $v) {
+ $goods_name = count($sku_list) > 1 ? '“' . $v[ 'goods' ][ 'goods_name' ] . $v[ 'sku_name' ] . '”' : '';
+ if ($v[ 'stock' ] < $sku_num[ 'num_' . $v[ 'sku_id' ] ]) throw new CommonException('商品' . $goods_name . '库存不足');
+ }
+ }
+
+ /**
+ * 发票整理
+ * @return void
+ */
+ public function invoice()
+ {
+ if ($this->config('invoice')) {
+ if (!empty($this->param[ 'invoice' ])) {
+// $invoive_type = $this->param['invoice']['type'] ?? '';
+ $this->invoice[ 'type' ] = $this->param[ 'invoice' ][ 'type' ] ?? '';
+ $this->invoice[ 'name' ] = $this->param[ 'invoice' ][ 'name' ] ?? '';
+ $this->invoice[ 'header_type' ] = $this->param[ 'invoice' ][ 'header_type' ] ?? '';
+ $this->invoice[ 'header_name' ] = $this->param[ 'invoice' ][ 'header_name' ] ?? '';
+ $this->invoice[ 'tax_number' ] = $this->param[ 'invoice' ][ 'tax_number' ] ?? '';
+ $this->invoice[ 'mobile' ] = $this->param[ 'invoice' ][ 'mobile' ] ?? '';
+ $this->invoice[ 'email' ] = $this->param[ 'invoice' ][ 'email' ] ?? '';
+ $this->invoice[ 'telephone' ] = $this->param[ 'invoice' ][ 'telephone' ] ?? '';
+ $this->invoice[ 'address' ] = $this->param[ 'invoice' ][ 'address' ] ?? '';
+ $this->invoice[ 'bank_name' ] = $this->param[ 'invoice' ][ 'bank_name' ] ?? '';
+ $this->invoice[ 'bank_card_number' ] = $this->param[ 'invoice' ][ 'bank_card_number' ] ?? '';
+// $this->invoice['money'] = $this->param['invoice']['money'] ?? '';
+ }
+ }
+
+ }
+
+ /**
+ * 配置设置或查询
+ * @param $key
+ * @return array|mixed
+ */
+ public function config($key)
+ {
+ //查询购物配置
+ $config = $this->config[ $key ] ?? [];
+ if (empty($this->config[ $key ])) {
+ switch ($key) {
+ case 'order'://交易配置
+ $config = ( new CoreOrderConfigService() )->orderClose() ?? [];
+ break;
+ case 'point'://交易配置
+ break;
+ case 'delivery_type':
+ $config = ( new CoreDeliveryService() )->getDeliveryConfig();
+ break;
+ case 'invoice':
+ $config = ( new CoreOrderConfigService() )->invoice() ?? [];
+ break;
+ }
+ $this->config[ $key ] = $config;
+ }
+ return $config;
+ }
+
+ /**
+ * 计算订单项金额
+ * @param $goods
+ * @return mixed
+ */
+ public function calculateOrderGoodsMoney($goods)
+ {
+ $goods_money = $goods[ 'goods_money' ];
+ $discount_money = $goods[ 'discount_money' ] ?? 0;
+ return $goods_money - $discount_money;
+ }
+
+ /**
+ * 优惠写入
+ * @return void
+ */
+ public function useDiscount()
+ {
+ $insert_discount_data = [];
+ $discount_service = new CoreOrderDiscountService();
+ if ($this->discount) {
+ foreach ($this->discount as $k => $v) {
+ $result = array_values(array_filter(event('ShopOrderDiscountCreate', [ 'data' => $v, 'order_object' => $this ])));
+ if (empty($result)) {
+ switch ($k) {
+ case 'coupon':
+ //使用优惠券
+ ( new CoreCouponMemberService() )->use([
+// 'member_id' => $this->member_id,
+ 'id' => $v[ 'discount_type_id' ],
+ 'trade_id' => $this->order_id
+ ]);
+ break;
+ }
+ }
+ if (isset($v[ 'discount_type' ])) {
+ $insert_discount_data[] = [
+ 'type' => $v[ 'type' ],
+ 'num' => $v[ 'num' ],
+ 'money' => $v[ 'money' ],
+ 'discount_type' => $v[ 'discount_type' ],
+ 'discount_type_id' => $v[ 'discount_type_id' ],
+ 'content' => $v[ 'content' ] ?? $v[ 'title' ] ?? "",
+ 'order_id' => $this->order_id,
+ ];
+ } else {
+ foreach ($v as $vv) {
+ if (isset($vv[ 'type' ])){
+ $insert_discount_data[] = [
+ 'type' => $vv[ 'type' ],
+ 'num' => $vv[ 'num' ],
+ 'money' => $vv[ 'money' ],
+ 'discount_type' => $vv[ 'discount_type' ],
+ 'discount_type_id' => $vv[ 'discount_type_id' ],
+ 'content' => $vv[ 'content' ] ?? $vv[ 'title' ] ?? "",
+ 'order_id' => $this->order_id,
+ ];
+ }elsE{
+ foreach ($vv as $vvv) {
+ $insert_discount_data[] = [
+ 'type' => $vvv[ 'type' ],
+ 'num' => $vvv[ 'num' ],
+ 'money' => $vvv[ 'money' ],
+ 'discount_type' => $vvv[ 'discount_type' ],
+ 'discount_type_id' => $vvv[ 'discount_type_id' ],
+ 'content' => $vvv[ 'content' ] ?? $vvv[ 'title' ] ?? "",
+ 'order_id' => $this->order_id,
+ ];
+ }
+ }
+
+ }
+ }
+
+ }
+
+ $discount_service->addAll($insert_discount_data);
+ }
+ return true;
+ }
+
+
+ /**
+ * 获取参数
+ * @param $key
+ * @param $default
+ * @return mixed|string
+ */
+ public function param($key, $default = '')
+ {
+ return $this->param[ $key ] ?? $default;
+ }
+
+ /**
+ * 订单优惠
+ * @return void
+ */
+ public function getDiscount()
+ {
+ //查询积分优惠
+// $this->getPoint();
+ //查询可用优惠券
+// $this->getCoupon();
+ }
+
+ /**
+ * 获取有效的优惠券
+ * @param $data
+ */
+ public function getCoupon($data)
+ {
+ //参数赋值
+ $this->setParam($data);
+ $order_key = $this->param[ 'order_key' ] ?? '';
+ //获取订单数据的缓存
+ $this->getOrderCache($order_key);
+
+ $coupon_list = ( new CoreCouponMemberService() )->getUseCouponListByMemberId($this->member_id);
+ //如果有优惠券
+ if (!empty($coupon_list)) {
+ foreach ($coupon_list as &$v) {
+ $type = (int) $v[ 'type' ];
+ $goods_data = $v[ 'goods' ];
+ $min_condition_money = $v[ 'min_condition_money' ];
+ switch ($type) {
+ case CouponDict::ALL:
+ $v[ 'is_normal' ] = true;
+ //匹配的商品
+ $match_goods_list = $this->goods_data;
+ $match_goods_money = $this->basic[ 'goods_money' ];
+ break;
+ case CouponDict::CATEGORY:
+ $category_ids = array_column($goods_data, 'category_id');
+ //匹配的商品
+ $match_goods_list = [];
+ $match_goods_money = 0;
+ foreach ($this->goods_data as $goods_v) {
+ $item_goods_category = $goods_v[ 'goods' ][ 'goods_category' ];//商品分类数组
+ if (!empty(array_intersect($category_ids, $item_goods_category))) {
+ $match_goods_list[] = $goods_v;
+ $match_goods_money += $goods_v[ 'goods_money' ];
+ }
+ }
+ break;
+ case CouponDict::GOODS:
+ $goods_ids = array_column($goods_data, 'goods_id');
+ //匹配的商品
+ $match_goods_list = [];
+ $match_goods_money = 0;
+ foreach ($this->goods_data as $goods_v) {
+ if (in_array($goods_v[ 'goods_id' ], $goods_ids)) {
+ $match_goods_list[] = $goods_v;
+ $match_goods_money += $goods_v[ 'goods_money' ];
+ }
+ }
+ break;
+ }
+
+ if (empty($match_goods_list)) {
+ $v[ 'is_normal' ] = false;
+ $v[ 'error' ] = get_lang('SHOP_ORDER_COUPON_SUPPORT_GOODS');//没有支持可用的商品
+ } else {
+ if ($match_goods_money < $min_condition_money) {
+ $v[ 'is_normal' ] = false;
+ $v[ 'error' ] = get_lang('SHOP_ORDER_COUPON_NOT_CONDITION');//没有达到商品最低使用条件
+ } else {
+ $v[ 'is_normal' ] = true;
+ }
+ }
+ }
+ }
+ return $coupon_list;
+ }
+
+ /**
+ * 给传参
+ * @param $param
+ * @return true
+ */
+ public function setParam($param)
+ {
+ $this->param = $param;
+ $this->extend_data = $this->param[ 'extend_data' ] ?? [];
+ return true;
+ }
+
+
+ /**
+ * 计算优惠
+ * @return void
+ */
+ public function calculateDiscount()
+ {
+ //查询积分优惠
+// $this->getPoint();
+ //满减送优惠计算
+ $this->calculateManjian();
+ //查询可用优惠券
+ $this->calculateCoupon();
+ }
+
+ /**
+ * 优惠券计算
+ * @return void
+ */
+ public function calculateCoupon()
+ {
+ $coupon_id = $this->param[ 'discount' ][ 'coupon_id' ] ?? 0;//使用优惠券id
+
+ if ($coupon_id > 0) {
+ $coupon_data = ( new CoreCouponMemberService() )->getUseCouponById($coupon_id);
+ if (empty($coupon_data)) throw new CommonException('SHOP_ORDER_COUPON_EXPIRE_OR_NOT_FOUND');//优惠券已使用或不存在
+
+ $time = time();
+ if ($time > strtotime($coupon_data[ 'expire_time' ])) {
+ throw new CommonException('SHOP_ORDER_COUPON_EXPIRE');//优惠券已使用或不存在
+ }
+ $type = (int) $coupon_data[ 'type' ];
+ $goods_data = $coupon_data[ 'goods' ];
+ $min_condition_money = $coupon_data[ 'min_condition_money' ];
+ $match_order_goods_money = 0;
+ switch ($type) {
+ case CouponDict::ALL:
+ //匹配的商品
+ $match_goods_list = $this->goods_data;
+ $match_goods_money = $this->basic[ 'goods_money' ];
+ $match_order_goods_money = $this->basic[ 'goods_money' ] - $this->basic[ 'discount_money' ];
+ break;
+ case CouponDict::CATEGORY:
+ $category_ids = array_column($goods_data, 'category_id');
+ //匹配的商品
+ $match_goods_list = [];
+ $match_goods_money = 0;
+ foreach ($this->goods_data as $goods_v) {
+ $item_goods_category = $goods_v[ 'goods' ][ 'goods_category' ];//商品分类数组
+ if (!empty(array_intersect($category_ids, $item_goods_category))) {
+ $match_goods_list[] = $goods_v;
+ $match_goods_money += $goods_v[ 'goods_money' ];
+ $match_order_goods_money += $this->calculateOrderGoodsMoney($goods_v);
+ }
+ }
+ break;
+ case CouponDict::GOODS:
+ $goods_ids = array_column($goods_data, 'goods_id');
+ //匹配的商品
+ $match_goods_list = [];
+ $match_goods_money = 0;
+ foreach ($this->goods_data as $goods_v) {
+ if (in_array($goods_v[ 'goods_id' ], $goods_ids)) {
+ $match_goods_list[] = $goods_v;
+ $match_goods_money += $goods_v[ 'goods_money' ];
+ $match_order_goods_money += $this->calculateOrderGoodsMoney($goods_v);
+ }
+ }
+
+ break;
+ }
+ if (empty($match_goods_list)) {
+ $this->setError(get_lang('SHOP_ORDER_COUPON_NOT_SUPPORT_GOODS'));//没有支持可用的商品
+ } else {
+ if ($match_goods_money < $min_condition_money) {
+ $this->setError(get_lang('SHOP_ORDER_COUPON_NOT_SUPPORT_MIN_MONEY'));//没有达到商品最低使用条件
+ } else {
+ $coupon_money = $coupon_data[ 'price' ];
+ if ($coupon_money > $match_order_goods_money) {
+ $coupon_money = $match_order_goods_money;
+ }
+ $surplus_money = $coupon_money;
+ $match_goods_list = array_values($match_goods_list);
+ $match_goods_list = array_filter($match_goods_list, function($item) {
+ return ( $item[ 'goods_money' ] - $item[ 'discount_money' ] ) != 0;
+ });
+ $match_count = count($match_goods_list);
+ //根据商品金额计算个订单项享受的优惠
+ foreach ($match_goods_list as $k => $v) {
+ $item_order_goods_money = $this->calculateOrderGoodsMoney($v);
+ $item_sku_id = $v[ 'sku_id' ];
+ if ($k == ( $match_count - 1 )) {
+ $item_coupon_money = $surplus_money;
+ } else {
+ if ($match_order_goods_money == 0 || $coupon_money == 0) {
+ $item_coupon_money = 0;
+ } else {
+ $item_coupon_money = $this->moneyFormat($item_order_goods_money / $match_order_goods_money * $coupon_money);
+ if ($item_coupon_money == 0) {
+ $item_coupon_money = $item_order_goods_money;
+ }
+ if ($item_coupon_money > $surplus_money) {
+ $item_coupon_money = $surplus_money;
+ }
+ }
+ }
+
+ $this->goods_data[ $item_sku_id ][ 'discount_money' ] += $item_coupon_money;
+// $this->goods_data[$item_sku_id]['order_goods_money'] = $this->calculateOrderGoodsMoney($this->goods_data[$item_sku_id]);
+
+ $surplus_money = bcsub($surplus_money, $item_coupon_money, 2);
+ }
+ //优惠累增
+ $this->basic[ 'discount_money' ] += $coupon_money;
+ $this->basic[ 'coupon_money' ] += $coupon_money;
+// $discount_money = $this->basic['discount']['discount_money'];
+ $this->discount[ 'coupon' ] = $this->discountFormat(
+ array_column($match_goods_list, 'sku_id'),
+ OrderDiscountDict::DISCOUNT,
+ 1,
+ $coupon_money,
+ 'coupon',
+ $coupon_id,
+ '',
+ $coupon_data[ 'title' ]
+ );
+ }
+ }
+
+ }
+
+ }
+
+ /**
+ * 优惠项格式
+ * @param $match_goods_ids
+ * @param $type
+ * @param $num
+ * @param $money
+ * @param $discount_type
+ * @param $discount_type_id
+ * @param $content
+ * @return array
+ */
+ public function discountFormat($match_goods_ids, $type, $num, $money, $discount_type, $discount_type_id, $content, $title = '')
+ {
+ return [
+ 'match_goods_ids' => $match_goods_ids,
+ 'type' => $type,
+ 'num' => $num,
+ 'money' => $money,
+ 'discount_type' => $discount_type,
+ 'discount_type_id' => $discount_type_id,
+ 'content' => $content,
+ 'title' => $title
+ ];
+ }
+
+ /**
+ * 获取积分
+ * @return true
+ */
+ public function getPoint()
+ {
+
+ $is_point = $this->param[ 'discount' ][ 'is_point' ] ?? 0;//是否使用积分
+ if ($is_point) {
+ //todo 现在认为积分只能抵扣商品总额(单个商品不设置支持积分)
+ $goods_money = $this->basic[ 'goods_money' ];
+ $member_point = $this->buyer[ 'point' ];//会员积分
+ $point_config = $this->config('config');
+ if ($point_config[ 'status' ]) {//启用
+ $point_money = $member_point * $point_config[ 'rate' ];
+ $point_money = $point_money > $goods_money ? $goods_money : $point_money;
+ $point = round($point_money / $point_config[ 'rate' ]);//todo 积分是否可以为小数
+
+ $this->discount[ 'point' ][ 'point' ] = $point;
+ $this->discount[ 'point' ][ 'point_money' ] = $point_money;
+ }
+ }
+
+ return true;
+ }
+
+ public function usePoint($data)
+ {
+ $member_account = $data[ 'member_account' ];
+ }
+
+ /**
+ * 计算积分
+ * @return void
+ */
+ public function calculatePoint()
+ {
+ }
+
+ /**
+ * 使用优惠券
+ * @param $data
+ * @return void
+ */
+ public function useCoupon($data)
+ {
+
+ }
+
+ /**
+ * 查询订单支持的配送方式
+ * @return void
+ */
+ public function getDelivery()
+ {
+ //先判断商品项中是否存在实物商品
+ $has_goods_types = $this->basic[ 'has_goods_types' ];
+ //存在实物商品查询物流信息
+ if (in_array(GoodsDict::REAL, $has_goods_types)) {
+ //todo 查询启用的配送方式
+ $delivery_type_list = $this->config('delivery_type');
+ foreach ($delivery_type_list as $k => $v) {
+ if ($v[ 'status' ] != 1) {
+ unset($delivery_type_list[ $k ]);
+ }
+ }
+// $delivery_type_list = array_column($delivery_type_list, null, 'key');
+ $this->delivery[ 'delivery_type_list' ] = $delivery_type_list;
+ }
+ return true;
+ }
+
+ /**
+ * 获取和计算配送信息和费用
+ * @return void
+ */
+ public function calculateDelivery()
+ {
+ //配送参数
+ $delivery = $this->param[ 'delivery' ] ?? [];
+ $delivery_type = $delivery[ 'delivery_type' ] ?? '';//配送方式
+ $has_goods_types = $this->basic[ 'has_goods_types' ];
+ //存在实物商品查询物流信息
+ if (in_array(GoodsDict::REAL, $has_goods_types)) {
+ $delivery_type_list = $this->delivery[ 'delivery_type_list' ];
+ if (empty($delivery_type_list)) $this->setError('NOT_CONFIGURED_DELIVERY_TYPE');//商家尚未配置配送方式
+ if ($delivery_type) {
+ //校验是否合法
+ if (empty($delivery_type_list[ $delivery_type ])) throw new CommonException('SHOP_ORDER_PLEASE_SELECT_DELIVERY_TYPE');//配送方式非法
+ } else {
+ //没有选择配送方式的话,默认选中第一个配送方式
+ $default_delivery = reset($delivery_type_list);
+ $delivery_type = $default_delivery ? $default_delivery[ 'key' ] : '';
+ }
+ } else {
+ //如果订单中只有虚拟商品
+ if (in_array(GoodsDict::VIRTUAL, $has_goods_types)) {
+ $delivery_type = OrderDeliveryDict::VIRTUAL;
+ }
+ }
+ if (!$delivery_type) {
+ $this->setError('SHOP_ORDER_PLEASE_SELECT_DELIVERY_TYPE');//没有选中配送方式....
+ } else {
+ $this->delivery[ 'delivery_type' ] = $delivery_type;
+
+ //选中收货地址
+ $this->selectTakeAddress();
+
+ switch ($delivery_type) {
+ case OrderDeliveryDict::EXPRESS://物流
+ CoreExpressService::calculate($this);
+ break;
+ case OrderDeliveryDict::LOCAL_DELIVERY://同城配送
+ CoreLocalDeliveryService::calculate($this);
+ break;
+ case OrderDeliveryDict::STORE://门店自提
+ CoreStoreService::calculate($this);
+ break;
+ }
+
+ if (!empty($this->extend_data) && isset($this->extend_data[ 'delivery_money' ])) {
+ $this->basic[ 'delivery_money' ] = $this->extend_data[ 'delivery_money' ];
+ } else {
+ $this->basic[ 'delivery_money' ] = round($this->basic[ 'delivery_money' ] ?? 0, 2);
+ }
+
+ }
+
+ return true;
+ }
+
+ /**
+ * 选中收货地址
+ * @return void
+ */
+ public function selectTakeAddress()
+ {
+ //定义收货地址
+ $has_goods_types = $this->basic[ 'has_goods_types' ];
+ if (in_array(GoodsDict::REAL, $has_goods_types)) {
+ if ($this->delivery[ 'delivery_type' ] == OrderDeliveryDict::STORE) {
+ if (!empty($this->param[ 'delivery' ][ 'take_store_id' ])) {
+ $this->delivery[ 'take_store' ] = ( new CoreStoreService() )->getInfoById($this->param[ 'delivery' ][ 'take_store_id' ]);
+ }
+ } else {
+ //查询默认收货地址
+ if (!empty($this->param[ 'delivery' ][ 'take_address_id' ])) {
+ $this->delivery[ 'take_address' ] = ( new CoreMemberAddressService() )->getMemberAddressById($this->param[ 'delivery' ][ 'take_address_id' ], $this->member_id);
+ } else {
+ $take_address = ( new CoreMemberAddressService() )->getDefaultAddressByMemberId($this->member_id);
+ if ($this->delivery[ 'delivery_type' ] == OrderDeliveryDict::LOCAL_DELIVERY && empty($take_address[ 'lng' ])) {
+ $take_address = ( new CoreMemberAddressService() )->getLngLatAddressByMemberId($this->member_id);
+ }
+ $this->delivery[ 'take_address' ] = $take_address;
+ }
+
+ if ($this->delivery[ 'delivery_type' ] == OrderDeliveryDict::LOCAL_DELIVERY && !empty($this->delivery[ 'take_address' ]) && empty($this->delivery[ 'take_address' ][ 'lng' ])) {
+ $this->setError('SHOP_ORDER_PLEASE_SELECT_DELIVERY_EMPTY_LNG_LAT');//选中的配送方式没有设置经纬度....
+ }
+ }
+
+ }
+ return true;
+ }
+
+ /**
+ * 检测限购
+ * @return bool
+ */
+ public function checkGoodsLimitBuy()
+ {
+ $error = ( new CoreGoodsLimitBuyService() )->checkGoodsLimitBuy($this->member_id, $this->limit_buy);
+ if (!empty($error)) {
+ $this->setError($error);
+ }
+ return true;
+ }
+
+ /**
+ * 满减送优惠计算
+ * @return void
+ */
+ public function calculateManjian()
+ {
+ ( new CoreManjianService() )->calculate($this);
+ }
+
+ /**
+ * 商品计算运费
+ * @param $goods
+ * @return void
+ */
+ public function getDeliveryMoney($goods, $delivery_type)
+ {
+
+ }
+
+ /**
+ * 存在错误则抛出
+ * @return void
+ */
+ public function checkError()
+ {
+ $error = $this->getError();
+ if ($error) throw new CommonException($error[ 0 ]);
+ }
+
+ /**
+ * 获取错误
+ * @return array|mixed
+ */
+ public function getError()
+ {
+ return $this->error;
+ }
+
+ /**
+ * 定义错误
+ * @param $error
+ * @return void
+ */
+ public function setError($error)
+ {
+ $this->error[] = $error;
+ }
+
+ /**
+ * 获取整合后的数据
+ * @return void
+ */
+ public function getData()
+ {
+
+ }
+
+ /**
+ * 设置订单缓存
+ * @return string
+ * @throws Exception
+ */
+ public function setOrderCache($order_key = '', $order_cache = [])
+ {
+ if (empty($order_key)) {
+ $order_key = create_no('', $this->member_id);
+ }
+ Cache::tag('order_cache')->set($order_key, $order_cache, 300000);
+ return $order_key;
+ }
+
+ /**
+ * 获取订单缓存
+ * @param $order_key
+ * @return void
+ */
+ public function getOrderCache($order_key)
+ {
+
+ $order_cache = Cache::get($order_key, []);
+ if (empty($order_cache))
+ throw new CommonException('SHOP_ORDER_CARTS_EXPIRE');//购物车数据已过期
+ foreach ($order_cache as $k => $v) {
+ $this->$k = $v;
+ }
+
+ return true;
+ }
+
+ /**
+ * 清除订单缓存
+ * @param $order_key
+ * @return true
+ */
+ public function delOrderCache($order_key = '')
+ {
+ Cache::delete($order_key);
+ return true;
+ }
+
+ /**
+ * 校验抵扣项是否可用
+ * @return void
+ */
+ public function checkDiscount()
+ {
+
+ }
+
+ /**
+ * 比例(向下取整)
+ * @param $rate
+ * @return float|int
+ */
+ public function rateFormat($rate)
+ {
+ return floor(strval(( $rate ) * 100)) / 100;
+ }
+
+ /**
+ * 金额计算
+ * @return void
+ */
+ public function moneyCalculate()
+ {
+ $args = func_get_args();
+ $money = 0;
+ foreach ($args as $v) {
+ $money += $v * 100;
+ }
+ return $money / 100;
+ }
+
+ /**
+ * 金额格式化
+ * @param $money
+ * @return float|int
+ */
+ public function moneyFormat($money)
+ {
+
+ return floor(strval(( $money ) * 100)) / 100;
+ }
+
+ /**
+ * 添加万能表单数据
+ * @param $order_id
+ */
+ public function addFormData($order_id)
+ {
+ if (!empty($this->form_data)) {
+ $diy_form_service = new CoreDiyFormRecordsService();
+ $order_form = $this->form_data[ 'order' ] ?? [];
+ if (!empty($order_form)) {
+ $order_form[ 'member_id' ] = $this->member_id;
+ $order_form[ 'relate_id' ] = $order_id;
+ $form_record_id = $diy_form_service->add($order_form);
+ ( new Order() )->where([
+ [ 'order_id', '=', $order_id ]
+ ])->update([ 'form_record_id' => $form_record_id ]);
+ }
+
+ $goods_form = $this->form_data[ 'goods' ] ?? [];
+ if (!empty($goods_form)) {
+ $order_goods_model = new OrderGoods();
+ $order_goods_list = $data = $order_goods_model->where([ [ 'order_id', '=', $order_id ] ])
+ ->field('order_goods_id,sku_id')->select()->toArray();
+ foreach ($goods_form as $k => $v) {
+ foreach ($order_goods_list as $ck => $cv) {
+ if ($cv[ 'sku_id' ] == $k) {
+ $v[ 'member_id' ] = $this->member_id;
+ $v[ 'relate_id' ] = $cv[ 'order_goods_id' ];
+ $form_record_id = $diy_form_service->add($v);
+ $order_goods_model->where([
+ [ 'order_id', '=', $order_id ],
+ [ 'order_goods_id', '=', $cv[ 'order_goods_id' ] ]
+ ])->update([ 'form_record_id' => $form_record_id ]);
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * 处理限时折扣
+ */
+ public function useDiscountActive()
+ {
+ if (!empty($this->goods_data)){
+ $insert_discount_data = [];
+ $discount_service = new CoreOrderDiscountService();
+ foreach ($this->goods_data as $k => $v) {
+ //排除赠品
+ if (empty($v['is_gift']) && isset($v['show_type']) && $v['show_type'] == GoodsDict::DISCOUNT_PRICE) {
+ $insert_discount_data[] = [
+ 'order_id' => $this->order_id,
+ 'member_id' => $this->member_id,
+ 'goods_id' => $v['goods_id'],
+ 'sku_id' => $v['sku_id'],
+ 'type' => 'discount',
+ 'num' => $v[ 'num' ],
+ 'money' => $v[ 'goods_money' ],
+ 'discount_type' => ActiveDict::DISCOUNT,
+ 'discount_type_id' => $v[ 'active_id' ],
+ 'content' => "",
+ ];
+ }
+ }
+
+ $discount_service->addAll($insert_discount_data);
+ }
+ return true;
+ }
+}
diff --git a/niucloud/addon/shop/app/service/core/order/CoreOrderDeliveryService.php b/niucloud/addon/shop/app/service/core/order/CoreOrderDeliveryService.php
new file mode 100644
index 000000000..b2de1b6a3
--- /dev/null
+++ b/niucloud/addon/shop/app/service/core/order/CoreOrderDeliveryService.php
@@ -0,0 +1,683 @@
+model = new Order();
+ }
+
+ /**
+ * 发货入口
+ * @param $data
+ * @return true
+ * @throws DataNotFoundException
+ * @throws DbException
+ * @throws ModelNotFoundException
+ */
+ public function delivery($data)
+ {
+ $order_id = $data['order_id'];
+ $order_goods_ids = $data['order_goods_ids'];//订单项id
+ //查询订单
+ $where = array(
+ ['order_id', '=', $order_id]
+ );
+ $order = $this->model->where($where)->findOrEmpty();
+ if ($order->isEmpty()) throw new CommonException('SHOP_ORDER_NOT_FOUND');//订单不存在
+
+ if ($order['status'] != OrderDict::WAIT_DELIVERY && empty($data['delivery_ids'])) {
+ throw new CommonException('SHOP_ONLY_WAIT_DELIVERY_CAN_BE_DELIVERY');//只有待收货的订单才可以收货
+ }
+
+ //赠品跟随下单商品一起发货
+ $gift_order_goods_ids = (new OrderGoods())->where([
+ ['order_id', '=', $order_id],
+ ['is_gift', '=', 1],
+ ['status', '=', OrderGoodsDict::NORMAL],
+ ['delivery_status', '=', OrderDeliveryDict::WAIT_DELIVERY]
+ ])->column('order_goods_id');
+ if (!empty($gift_order_goods_ids)) {
+ $order_goods_ids = array_merge($order_goods_ids, $gift_order_goods_ids);
+ $data['order_goods_ids'] = $order_goods_ids;
+ }
+
+ //配送
+ $delivery_type = $data['delivery_type'];
+ if (!empty($data['delivery_ids'])) {
+ $sub_where = [
+ 'delivery_status', '=', OrderDeliveryDict::DELIVERY_FINISH
+ ];
+ } else {
+ $sub_where = [
+ 'delivery_status', '=', OrderDeliveryDict::WAIT_DELIVERY
+ ];
+ }
+ //不用的订单项针对的发货方式不同
+ $order_goods_where = [
+ [
+ 'order_id', '=', $order_id
+ ],
+ [
+ 'order_goods_id', 'in', $order_goods_ids
+ ],
+ [
+ 'status', '=', OrderGoodsDict::NORMAL
+ ],
+ $sub_where
+ ];
+ $order_goods_data = (new OrderGoods())->with(['sku' => function ($q) {
+ $q->field('sku_id,weight');
+ }, 'goods' => function ($q) {
+ $q->field('goods_id,unit');
+ }])->where($order_goods_where)->select();
+ if ($order_goods_data->count() != count($order_goods_ids)) throw new CommonException('SHOP_ORDER_DELIVERY_NOT_ALLOW_REFUND_OR_DELIVERY_FINISH');//存在退款的商品不能发货
+ $has_goods_type_array = [];
+ foreach ($order_goods_data as $v) {
+
+ if ($v['is_gift'] == 1) continue;
+
+ if (!in_array($v['goods_type'], $has_goods_type_array)) {
+ $has_goods_type_array[] = $v['goods_type'];
+ }
+ }
+ if (count($has_goods_type_array) != 1) throw new CommonException('SHOP_ORDER_DELIVERY_ALLOW_ONE_GOODS_TYPE');
+ //一次发货只能发送一种商品类型的订单项
+ $goods_type = $has_goods_type_array[0];
+
+ $delivery_param = [
+ 'order_data' => $order,
+ 'order_goods_data' => $order_goods_data,
+ 'param' => $data
+ ];
+ Db::startTrans();
+ try {
+ switch ($goods_type) {
+ case GoodsDict::VIRTUAL://只要有虚拟商品,就可以使用虚拟发货
+ if ($delivery_type != OrderDeliveryDict::VIRTUAL) throw new CommonException('SHOP_ORDER_DELIVERY_VIRTUAL_ALLOW_VIRTUAL_DELIVERY');//虚拟商品只支持虚拟发货
+ //虚拟发货
+ $this->virtual($delivery_param);
+ break;
+ case GoodsDict::REAL:
+ if (in_array($delivery_type, OrderDeliveryDict::getChildType($order['delivery_type']))) throw new CommonException('SHOP_ORDER_DELIVERY_TYPE_NOT_ORDER_DELIVERY_TYPE');//不支持的配送方式
+ switch ($order['delivery_type']) {
+ case OrderDeliveryDict::EXPRESS://快递
+ $this->express($delivery_param);
+ break;
+ case OrderDeliveryDict::LOCAL_DELIVERY://配送
+ $this->localDelivery($delivery_param);
+ break;
+ case OrderDeliveryDict::STORE://自提
+ $this->store($delivery_param);
+ break;
+ }
+ break;
+
+ //todo 可以扩展新的商品形式
+ }
+ //校验是否全部发放完毕
+ $this->checkFinish($data);
+ Db::commit();
+ return true;
+
+ } catch (AdminException $exception) {
+ Db::rollback();
+ throw new AdminException($exception->getMessage());
+ }
+
+
+ }
+
+ /**
+ * 虚拟发货
+ * @param $data
+ * @return void
+ */
+ public function virtual($data)
+ {
+ $order_data = $data['order_data'];
+ $order_goods_data = $data['order_goods_data'];
+ $param = $data['param'];
+ $delivery_type = $param['delivery_type'];
+ $delivery_ids = $param['delivery_ids'] ?? [];
+ $insert_data = [
+ 'delivery_ids' => $delivery_ids,
+ 'order_id' => $order_data['order_id'],
+ 'delivery_type' => $order_data['delivery_type'],
+ 'sub_delivery_type' => $delivery_type,
+ 'remark' => $param['remark'] ?? '',
+ ];
+ $delivery_id = $this->package($insert_data);
+ if (empty($delivery_ids)) {
+ //todo 甚至可自动收货
+ $order_goods_data->update([
+ 'delivery_status' => OrderDeliveryDict::DELIVERY_FINISH,
+ 'delivery_id' => $delivery_id
+ ]);
+ //todo 实际调用虚拟配送的操作(类似生成核销码.....)
+ $goods_ids = array_column($order_goods_data->toArray(), 'goods_id');
+ $temp_goods_list = (new Goods())->where([['goods_id', 'in', $goods_ids]])->column('*', 'goods_id');
+ foreach ($order_goods_data as $v) {
+ $temp_goods = $temp_goods_list[$v['goods_id']];
+ $virtual_receive_type = $temp_goods['virtual_receive_type'];
+ //如果需要核销,则生成核销码
+ if ($virtual_receive_type == 'verify') {//生成核销码
+ //待核销(todo 可能设置待核销状态)
+ if ($temp_goods['virtual_verify_type'] == 0) {
+ $expire_time = 0;
+ } else if ($temp_goods['virtual_verify_type'] == 1) {
+ $expire_time = time() + 86400 * $temp_goods['virtual_indate'];
+ } else {
+ $expire_time = $temp_goods['virtual_indate'];
+ }
+ //设置虚拟商品的核销有效期
+ $order_goods_data->update([
+ 'verify_expire_time' => $expire_time,
+ 'is_verify' => 1,
+ ]);
+// (new CoreVerifyService())->create('virtual_verify', ['goods_id' => $v['goods_id'], 'sku_id' => $v['sku_id'], 'order_goods_id' => $v['order_goods_id']]);
+ } else if ($virtual_receive_type == 'auto') {//todo 自动收货 (订单发货后,校验订单项是否全部收货,如果已全部收货,订单就只接完成)
+ (new CoreOrderFinishService())->orderGoodsTake([
+ 'order_id' => $order_data['order_id'],
+ 'order_goods_ids' => [$v['order_goods_id']]
+ ]);
+ }
+ }
+ }
+
+
+ return true;
+ }
+
+ /**
+ * 订单配送包裹(order_delivery)
+ * @param $data
+ * @return mixed
+ */
+ public function package($data)
+ {
+ if (isset($data['delivery_ids']) && !empty($data['delivery_ids'])) {
+ $delivery_ids = $data['delivery_ids'];
+ unset($data['delivery_ids']);
+ $delivery = (new OrderDelivery())->whereIn('id', $delivery_ids)->update($data);
+ } else {
+ $delivery = (new OrderDelivery())->create($data);
+ }
+ return $delivery->id ?? 0;
+ }
+
+ /**
+ * 物流发货
+ * @param $data
+ * @return true
+ */
+ public function express($data)
+ {
+
+ $order_data = $data['order_data'];
+ $order_goods_data = $data['order_goods_data'];
+ $param = $data['param'];
+ $delivery_type = $param['delivery_type'];
+ $order_goods_ids = $param['order_goods_ids']; // 订单项id
+ $delivery_way = $param['delivery_way']; // 发货方式,manual_write:手动填写,electronic_sheet:电子面单
+ $electronic_sheet_id = $param['electronic_sheet_id']; // 电子面单模板
+ $delivery_ids = $param['delivery_ids'] ?? [];
+
+ $insert_data = array(
+ 'delivery_ids' => $delivery_ids,
+ 'order_id' => $order_data['order_id'],
+ 'delivery_type' => $order_data['delivery_type'],
+ 'sub_delivery_type' => $delivery_type,
+ 'express_company_id' => $param['express_company_id'],
+ 'express_number' => $param['express_number'],
+ 'remark' => $param['remark'],
+ );
+ if (empty($delivery_ids)) {
+ // 手动填写
+ if ($delivery_way == 'manual_write') {
+ if (!empty($param['express_number'])) {
+ $express_number_count = (new OrderDelivery())->where([
+ ['order_id', '=', $order_data['order_id']],
+ ['express_number', '=', $param['express_number']]
+ ])->count();
+ if ($express_number_count > 0) throw new CommonException('SHOP_ORDER_DELIVERY_EXPRESS_NUMBER_EXITS');//物流单号不能重复
+ }
+ } elseif ($delivery_way == 'electronic_sheet') {
+ if ($delivery_type == OrderDeliveryDict::EXPRESS) {
+ // 电子面单
+ $electronic_sheet_result = (new CoreElectronicSheetService())->printElectronicSheetByDelivery([
+ 'order_id' => $order_data['order_id'],
+ 'electronic_sheet_id' => $electronic_sheet_id,
+ 'order_goods_data' => $order_goods_data->toArray()
+ ]);
+ if ($electronic_sheet_result['success']) {
+ $insert_data['express_number'] = $electronic_sheet_result['order_info']['LogisticCode']; // 获取电子面单返回的快递单号
+ } else {
+ throw new CommonException($electronic_sheet_result['reason']);
+ }
+ }
+ }
+
+ }
+ $delivery_id = $this->package($insert_data);
+ if (empty($delivery_ids)) {
+ $order_goods_data->update([
+ 'delivery_status' => OrderDeliveryDict::DELIVERY_FINISH,
+ 'delivery_id' => $delivery_id
+ ]);
+ }
+
+
+ return true;
+ }
+
+ /**
+ * 同城配送
+ * @param $data
+ * @return true
+ */
+ public function localDelivery($data)
+ {
+ $order_data = $data['order_data'];
+ $order_goods_data = $data['order_goods_data'];
+ $param = $data['param'];
+ $delivery_type = $param['delivery_type'];
+ $local = (new Local())->where([['local_id', '>', 0 ]])->field('fee_type,base_dist,base_price,grad_dist,grad_price,weight_start,weight_unit,weight_price,delivery_type,area,center')->findOrEmpty()->toArray();
+ //若使用的是第三方配送
+ if (in_array(DeliveryLocalDict::DELIVERY_TYPE_THIRD, $local['delivery_type'])) {
+ $third_party_config = (new CoreLocalDeliveryService())->getConfig();
+ $third_delivery = $third_party_config['default'] ?? '';
+ $loader = new ThirdDeliveryLoader($third_delivery, $third_party_config[$third_delivery]);
+ //三方配送下单
+ $loader->createOrder($data);
+ }
+ $insert_data = array(
+ 'delivery_ids' => $param['delivery_ids'] ?? [],
+ 'order_id' => $order_data['order_id'],
+ 'delivery_type' => $order_data['delivery_type'],
+ 'sub_delivery_type' => $delivery_type,
+ 'local_deliver_id' => $param['local_deliver_id'],
+ 'remark' => $param['remark'],
+ 'third_delivery' => $third_delivery ?? "",
+ );
+ $delivery_id = $this->package($insert_data);
+ $delivery_ids = $param['delivery_ids'];
+ if (empty($delivery_ids)) {
+ $order_goods_data->update([
+ 'delivery_status' => OrderDeliveryDict::DELIVERY_FINISH,
+ 'delivery_id' => $delivery_id
+ ]);
+ }
+ return true;
+ }
+
+ /**
+ * 门店自提
+ * @param $data
+ * @return true
+ */
+ public function store($data)
+ {
+ $order_data = $data['order_data'];
+ $order_goods_data = $data['order_goods_data'];
+ $param = $data['param'];
+ $delivery_type = $param['delivery_type'];
+ $delivery_ids = $param['delivery_ids'] ?? [];
+ $insert_data = array(
+ 'delivery_ids' => $delivery_ids,
+ 'order_id' => $order_data['order_id'],
+ 'delivery_type' => $order_data['delivery_type'],
+ 'sub_delivery_type' => $delivery_type,
+ 'remark' => $param['remark'],
+ );
+ $delivery_id = $this->package($insert_data);
+ if (empty($delivery_ids)) {
+ $order_goods_data->update([
+ 'delivery_status' => OrderDeliveryDict::DELIVERY_FINISH,
+ 'delivery_id' => $delivery_id
+ ]);
+ }
+ return true;
+ }
+
+ /**
+ * 校验订单下的订单项是否全部发货
+ * @param $data
+ * @return void
+ */
+ public function checkFinish($data)
+ {
+ $order_id = $data['order_id'];
+ //校验订单下的有效的订单项是否全部发货完毕
+ $where = array(
+ [
+ 'delivery_status', '=', OrderDeliveryDict::WAIT_DELIVERY
+ ],
+ [
+ 'order_id', '=', $order_id
+ ],
+ [
+ 'status', '<>', OrderGoodsDict::REFUND_FINISH,//不包含退款完毕的
+ ]
+ );
+ $order_goods_count = (new OrderGoods())->where($where)->count();
+ $where_delivery = array(
+ [
+ 'delivery_status', 'in', [OrderDeliveryDict::DELIVERY_FINISH, OrderDeliveryDict::TAKED]
+ ],
+ [
+ 'order_id', '=', $order_id
+ ],
+ [
+ 'status', '<>', OrderGoodsDict::REFUND_FINISH,//不包含退款完毕的
+ ]
+ );
+ $order_goods_delivery_count = (new OrderGoods())->where($where_delivery)->count();
+ //完成
+ if ($order_goods_count == 0 && $order_goods_delivery_count > 0) {
+ $this->finish($data);
+ }
+ return true;
+ }
+
+ /**
+ * 发货完成
+ * @param $data
+ * @return void
+ */
+ public function finish($data)
+ {
+ $order_id = $data['order_id'];
+ //查询订单
+ if (!empty($data['delivery_ids'])) {
+ $sub_where = ['status', '=', OrderDict::REFUND_FINISH];
+ } else {
+ $sub_where = ['status', '=', OrderDict::WAIT_DELIVERY];
+ }
+ $where = array(
+ ['order_id', '=', $order_id],
+ $sub_where
+ );
+ $order = $this->model->where($where)->findOrEmpty();
+ if ($order->isEmpty()) throw new CommonException('SHOP_ORDER_NOT_FOUND');//订单不存在
+
+ $order_data = array(
+ 'delivery_time' => time(),
+ 'status' => OrderDict::WAIT_TAKE,
+ 'timeout' => 0
+ );
+ $order->save($order_data);
+ //订单发货后操作
+ $data['order_data'] = $order->toArray();
+ event('AfterShopOrderDelivery', $data);
+ //订单发货操作
+ CoreOrderEventService::orderDelivery($data);
+ //订单发货后操作
+// CoreOrderEventService::orderDeliveryAfter($data); // 注释是为了解决小程序发货问题
+
+ //如果有且只有一个虚拟商品并且已经收货,则订单完成
+ $order_goods_list = (new OrderGoods())->where([
+ ['order_id', '=', $order_id],
+ ])->select()->toArray();
+ if (count($order_goods_list) == 1) {
+ $first_order_goods = $order_goods_list[0];
+ if ($first_order_goods['goods_type'] == GoodsDict::VIRTUAL && $first_order_goods['delivery_status'] == OrderDeliveryDict::TAKED) {
+ (new CoreOrderFinishService())->finish(['order_id' => $order_id]);
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * 微信小程序 发货信息录入接口
+ * @param $params
+ * @return string
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
+ */
+ public function orderShippingUploadShippingInfo($params)
+ {
+ try {
+
+ $order_id = $params['order_id'];
+
+ //查询订单
+ $where = array(
+ ['order_id', '=', $order_id]
+ );
+ $order_data = $this->model->where($where)->findOrEmpty();
+
+ //订单不存在
+ if ($order_data->isEmpty()) {
+ return '';
+ }
+
+ //不用的订单项针对的发货方式不同
+ $order_goods_where = [
+ ['order_id', '=', $order_id],
+ ['status', '=', OrderGoodsDict::NORMAL]
+ ];
+
+ $order_goods_data = (new OrderGoods())->where($order_goods_where)->select();
+
+ if ($order_goods_data->count() == 0) {
+ return '';
+ }
+
+ $pay_model = new Pay();
+ $where = array(
+ ['out_trade_no', '=', $order_data['out_trade_no']]
+ );
+ $pay_info = $pay_model->where($where)->field('id,type')->findOrEmpty()->toArray();
+
+ if (empty($pay_info)) {
+ return '';
+ }
+
+ // 订单未使用微信支付,无须处理
+ if ($pay_info['type'] != PayDict::WECHATPAY) {
+ return '订单未使用微信支付';
+ }
+
+ $weapp_delivery_service = new CoreWeappDeliveryService();
+
+ // 检测微信小程序是否已开通发货信息管理服务
+ $is_trade_managed = $weapp_delivery_service->isTradeManaged();
+
+ if (empty($is_trade_managed['is_trade_managed'])) {
+ return '发货信息录入接口,报错:' . $is_trade_managed["errmsg"];
+ }
+
+ // 设置消息跳转路径设置接口
+ $result_jump_path = $weapp_delivery_service->setMsgJumpPath( 'shop_order');
+ if ($result_jump_path['errcode'] != 0) {
+ return '设置消息跳转路径设置接口,报错:' . $result_jump_path["errmsg"];
+ }
+
+ $logistics_type = 1; // 物流模式,发货方式枚举值:1、实体物流配送采用快递公司进行实体物流配送形式 2、同城配送 3、虚拟商品,虚拟商品,例如话费充值,点卡等,无实体配送形式 4、用户自提
+
+ if ($order_data['delivery_type'] == OrderDeliveryDict::EXPRESS) {
+
+ // 1、实体物流配送采用快递公司进行实体物流配送形式
+ $logistics_type = 1;
+
+ } else if ($order_data['delivery_type'] == OrderDeliveryDict::STORE) {
+
+ // 门店自提
+ $logistics_type = 4;
+
+ } else if ($order_data['delivery_type'] == OrderDeliveryDict::LOCAL_DELIVERY) {
+
+ // 同城配送
+ $logistics_type = 2;
+
+ } else if ($order_data['delivery_type'] == OrderDeliveryDict::VIRTUAL) {
+
+ // 虚拟商品,例如话费充值,点卡等,无实体配送形式
+ $logistics_type = 3;
+
+ }
+
+ $order_goods_list = $order_goods_data;
+
+ $shipping_list = [];
+ $first_shipping_info = [];
+
+ // 获取物流公司
+ $delivery_list = [];
+
+ $delivery_mode = 1; // 发货模式,发货模式枚举值:1、UNIFIED_DELIVERY(统一发货)2、SPLIT_DELIVERY(分拆发货) 示例值: UNIFIED_DELIVERY
+ if ($logistics_type == 1) {
+ $delivery_mode = count($order_goods_list) == 1 ? 1 : 2;
+ $result_delivery_list = $weapp_delivery_service->getDeliveryList();
+ if ($result_delivery_list['errcode'] == 0 && !empty($result_delivery_list['delivery_list'])) {
+ $delivery_list = $result_delivery_list['delivery_list'];
+ }
+
+ }
+
+ // 查询商家默认发货地址
+ $shop_address_field = 'contact_name,mobile,province_id,city_id,district_id,address,full_address,lat,lng';
+ $shop_address = (new ShopAddress())->where([['is_default_delivery', '=', 1]])->field($shop_address_field)->findOrEmpty()->toArray();
+
+ foreach ($order_goods_list as $k => $v) {
+
+ // 一笔支付单最多分拆成 10 个包裹
+ if ($k == 9) {
+ break;
+ }
+
+ $express_company = ''; // 物流公司编码,快递公司ID,参见「查询物流公司编码列表」,物流快递发货时必填, 示例值: DHL 字符字节限制: [1, 128]
+ $tracking_no = ''; // 物流单号,物流快递发货时必填,示例值: 323244567777 字符字节限制: [1, 128]
+
+ if ($logistics_type == 1) {
+
+ $field = 'id, order_id, delivery_type, sub_delivery_type, express_company_id,express_number';
+ $info = (new OrderDelivery())->where([['id', '=', $v['delivery_id']]])->with([
+ 'company' => function ($query) {
+ $query->field('company_id, company_name, express_no');
+ }
+ ])->field($field)->findOrEmpty()->toArray();
+
+ if (!empty($info) && $info['express_company_id'] && !empty($delivery_list)) {
+ $tracking_no = $info['express_number'];
+ $index = array_search($info['company']['express_no'], array_column($delivery_list, 'delivery_id'));
+ if ($index !== false && isset($delivery_list[$index])) {
+ $express_company = $delivery_list[$index]['delivery_id'];
+ }
+ if (empty($express_company)) {
+ return '物流公司不支持,请更换其他物流公司';
+ }
+ } else {
+ $logistics_type = 2; // 无需物流的情况,无实体配送形式
+ $delivery_mode = 1; // 统一发货
+ }
+
+ }
+
+ $item = [
+ 'tracking_no' => $tracking_no, // 物流单号,物流快递发货时必填,示例值: 323244567777 字符字节限制: [1, 128]
+ 'express_company' => $express_company, // 物流公司编码,快递公司ID,参见「查询物流公司编码列表」,物流快递发货时必填, 示例值: DHL 字符字节限制: [1, 128]
+ 'item_desc' => str_sub($v['goods_name'] . $v['sku_name'], 90) . '*' . $v['num'], // 商品信息,例如:微信红包抱枕*1个,限120个字以内
+ 'contact' => [
+ 'consignor_contact' => '',
+ 'receiver_contact' => ''
+ ]
+ ];
+
+ // 寄件人联系方式,寄件人联系方式,采用掩码传输,最后4位数字不能打掩码 示例值: `189****1234, 021-****1234, ****1234, 0**2-***1234, 0**2-******23-10, ****123-8008` 值限制: 0 ≤ value ≤ 1024
+ if (!empty($shop_address['mobile'])) {
+ $item['contact']['consignor_contact'] = substr($shop_address['mobile'], 0, 3) . '****' . substr($shop_address['mobile'], 7);
+ }
+
+ // 收件人联系方式,收件人联系方式为,采用掩码传输,最后4位数字不能打掩码 示例值: `189****1234, 021-****1234, ****1234, 0**2-***1234, 0**2-******23-10, ****123-8008` 值限制: 0 ≤ value ≤ 1024
+ if (!empty($order_data['taker_mobile'])) {
+ $item['contact']['receiver_contact'] = substr($order_data['taker_mobile'], 0, 3) . '****' . substr($order_data['taker_mobile'], 7);
+ }
+
+ $shipping_list[] = $item;
+ if ($k == 0) {
+ $first_shipping_info = $item;
+ }
+ }
+
+ // 统一发货,只能有一个物流信息,拼装商品信息
+ if ($delivery_mode == 1) {
+ if (count($shipping_list) > 1) {
+ foreach ($shipping_list as $k => $v) {
+ if ($k > 0) {
+ $first_shipping_info['item_desc'] .= ',' . $v['item_desc'];
+ }
+ }
+ }
+ $first_shipping_info['item_desc'] = str_sub($first_shipping_info['item_desc'], 90);
+ }
+
+ // 分拆发货模式时必填,用于标识分拆发货模式下是否已全部发货完成,只有全部发货完成的情况下才会向用户推送发货完成通知。示例值: true/false
+ $is_all_delivered = false;
+ if ($delivery_mode == 2) {
+ $is_all_delivered = true;
+ }
+
+ $member_info = (new Member())->where([ ['member_id', '=', $order_data['member_id']]])->field('weapp_openid')->findOrEmpty()->toArray();
+
+ $data = [
+ 'out_trade_no' => $order_data['out_trade_no'],
+ 'logistics_type' => $logistics_type, // 物流模式,发货方式枚举值:1、实体物流配送采用快递公司进行实体物流配送形式 2、同城配送 3、虚拟商品,虚拟商品,例如话费充值,点卡等,无实体配送形式 4、用户自提
+ 'delivery_mode' => $delivery_mode, // 发货模式,发货模式枚举值:1、UNIFIED_DELIVERY(统一发货)2、SPLIT_DELIVERY(分拆发货) 示例值: UNIFIED_DELIVERY
+ // 同城配送没有物流信息,只能传一个订单
+ 'shipping_list' => $delivery_mode == 1 ? [$first_shipping_info] : $shipping_list, // 物流信息列表,发货物流单列表,支持统一发货(单个物流单)和分拆发货(多个物流单)两种模式,多重性: [1, 10]
+ 'weapp_openid' => $member_info['weapp_openid'], // 用户标识,用户在小程序appid下的唯一标识。 下单前需获取到用户的Openid 示例值: oUpF8uMuAJO_M2pxb1Q9zNjWeS6o 字符字节限制: [1, 128]
+ 'is_all_delivered' => $is_all_delivered
+ ];
+
+ $weapp_delivery_service->uploadShippingInfo( $data);
+ } catch (\Exception $e) {
+ Log::write('商城订单发货失败' . $e->getMessage() . $e->getFile() . $e->getLine());
+ }
+ }
+
+}
diff --git a/niucloud/addon/shop/app/service/core/order/CoreOrderDiscountService.php b/niucloud/addon/shop/app/service/core/order/CoreOrderDiscountService.php
new file mode 100644
index 000000000..6f483f808
--- /dev/null
+++ b/niucloud/addon/shop/app/service/core/order/CoreOrderDiscountService.php
@@ -0,0 +1,42 @@
+model = new OrderDiscounts();
+ }
+
+
+ /**
+ * 订单优惠
+ * @param array $data
+ * @return true
+ */
+ public function addAll(array $data)
+ {
+ $this->model->insertAll($data);
+ return true;
+ }
+
+
+}
diff --git a/niucloud/addon/shop/app/service/core/order/CoreOrderEditPriceService.php b/niucloud/addon/shop/app/service/core/order/CoreOrderEditPriceService.php
new file mode 100644
index 000000000..899b6c726
--- /dev/null
+++ b/niucloud/addon/shop/app/service/core/order/CoreOrderEditPriceService.php
@@ -0,0 +1,156 @@
+model = new Order();
+ }
+
+
+ /**
+ * 订单完成
+ * @param array $data
+ * @return true
+ * @throws DbException
+ */
+ public function finish(array $data)
+ {
+ $order_id = $data[ 'order_id' ];
+
+ //查询订单
+ $where = array (
+ [ 'order_id', '=', $order_id ],
+ );
+ $order = $this->model->where($where)->findOrEmpty()->toArray();
+ if (empty($order)) throw new CommonException('SHOP_ORDER_NOT_FOUND');//订单不存在
+// if ($order[ 'status' ] != OrderDict::WAIT_TAKE) throw new CommonException('SHOP_ONLY_WAIT_TAKE_CAN_BE_TAKE');//只有待收货的订单才可以收货
+
+ //存在退款中的订单项,订单就不可以收货
+ $refunding_order_goods_count = ( new OrderGoods() )->where([
+ [ 'order_id', '=', $order_id ],
+ [ 'status', '=', OrderGoodsDict::REFUNDING ]
+ ])->count();
+ if ($refunding_order_goods_count > 0) throw new CommonException('SHOP_ORDER_HAS_REFUNDING_NOT_ALLOW_FINISH');//是否存在退款中的订单项
+ $update_data = array (
+ 'status' => OrderDict::FINISH,
+ 'finish_time' => time(),
+ 'timeout' => 0
+ );
+ $this->model->where($where)->update($update_data);
+ //订单项收货
+ $this->orderGoodsTake($data);
+ $data[ 'order_data' ] = array_merge($order, $update_data);
+ //订单完成操作
+ CoreOrderEventService::orderFinish($data);
+ //订单完成后操作
+ CoreOrderEventService::orderFinishAfter($data);
+ return true;
+ }
+
+ /**
+ * 订单项收货
+ * @param $data
+ * @return void
+ */
+ public function orderGoodsTake($data)
+ {
+ $order_id = $data[ 'order_id' ];
+ $order_goods_ids = $data[ 'order_goods_ids' ] ?? [];
+ //将待收货的订单项设置已收货
+ $order_goods_where = array (
+ [ 'order_id', '=', $order_id ],
+ [ 'status', '=', OrderGoodsDict::NORMAL ],
+// ['delivery_status', '=', OrderDeliveryDict::DELIVERY_FINISH]
+ );
+ if(!empty($order_goods_ids)){
+ $order_goods_where[] = ['order_goods_id', 'in', $order_goods_ids];
+ }
+ $order_goods_data = array (
+ 'delivery_status' => OrderDeliveryDict::TAKED
+ );
+ ( new OrderGoods() )->where($order_goods_where)->update($order_goods_data);
+ return true;
+ }
+
+
+ /**
+ * 确认收货提醒接口
+ * @param array $params
+ * @return string
+ */
+ public function orderShippingNotifyConfirmReceive($params = [])
+ {
+
+ try {
+
+ $pay_model = new Pay();
+ $where = array (
+ [ 'out_trade_no', '=', $params[ 'out_trade_no' ] ]
+ );
+ $pay_info = $pay_model->where($where)->field('id,type')->findOrEmpty()->toArray();
+
+ // 订单未使用微信支付,无须处理
+ if ($pay_info[ 'type' ] != PayDict::WECHATPAY) {
+ return '订单未使用微信支付';
+ }
+
+ if ($params[ 'delivery_type' ] != OrderDeliveryDict::EXPRESS) {
+ return '只有物流订单才能进行提醒';
+ }
+
+ $weapp_delivery_service = new CoreWeappDeliveryService();
+
+ // 检测微信小程序是否已开通发货信息管理服务
+ $is_trade_managed = $weapp_delivery_service->isTradeManaged();
+
+ if (empty($is_trade_managed[ 'is_trade_managed' ])) {
+ return '发货信息录入接口,报错:' . $is_trade_managed[ "errmsg" ];
+ }
+
+ // 设置消息跳转路径设置接口
+ $result_jump_path = $weapp_delivery_service->setMsgJumpPath('shop_order');
+ if ($result_jump_path[ 'errcode' ] != 0) {
+ return '设置消息跳转路径设置接口,报错:' . $result_jump_path[ "errmsg" ];
+ }
+
+ $data = [
+ 'merchant_trade_no' => $params[ 'out_trade_no' ] // 商户系统内部订单号,只能是数字、大小写字母_-*且在同一个商户号下唯一
+ ];
+ $weapp_delivery_service->notifyConfirmReceive($data);
+
+ } catch (\Exception $e) {
+ Log::write('确认收货提醒接口失败' . $e->getMessage() . $e->getFile() . $e->getLine());
+ }
+ }
+
+}
diff --git a/niucloud/addon/shop/app/service/core/order/CoreOrderEventService.php b/niucloud/addon/shop/app/service/core/order/CoreOrderEventService.php
new file mode 100644
index 000000000..af01c5181
--- /dev/null
+++ b/niucloud/addon/shop/app/service/core/order/CoreOrderEventService.php
@@ -0,0 +1,155 @@
+model = new Order();
+ }
+
+ /**
+ * 订单创建事件
+ * @param $data
+ * @return true
+ */
+ public static function orderCreate($data){
+ event('ShopOrderCreate', $data);
+ return true;
+ }
+
+ /**
+ * 订单创建后事件
+ * @param $data
+ * @return true
+ */
+ public static function orderCreateAfter($data){
+ OrderCreateAfter::dispatch(['data' => $data]);
+ return true;
+ }
+
+ /**
+ * 订单支付
+ * @param $data
+ * @return true
+ */
+ public static function orderPay($data){
+ event('ShopOrderPay', $data);
+ return true;
+ }
+
+ /**
+ * 订单支付后事件
+ * @param $data
+ * @return true
+ */
+ public static function orderPayAfter($data){
+ OrderPayAfter::dispatch(['data' => $data]);
+ return true;
+ }
+
+ /**
+ * 订单关闭
+ * @param $data
+ * @return true
+ */
+ public static function orderClose($data){
+ event('ShopOrderClose', $data);
+ return true;
+ }
+
+ /**
+ * 订单关闭后事件
+ * @param $data
+ * @return true
+ */
+ public static function orderCloseAfter($data){
+ OrderCloseAfter::dispatch(['data' => $data]);
+ return true;
+ }
+
+
+ /**
+ * 订单发货
+ * @param $data
+ * @return true
+ */
+ public static function orderDelivery($data){
+ event('ShopOrderDelivery', $data);
+ return true;
+ }
+
+ /**
+ * 订单发货后事件
+ * @param $data
+ * @return true
+ */
+ public static function orderDeliveryAfter($data){
+ OrderDeliveryAfter::dispatch(['data' => $data]);
+ return true;
+ }
+
+ /**
+ * 订单完成
+ * @param $data
+ * @return true
+ */
+ public static function orderFinish($data){
+ event('ShopOrderFinish', $data);
+ return true;
+ }
+
+ /**
+ * 订单完成后事件
+ * @param $data
+ * @return true
+ */
+ public static function orderFinishAfter($data){
+ OrderFinishAfter::dispatch(['data' => $data]);
+ return true;
+ }
+
+ /**
+ * 订单改价
+ * @param $data
+ * @return true
+ */
+ public static function orderEditPrice($data){
+ event('ShopOrderEditPrice', $data);
+ return true;
+ }
+
+ /**
+ * 订单改价后事件
+ * @param $data
+ * @return true
+ */
+ public static function orderEditPriceAfter($data){
+ OrderEditPriceAfter::dispatch(['data' => $data]);
+ return true;
+ }
+}
diff --git a/niucloud/addon/shop/app/service/core/order/CoreOrderFinishService.php b/niucloud/addon/shop/app/service/core/order/CoreOrderFinishService.php
new file mode 100644
index 000000000..9b54208ae
--- /dev/null
+++ b/niucloud/addon/shop/app/service/core/order/CoreOrderFinishService.php
@@ -0,0 +1,154 @@
+model = new Order();
+ }
+
+ /**
+ * 订单完成
+ * @param array $data
+ * @return true
+ * @throws DbException
+ */
+ public function finish(array $data)
+ {
+ $order_id = $data[ 'order_id' ];
+
+ //查询订单
+ $where = array(
+ [ 'order_id', '=', $order_id ],
+ );
+ $order = $this->model->where($where)->findOrEmpty()->toArray();
+ if (empty($order)) throw new CommonException('SHOP_ORDER_NOT_FOUND');//订单不存在
+// if ($order[ 'status' ] != OrderDict::WAIT_TAKE) throw new CommonException('SHOP_ONLY_WAIT_TAKE_CAN_BE_TAKE');//只有待收货的订单才可以收货
+
+ //存在退款中的订单项,订单就不可以收货
+ $refunding_order_goods_count = ( new OrderGoods() )->where([
+ [ 'order_id', '=', $order_id ],
+ [ 'status', '=', OrderGoodsDict::REFUNDING ]
+ ])->count();
+ if ($refunding_order_goods_count > 0) throw new CommonException('SHOP_ORDER_HAS_REFUNDING_NOT_ALLOW_FINISH');//是否存在退款中的订单项
+ $update_data = array(
+ 'status' => OrderDict::FINISH,
+ 'finish_time' => time(),
+ 'is_enable_refund' => 0,
+ 'timeout' => 0
+ );
+ $this->model->where($where)->update($update_data);
+ //订单项收货
+ $this->orderGoodsTake($data);
+ $data[ 'order_data' ] = array_merge($order, $update_data);
+ //订单完成操作
+ CoreOrderEventService::orderFinish($data);
+ //订单完成后操作
+ CoreOrderEventService::orderFinishAfter($data);
+ return true;
+ }
+
+ /**
+ * 订单项收货
+ * @param $data
+ * @return void
+ */
+ public function orderGoodsTake($data)
+ {
+ $order_id = $data[ 'order_id' ];
+ $order_goods_ids = $data[ 'order_goods_ids' ] ?? [];
+ //将待收货的订单项设置已收货
+ $order_goods_where = array(
+ [ 'order_id', '=', $order_id ],
+ [ 'status', '=', OrderGoodsDict::NORMAL ],
+// ['delivery_status', '=', OrderDeliveryDict::DELIVERY_FINISH]
+ );
+ if (!empty($order_goods_ids)) {
+ $order_goods_where[] = [ 'order_goods_id', 'in', $order_goods_ids ];
+ }
+ $order_goods_data = array(
+ 'delivery_status' => OrderDeliveryDict::TAKED
+ );
+ ( new OrderGoods() )->where($order_goods_where)->update($order_goods_data);
+ return true;
+ }
+
+ /**
+ * 确认收货提醒接口
+ * @param array $params
+ * @return string
+ */
+ public function orderShippingNotifyConfirmReceive($params = [])
+ {
+
+ try {
+
+ $pay_model = new Pay();
+ $where = array(
+ [ 'out_trade_no', '=', $params[ 'out_trade_no' ] ]
+ );
+ $pay_info = $pay_model->where($where)->field('id,type')->findOrEmpty()->toArray();
+
+ // 订单未使用微信支付,无须处理
+ if ($pay_info[ 'type' ] != PayDict::WECHATPAY) {
+ return '订单未使用微信支付';
+ }
+
+ if ($params[ 'delivery_type' ] != OrderDeliveryDict::EXPRESS) {
+ return '只有物流订单才能进行提醒';
+ }
+
+ $weapp_delivery_service = new CoreWeappDeliveryService();
+
+ // 检测微信小程序是否已开通发货信息管理服务
+ $is_trade_managed = $weapp_delivery_service->isTradeManaged();
+
+ if (empty($is_trade_managed[ 'is_trade_managed' ])) {
+ return '发货信息录入接口,报错:' . $is_trade_managed[ "errmsg" ];
+ }
+
+ // 设置消息跳转路径设置接口
+ $result_jump_path = $weapp_delivery_service->setMsgJumpPath('shop_order');
+ if ($result_jump_path[ 'errcode' ] != 0) {
+ return '设置消息跳转路径设置接口,报错:' . $result_jump_path[ "errmsg" ];
+ }
+
+ $data = [
+ 'merchant_trade_no' => $params[ 'out_trade_no' ] // 商户系统内部订单号,只能是数字、大小写字母_-*且在同一个商户号下唯一
+ ];
+ $weapp_delivery_service->notifyConfirmReceive($data);
+
+ } catch (\Exception $e) {
+// throw new CommonException($e->getMessage());
+ }
+ }
+
+}
diff --git a/niucloud/addon/shop/app/service/core/order/CoreOrderLogService.php b/niucloud/addon/shop/app/service/core/order/CoreOrderLogService.php
new file mode 100644
index 000000000..db537f88c
--- /dev/null
+++ b/niucloud/addon/shop/app/service/core/order/CoreOrderLogService.php
@@ -0,0 +1,89 @@
+model = new OrderLog();
+ }
+
+ /**
+ * 订单日志
+ * @param array $data
+ * @return true
+ */
+ public function add(array $data)
+ {
+ $this->model->create($data);
+ return true;
+ }
+
+ /**
+ * 批量写入日志
+ * @param array $data
+ * @return true
+ */
+ public function addAll(array $data)
+ {
+ $this->model->insertAll($data);
+ return true;
+ }
+
+ /**
+ * 操作人数据批量查询并转化(周)
+ * @param $data
+ * @return void[]
+ */
+ public function getMainData($data)
+ {
+ $member_ids = [];
+ $uids = [];
+ foreach ($data as $v) {
+ $main_type = $v[ 'main_type' ];
+ $main_id = $v[ 'main_id' ];
+ if ($main_type == OrderLogDict::MEMBER) {
+ $member_ids[] = $main_id;
+ } elseif ($main_type == OrderLogDict::STORE) {
+ $uids[] = $main_id;
+ }
+ }
+ $member_names = !empty($member_ids) ? ( new Member() )->where([ [ 'member_id', 'in', $member_ids ] ])->column('nickname', 'member_id') : [];
+ $user_names = !empty($uids) ? ( new SysUser() )->where([ [ 'uid', 'in', $uids ] ])->column('username', 'uid') : [];
+ return array_map(function($value) use ($member_names, $user_names) {
+ $main_type = $value[ 'main_type' ];
+ $main_id = $value[ 'main_id' ];
+ if ($main_type == OrderLogDict::MEMBER) {
+ $main_name = $member_names[ $main_id ];
+ } elseif ($main_type == OrderLogDict::STORE) {
+ $main_name = $user_names[ $main_id ];
+ } else {
+ $main_name = '';
+ }
+ $value[ 'main_name' ] = $main_name;
+ return $value;
+ }, $data);
+ }
+
+}
diff --git a/niucloud/addon/shop/app/service/core/order/CoreOrderPayService.php b/niucloud/addon/shop/app/service/core/order/CoreOrderPayService.php
new file mode 100644
index 000000000..acc3d89b1
--- /dev/null
+++ b/niucloud/addon/shop/app/service/core/order/CoreOrderPayService.php
@@ -0,0 +1,108 @@
+model = new Order();
+ }
+
+ /**
+ * 订单已支付操作
+ * @param array $data
+ * @return void
+ */
+ public function pay(array $data)
+ {
+ $order_id = $data[ 'trade_id' ];
+ $where = [
+ [
+ 'order_id', '=', $order_id
+ ]
+ ];
+ $order = $this->model->where($where)->findOrEmpty();
+ if ($order->isEmpty())
+ throw new CommonException('SHOP_ORDER_NOT_FOUND');//订单不存在
+
+ //todo 状态判断
+ if (!in_array($order[ 'status' ], [ OrderDict::WAIT_PAY, OrderDict::CLOSE ])) throw new CommonException('SHOP_ORDER_IS_PAY_FINISH');//订单支付
+ $out_trade_no = $data[ 'out_trade_no' ] ?? '';
+ //订单状态变成已支付
+ $order_data = array(
+ 'status' => OrderDict::WAIT_DELIVERY,
+ 'pay_time' => time(),
+ 'timeout' => 0,
+ 'out_trade_no' => $out_trade_no,
+ 'is_enable_refund' => 1,
+ );
+ $this->model->where($where)->update($order_data);
+
+ //订单到达待发货状态
+ $this->orderGoodsPay([ 'order_id' => $order_id ]);
+
+ $data[ 'order_data' ] = $order->toArray();
+ $data[ 'order_id' ] = $order_id;
+
+// event('AfterShopOrderPay', $data);
+ //订单支付操作
+ CoreOrderEventService::orderPay($data);
+ //订单支付后操作
+ CoreOrderEventService::orderPayAfter($data);
+ return true;
+ }
+
+
+ /**
+ * 订单项支付操作
+ * @param $data
+ * @return true
+ */
+ public function orderGoodsPay($data)
+ {
+ $order_id = $data[ 'order_id' ];
+ $update_data = [
+ 'delivery_status' => OrderDeliveryDict::WAIT_DELIVERY,
+ 'is_enable_refund' => 1
+ ];
+ $where = [
+ [ 'order_id', '=', $order_id ]
+ ];
+ ( new OrderGoods() )->where($where)->update($update_data);
+ return true;
+ }
+
+
+ /**
+ * to待配送状态
+ * @param $data
+ * @return void
+ */
+ public function toDelivery($data)
+ {
+ //todo 根据订单项类判断各个商品的配送操作
+
+ }
+}
diff --git a/niucloud/addon/shop/app/service/core/order/CoreOrderService.php b/niucloud/addon/shop/app/service/core/order/CoreOrderService.php
new file mode 100644
index 000000000..f4f8f892c
--- /dev/null
+++ b/niucloud/addon/shop/app/service/core/order/CoreOrderService.php
@@ -0,0 +1,86 @@
+model = new Order();
+ }
+
+ /**
+ * 查询订单
+ * @param int $order_id
+ * @return array
+ */
+ public function getInfo(int $order_id)
+ {
+ //查询订单
+ $where = array(
+ [ 'order_id', '=', $order_id ]
+ );
+ return $this->model->where($where)->findOrEmpty()->toArray();
+ }
+
+ /**
+ * 查询物流信息
+ * @param $params
+ * @return mixed
+ */
+ public function deliverySearch($params)
+ {
+ $class = new DeliverySearchLoader();
+ $data = [
+ 'company_id' => !empty($params[ 'company' ]) ? $params[ 'company' ][ 'company_id' ] : '',
+ 'express_no' => !empty($params[ 'company' ]) ? $params[ 'company' ][ 'express_no' ] : '',
+ 'logistic_no' => $params[ 'express_number' ],
+ 'mobile' => $params[ 'mobile' ],
+ ];
+
+ //获取缓存
+ $traces = Cache::get('order_delivery:'.$data['express_no'].$params['id']);
+ if(empty($traces)){
+ $traces = $class->search($data);
+ if (!empty($traces[ 'list' ])) {
+ //结果缓存2小时
+ $traces[ 'list' ] = array_reverse($traces[ 'list' ]);
+ Cache::tag('order_delivery')->set('order_delivery:'.$data['express_no'], $traces, 7200);
+ }
+ }
+ $params[ 'traces' ] = $traces;
+ return $params;
+ }
+
+ public function setInvoiceIdByOrderId($order_ids, $invoice_id = 0)
+ {
+ if (is_string($order_ids)){
+ $order_ids = explode(',', $order_ids);
+ }
+ $this->model->whereIn('order_id', $order_ids)->update(['invoice_id' => $invoice_id]);
+ }
+ public function cancelInvoiceId($invoice_id = 0)
+ {
+ $this->model->whereIn('invoice_id', $invoice_id)->update(['invoice_id' => 0]);
+ }
+}
diff --git a/niucloud/addon/shop/app/service/core/pointexchange/CoreGoodsSaleNumService.php b/niucloud/addon/shop/app/service/core/pointexchange/CoreGoodsSaleNumService.php
new file mode 100644
index 000000000..8754a58a0
--- /dev/null
+++ b/niucloud/addon/shop/app/service/core/pointexchange/CoreGoodsSaleNumService.php
@@ -0,0 +1,62 @@
+model = new Exchange();
+ }
+
+ /**
+ * 增加
+ * @param $data
+ * @return void
+ */
+ public function inc($data)
+ {
+ $this->model->where([['id', '=', $data['id']]])->inc('total_exchange_num', $data['num'])->inc('total_member_num', 1)->inc('total_point_num', $data['point'])->inc('total_price_num', $data['goods_money'])->inc('total_order_num', 1)->update();
+ return true;
+ }
+ /**
+ * 增加
+ * @param $data
+ * @return void
+ */
+ public function batchUpdate($data)
+ {
+ $this->model->saveAll($data);
+ return true;
+ }
+
+ /**
+ * 减少
+ * @param $data
+ * @return void
+ */
+ public function dec($data)
+ {
+ $this->model->where([['id', '=', $data['id']]])->dec('total_exchange_num', $data['num'])->dec('total_member_num', 1)->dec('total_point_num', $data['point'])->dec('total_price_num', $data['goods_money'])->dec('total_order_num', 1)->update();
+ return true;
+ }
+
+}
diff --git a/niucloud/addon/shop/app/service/core/pointexchange/CoreGoodsStockService.php b/niucloud/addon/shop/app/service/core/pointexchange/CoreGoodsStockService.php
new file mode 100644
index 000000000..6194ab817
--- /dev/null
+++ b/niucloud/addon/shop/app/service/core/pointexchange/CoreGoodsStockService.php
@@ -0,0 +1,88 @@
+model = new Exchange();
+ }
+
+
+ /**
+ * 增加库存
+ * @param $data
+ * @return void
+ */
+ public function inc($data)
+ {
+ $where[ 'sku_id' ] = $data[ 'sku_id' ];
+ $exchange_goods_info = ( new CorePointexChangeService )->getInfo($where);
+ if (!empty($exchange_goods_info)) {
+ $sku_key = array_search($data[ 'sku_id' ], array_column($exchange_goods_info[ 'product_detail' ], 'sku_id'));
+ $exchange_sku_info = $exchange_goods_info[ 'product_detail' ][ $sku_key ];
+ $exchange_goods_info[ 'product_detail' ][ $sku_key ][ 'stock' ] += $data[ 'num' ];
+ $update_array[ 'stock' ] = $exchange_sku_info[ 'stock' ] + $data[ 'num' ];
+ $update_array[ 'product_detail' ] = json_encode($exchange_goods_info[ 'product_detail' ]);
+ $this->model->where([ [ 'id', '=', $exchange_goods_info[ 'id' ] ] ])->update($update_array);
+ return true;
+ }
+ }
+
+ /**
+ * 减少库存
+ * @param $data
+ * @return void
+ */
+ public function dec($data)
+ {
+
+ $where[ 'sku_id' ] = $data[ 'sku_id' ];
+ $exchange_goods_info = ( new CorePointexChangeService )->getInfo($where);
+ if (!empty($exchange_goods_info)) {
+ $sku_key = array_search($data[ 'sku_id' ], array_column($exchange_goods_info[ 'product_detail' ], 'sku_id'));
+ $exchange_sku_info = $exchange_goods_info[ 'product_detail' ][ $sku_key ];
+ $sku_where[] = [ 'sku_id', '=', $exchange_sku_info[ 'sku_id' ] ];
+ $goods_sku_info = ( new GoodsSku() )->where($sku_where)->field('stock')->findOrEmpty()->toArray();
+ if ($exchange_sku_info[ 'stock' ] < $goods_sku_info[ 'stock' ]) {
+ $exchange_goods_info[ 'product_detail' ][ $sku_key ][ 'stock' ] -= $data[ 'num' ];
+ } else {
+ $exchange_goods_info[ 'product_detail' ][ $sku_key ][ 'stock' ] = $goods_sku_info[ 'stock' ];
+ }
+ $stock = array_sum(array_column($exchange_goods_info[ 'product_detail' ], 'stock'));
+ $update_array[ 'product_detail' ] = json_encode($exchange_goods_info[ 'product_detail' ]);
+ //数量不足直接下架
+ $update_array[ 'stock' ] = max($stock, 0);
+ //todo 目前不考虑 切默认展示的sku 限购等数据
+ // array_multisort(array_column($exchange_goods_info['product_detail'], "point"), SORT_ASC, $product_detail);
+ // $update_array['point'] = $product_detail[0]['point'];
+ // $update_array['price'] = $product_detail[0]['price'];
+ // $update_array['limit_num'] = $product_detail[0]['limit_num'];
+ $this->model->where([ [ 'id', '=', $exchange_goods_info[ 'id' ] ] ])->update($update_array);
+ return true;
+ }
+
+ }
+
+}
diff --git a/niucloud/addon/shop/app/service/core/pointexchange/CoreOrderCreateService.php b/niucloud/addon/shop/app/service/core/pointexchange/CoreOrderCreateService.php
new file mode 100644
index 000000000..93118f317
--- /dev/null
+++ b/niucloud/addon/shop/app/service/core/pointexchange/CoreOrderCreateService.php
@@ -0,0 +1,301 @@
+model = new Order();
+ }
+
+ /**
+ * 订单创建
+ * @param array $data
+ * @return array
+ */
+ public function create(array $data)
+ {
+
+ //参数赋值
+ $this->setParam($data);
+ $order_key = $this->param[ 'order_key' ] ?? '';
+ //获取订单缓存缓存
+ $this->getOrderCache($order_key);
+ //校验错误
+ $this->checkError();
+ //基础校验库存/活动信息
+ $this->checkExchangeGoods($this->goods_data);
+ $local_delivery_type = $data[ 'delivery' ]['local_delivery_type'] ?? '';
+ $order_data = [
+ //订单整体
+ 'order_type' => OrderDict::TYPE,
+ 'status' => OrderDict::WAIT_PAY,
+ 'body' => $this->basic[ 'body' ],
+ 'member_id' => $this->member_id,
+ 'goods_money' => $this->basic[ 'goods_money' ],
+ 'delivery_money' => $this->basic[ 'delivery_money' ] ?? 0,
+ 'discount_money' => $this->basic[ 'discount_money' ] ?? 0,
+ 'order_money' => $this->basic[ 'order_money' ],
+ 'has_goods_types' => $this->basic[ 'has_goods_types' ],//包含的商品形式
+ //收发货相关
+ 'delivery_type' => $this->delivery[ 'delivery_type' ] ?? '',
+ 'taker_name' => $this->delivery[ 'take_address' ][ 'name' ] ?? $data['delivery'][ 'taker_name' ] ?? '',
+ 'taker_mobile' => $this->delivery[ 'take_address' ][ 'mobile' ] ?? $data['delivery'][ 'taker_mobile' ] ?? '',
+ 'taker_province' => $this->delivery[ 'take_address' ][ 'province_id' ] ?? 0,
+ 'taker_city' => $this->delivery[ 'take_address' ][ 'city_id' ] ?? 0,
+ 'taker_district' => $this->delivery[ 'take_address' ][ 'district_id' ] ?? 0,
+ 'taker_address' => $this->delivery[ 'take_address' ][ 'address' ] ?? '',
+ 'taker_full_address' => $this->delivery[ 'take_address' ][ 'full_address' ] ?? '',
+ 'taker_longitude' => $this->delivery[ 'take_address' ][ 'lng' ] ?? '',
+ 'taker_latitude' => $this->delivery[ 'take_address' ][ 'lat' ] ?? '',
+ 'take_store_id' => $this->delivery[ 'take_store' ][ 'store_id' ] ?? 0,
+
+ 'buyer_ask_delivery_time' =>$local_delivery_type == 'now' ? "" : $data[ 'delivery' ][ 'buyer_ask_delivery_time' ] ?? '', // 购买者期望的时间
+
+ //附属信息
+ 'member_remark' => $this->param[ 'member_remark' ] ?? '',//买家留言
+ 'point' => $this->basic[ 'point_sum' ] ?? 0,//买家留言
+ 'relate_id' => $this->discount[ 'discount' ][ 'discount_type_id' ] ?? 0,//关联id
+ 'activity_type' => ExchangeDict::DISCOUNT, // 活动类型
+ ];
+ $order_goods_data = [];//项
+ foreach ($this->goods_data as $v) {
+ $order_goods_data[] = [
+ 'member_id' => $data[ 'member_id' ],
+ 'goods_id' => $v[ 'goods_id' ],
+ 'sku_id' => $v[ 'sku_id' ],
+ 'goods_name' => $v[ 'goods' ][ 'goods_name' ],
+ 'sku_name' => $v[ 'sku_name' ],
+ 'goods_image' => $v[ 'goods' ][ 'goods_cover' ],
+ 'sku_image' => $v[ 'sku_image' ],
+ 'price' => $v[ 'price' ],
+ 'original_price' => $v[ 'original_price' ] ?? 0,
+ 'num' => $v[ 'num' ],
+ 'goods_money' => $v[ 'goods_money' ],
+ 'goods_type' => $v[ 'goods' ][ 'goods_type' ],
+ 'order_id' => &$this->order_id,
+ 'discount_money' => $v[ 'discount_money' ] ?? 0,
+ 'status' => OrderGoodsDict::NORMAL,
+ 'extend' => json_encode($v[ 'exchange_info' ])
+ ];
+ }
+ $create_order_data = array(
+ 'order_data' => $order_data,
+ 'order_goods_data' => $order_goods_data,
+ );
+ return $this->createOrder($create_order_data);
+ }
+
+ /**
+ * @param array $data
+ * @return array
+ * @throws \Exception
+ */
+ public function calculate(array $data)
+ {
+
+ //参数赋值
+ $this->setParam($data);
+ $this->order_key = $this->param[ 'order_key' ] ?? '';
+ if (empty($this->order_key)) {
+ $this->confirm();
+ }
+ //获取订单数据的缓存
+ $this->getOrderCache($this->order_key . '_basic');
+ // todo 计算优惠和营销
+ //$this->calculateDiscount();
+ $this->setOrderCache($this->order_key);
+ //计算运费
+ $this->calculateDelivery();
+ //金额格式化
+ $discount_money = $this->moneyFormat($this->basic[ 'discount_money' ] ?? 0);//优惠金额
+ $delivery_money = $this->moneyFormat($this->basic[ 'delivery_money' ] ?? 0);
+ $goods_money = $this->moneyFormat($this->basic[ 'goods_money' ] ?? 0);
+
+ $order_money = $this->moneyFormat($this->moneyCalculate($delivery_money, $goods_money, -$discount_money));
+ $this->basic[ 'discount_money' ] = $discount_money;
+ $this->basic[ 'delivery_money' ] = $delivery_money;
+ $this->basic[ 'goods_money' ] = $goods_money;
+ //todo 校验控制,不能小于0
+ $order_money = $order_money < 0 ? 0 : $order_money;
+ $this->basic[ 'order_money' ] = $order_money;
+// $this->basic['pay_money'] = $this->basic['pay_money'] ?? $order_money;
+ //订单创建数据写入缓存,并将标识返回给前端
+ $order_cache = get_object_vars($this);
+ unset($order_cache[ 'param' ]);
+ $this->setOrderCache($this->order_key, $order_cache);
+ return $order_cache;
+ }
+
+ /**
+ * 订单确认(基础信息查询并缓存)
+ * @param array $data
+ * @return array|mixed
+ */
+ public function confirm()
+ {
+ //查看会员信息
+ $member_id = $this->param[ 'member_id' ];
+ $this->member_id = $member_id;
+ $member_info = ( new CoreMemberService() )->getInfoByMemberId($member_id, 'nickname, point, member_level');
+ if (empty($member_info)) throw new CommonException('SHOP_ORDER_BUYER_NOT_FOUND');//无效的账号
+ // 查询会员等级信息
+ $member_info[ 'member_level' ] = ( new MemberLevel() )->where([ [ 'level_id', '=', $member_info[ 'member_level' ] ] ])->field('level_id,level_benefits')->findOrEmpty()->toArray();
+ //会员账户信息
+ $this->buyer = $member_info;
+ //查询商品信息
+ $this->getGoodsData();
+ //配送相关信息
+ $this->getDelivery();
+ $order_cache = get_object_vars($this);
+ unset($order_cache[ 'param' ]);
+ unset($order_cache[ 'order_key' ]);
+ $order_key = $this->setOrderCache('', $order_cache);
+ //将基础订单数据单独存放一个缓存
+ $order_basic_key = $order_key . '_basic';
+ $this->setOrderCache($order_basic_key, $order_cache);
+ $this->order_key = $order_key;
+ return true;
+ }
+
+ /**
+ * 商品相关数据
+ * @return array
+ * @throws DataNotFoundException
+ * @throws DbException
+ * @throws ModelNotFoundException
+ */
+ public function getGoodsData()
+ {
+ $sku_data = $this->param[ 'sku_data' ] ?? [];
+ $sku_ids = array_column($sku_data, 'sku_id');
+ $sku_id = $sku_ids[ 0 ];
+ $sku_where = [];
+ $field = 'names,total_exchange_num,stock,id,type,names,title,image,status,product_detail,point,price,limit_num,content,sort,total_point_num,total_price_num,total_order_num,total_member_num,update_time,create_time';
+ $exchange_goods_info = ( new Exchange() )->where(array_merge($sku_where, [ [ 'product_detail', 'like', '%' . '"sku_id":' . $sku_ids[ 0 ] . ',' . '%' ] ]))->append([ 'type_name', 'status_name' ])->field($field)->findOrEmpty()->toArray();
+ if (empty($exchange_goods_info)) throw new CommonException('EXCHANGE_DATA_NOT_FOUND');//无效的商品
+ $sku_key = array_search($sku_id, array_column($exchange_goods_info[ 'product_detail' ], 'sku_id'));
+ //todo 限制兑换 业务
+ $sku_info = $exchange_goods_info[ 'product_detail' ][ $sku_key ];
+ $exchange_goods_info = array_merge2($exchange_goods_info, $sku_info);
+ $sku_list = ( new GoodsSku() )->where(array_merge($sku_where, [ [ 'sku_id', 'in', $sku_ids ] ]))->with([ 'goods' ])->field('sku_id, sku_name, sku_image, goods_id, price, stock, weight, volume,sku_id, sku_spec_format,member_price, sale_price')->select()->toArray();
+ $sku_list = array_column($sku_list, null, 'sku_id');
+ $order_data = [];
+ $goods_list = [];
+ $order_money = $goods_money = $delivery_money = 0;
+ $total_num = 0;
+ $point_sum = 0;
+ $body = '';
+ //订单中包含的商品形式
+ $has_goods_types = [];
+ foreach ($sku_data as $v) {
+ $sku_id = $v[ 'sku_id' ];
+ $num = $v[ 'num' ];
+ $total_num += $num;
+ $sku_info = $sku_list[ $sku_id ] ?? [];
+ if (empty($sku_info)) throw new CommonException('SHOP_ORDER_CARTS_EXPIRE');//无效的商品
+ //商品原价
+ $sku_info[ 'original_price' ] = $sku_info[ 'price' ];
+ $sku_info[ 'member_price' ] = $exchange_goods_info[ 'price' ];
+ $sku_info[ 'price' ] = $exchange_goods_info[ 'price' ];
+ //默认金额填充
+ $sku_info[ 'discount_money' ] = 0;
+ $item_goods_type = $sku_info[ 'goods' ][ 'goods_type' ];
+ if (!in_array($item_goods_type, $has_goods_types)) $has_goods_types[] = $item_goods_type;
+ $sku_info[ 'num' ] = $num;
+ $sku_info[ 'market_type' ] = '积分兑换';//活动类型
+ $sku_info[ 'market_type_id' ] = $exchange_goods_info[ 'id' ];//活动id
+ //优化业务录入 todo 目前不考虑 数量
+ $this->discount[ 'discount' ] = $this->discountFormat(
+ [ $sku_info[ 'sku_id' ] ],
+ OrderDiscountDict::DISCOUNT,
+ $exchange_goods_info[ 'point' ] * $num,
+ ( $sku_info[ 'original_price' ] - $sku_info[ 'price' ] ) * $num,
+ ExchangeDict::DISCOUNT,
+ $exchange_goods_info[ 'id' ],
+ '积分兑换',
+ $exchange_goods_info[ 'names' ] ?? ''
+ );
+ $price = $sku_info[ 'price' ];
+ $sku_info[ 'goods_money' ] = $price * $num;//小计
+ $sku_info[ 'point_sum' ] = $exchange_goods_info[ 'point' ] * $num;//小计
+ $goods_money += $sku_info[ 'goods_money' ];
+ $point_sum += $sku_info[ 'point_sum' ];
+ $body = $body ? $body . ( $sku_info[ 'sku_name' ] . $sku_info[ 'goods' ][ 'goods_name' ] ) : ( $sku_info[ 'sku_name' ] . $sku_info[ 'goods' ][ 'goods_name' ] );
+ $body = $exchange_goods_info[ 'names' ] . " " . $body;
+ $sku_info[ 'goods_name' ] = $exchange_goods_info[ 'names' ];
+ $sku_info[ 'sku_image' ] = $exchange_goods_info[ 'image' ];
+ $sku_info[ 'exchange_id' ] = $exchange_goods_info[ 'id' ];
+ $sku_info[ 'exchange_info' ] = $exchange_goods_info[ 'product_detail' ][ $sku_key ];
+ $goods_list[ $sku_id ] = $sku_info;
+ }
+ $this->basic[ 'has_goods_types' ] = $has_goods_types;
+ $this->basic[ 'total_num' ] = $total_num;
+ $this->basic[ 'point_sum' ] = $point_sum ?? 0;
+ $this->goods_data = $goods_list;
+ $this->basic[ 'goods_money' ] = $goods_money;
+ $this->basic[ 'body' ] = $body;
+ return $order_data;
+ }
+
+ /**
+ * 自身业务检测
+ * @param $sku_info
+ * @return string
+ */
+ public function checkExchangeGoods($order_goods_data)
+ {
+ //不走后续的扣款判断改变提示语
+ if ($this->basic[ 'point_sum' ] > $this->buyer[ 'point' ]) {
+ throw new CommonException('SHOP_ORDER_EXCHANGE_POINT_INSUFFICIENT');
+ }
+ $order_goods_data_column = array_column($order_goods_data, 'num', 'sku_id');
+ $sku_list = ( new GoodsSku() )->where([ [ 'sku_id', 'in', array_column($order_goods_data, 'sku_id') ] ])->select();
+ foreach ($sku_list as $v) {
+ $sku_where = [];
+ $field = 'names,total_exchange_num,stock,id,type,names,title,image,status,product_detail,point,price,limit_num,content,sort,total_point_num,total_price_num,total_order_num,total_member_num,update_time,create_time';
+ $exchange_goods_info = ( new Exchange() )->where(array_merge($sku_where, [ [ 'product_detail', 'like', '%' . '"sku_id":' . $v[ 'sku_id' ] . ',' . '%' ] ]))->append([ 'type_name', 'status_name' ])->field($field)->findOrEmpty()->toArray();
+ if (empty($exchange_goods_info)) throw new CommonException('EXCHANGE_DATA_NOT_FOUND');//无效的商品
+ if ($exchange_goods_info[ 'status' ] != 1) throw new CommonException('EXCHANGE_ACTIVITY_REMOVE');//下架判断
+ $sku_key = array_search($v[ 'sku_id' ], array_column($exchange_goods_info[ 'product_detail' ], 'sku_id'));
+ //todo 限制兑换 业务
+ $sku_info = $exchange_goods_info[ 'product_detail' ][ $sku_key ];
+ if ($sku_info[ 'limit_num' ] < $order_goods_data_column[ $v[ 'sku_id' ] ]) throw new CommonException('SHOP_ORDER_EXCHANGE_EXCEEDING_LIMIT');// 限购判断
+ if ($v[ 'stock' ] < $order_goods_data_column[ $v[ 'sku_id' ] ]) throw new CommonException('SHOP_ORDER_GOODS_INSUFFICIENT');
+ if ($sku_info[ 'stock' ] < $order_goods_data_column[ $v[ 'sku_id' ] ]) throw new CommonException('SHOP_ORDER_EXCHANGE_INSUFFICIENT_EXCHANGE_QUANTITY');//兑换数判断
+ }
+ }
+
+}
diff --git a/niucloud/addon/shop/app/service/core/pointexchange/CorePointexChangeService.php b/niucloud/addon/shop/app/service/core/pointexchange/CorePointexChangeService.php
new file mode 100644
index 000000000..d97aae523
--- /dev/null
+++ b/niucloud/addon/shop/app/service/core/pointexchange/CorePointexChangeService.php
@@ -0,0 +1,42 @@
+model = new Exchange();
+ }
+
+ /**
+ * 获取积分商城详情
+ * @param int $active_id
+ * @return array
+ */
+ public function getInfo($where)
+ {
+ $field = 'stock,total_exchange_num,id,type,names,title,image,status,product_detail,point,price,limit_num,content,sort,total_point_num,total_price_num,total_order_num,total_member_num,update_time,create_time';
+ $info = $this->model->withSearch([ 'names', 'status', 'create_time', 'product_detail', 'sku_id', 'goods_id' ], $where)->append([ 'type_name' ])->field($field)->findOrEmpty()->toArray();
+ return $info;
+ }
+
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/app/service/core/refund/CoreRefundActionService.php b/niucloud/addon/shop/app/service/core/refund/CoreRefundActionService.php
new file mode 100644
index 000000000..27306ff56
--- /dev/null
+++ b/niucloud/addon/shop/app/service/core/refund/CoreRefundActionService.php
@@ -0,0 +1,232 @@
+model = new OrderRefund();
+ }
+
+ /**
+ * 审核退款申请
+ * @param $data ['is-agree]
+ * @return void
+ */
+ public function auditApply($data)
+ {
+ $is_agree = $data[ 'is_agree' ];
+ $order_refund_no = $data[ 'order_refund_no' ];
+ //查询订单项信息
+ $order_refund_info = $this->model->where([
+ [ 'order_refund_no', '=', $order_refund_no ]
+ ])->findOrEmpty();
+ if ($order_refund_info->isEmpty()) throw new CommonException('SHOP_ORDER_REFUND_IS_INVALID');//退款已失效
+ if ($order_refund_info[ 'status' ] != OrderRefundDict::APPLY) throw new CommonException('SHOP_ORDER_REFUND_IS_ONLY_WAIT_REFUND');//退款已失效(只有申请中的退款才可以审核)
+
+ $order_goods_id = $order_refund_info[ 'order_goods_id' ];
+ //查询订单项信息
+ $order_goods_info = ( new OrderGoods() )->where([
+ [ 'order_goods_id', '=', $order_goods_id ],
+ ])->findOrEmpty();
+ if ($order_goods_info->isEmpty()) throw new CommonException('SHOP_ORDER_IS_INVALID');//订单已失效
+
+ $order_id = $order_goods_info[ 'order_id' ];//订单id
+ $order = ( new Order() )->where([ [ 'order_id', '=', $order_id ] ])->findOrEmpty();
+ if ($order->isEmpty()) throw new CommonException('SHOP_ORDER_IS_INVALID');//订单已失效
+
+ //根据退款方式来判断下一步的状态
+ $update_data = [];
+
+ $is_refund_delivery = $order_refund_info[ 'is_refund_delivery' ];
+ //当前订单项最大可退金额
+ $max_refund_money = $order_goods_info[ 'goods_money' ] - $order_goods_info[ 'discount_money' ];//可退金额
+ if ($is_refund_delivery == 1) {
+ $max_refund_money += $order[ 'delivery_money' ];
+ }
+
+ if ($is_agree) {
+ $money = $data[ 'money' ];
+ //退款金额不能大于可退款总额
+ $comparison = bccomp(bcsub($money, $max_refund_money), 0);//浮点数直接进行比较会出现精度问题
+ if ($comparison > 0) throw new CommonException('SHOP_ORDER_REFUND_MONEY_GT_ORDER_MONEY');//退款金额不能大于可退款总额
+ $update_data[ 'money' ] = $money;
+ //只退款
+ if ($order_refund_info[ 'refund_type' ] == OrderRefundDict::ONLY_REFUND) {
+
+ $update_data[ 'status' ] = OrderRefundDict::STORE_AGREE_REFUND_WAIT_TRANSFER;
+ } else {
+ $refund_address_id = $data[ 'refund_address_id' ] ?? 0;
+ $shop_address_field = 'contact_name,mobile,province_id,city_id,district_id,address,full_address,lat,lng';
+ $shop_address = ( new ShopAddress() )->where([ [ 'id', '=', $refund_address_id ] ])->field($shop_address_field)->findOrEmpty();
+ if ($shop_address->isEmpty()) throw new CommonException('SHOP_ORDER_REFUND_SELECT_ADDRESS');//订单已失效
+ $update_data[ 'refund_address' ] = $shop_address->toArray();
+// $update_data['timeout'] = 0;
+ $update_data[ 'status' ] = OrderRefundDict::STORE_AGREE_REFUND_GOODS_APPLY_WAIT_BUYER;
+ }
+ } else {
+ $update_data[ 'status' ] = OrderRefundDict::STORE_REFUSE_REFUND_GOODS_APPLY_WAIT_BUYER;
+ $update_data[ 'shop_reason' ] = $data[ 'shop_reason' ];
+ }
+ $order_refund_info->save($update_data);
+ //审核完毕后续事件
+ $data[ 'order_refund_no' ] = $order_refund_no;
+ $data[ 'refund_data' ] = array_merge($order_refund_info->toArray(), $update_data);
+
+ event('AfterShopOrderRefundAuditApply', $data);
+ return true;
+ }
+
+ /**
+ * 审核是否确认收货
+ * @param $data
+ * @return true
+ */
+ public function auditRefundGoods($data)
+ {
+ $is_agree = $data[ 'is_agree' ];
+ $order_refund_no = $data[ 'order_refund_no' ];
+ //查询订单项信息
+ $order_refund_info = $this->model->where([
+ [ 'order_refund_no', '=', $order_refund_no ]
+ ])->findOrEmpty();
+ if ($order_refund_info->isEmpty()) throw new CommonException('SHOP_ORDER_REFUND_IS_INVALID');//退款已失效
+ if ($order_refund_info[ 'status' ] != OrderRefundDict::BUYER_REFUND_GOODS_WAIT_STORE) throw new CommonException('SHOP_ORDER_REFUND_IS_ONLY_WAIT_REFUND_GOODS');//退款已失效(只有待确认收货请求才可以修改退款)
+
+ $order_goods_id = $order_refund_info[ 'order_goods_id' ];
+ //查询订单项信息
+ $order_goods_info = ( new OrderGoods() )->where([
+ [ 'order_goods_id', '=', $order_goods_id ],
+ ])->findOrEmpty();
+ if ($order_goods_info->isEmpty()) throw new CommonException('SHOP_ORDER_IS_INVALID');//订单已失效
+ //根据退款方式来判断下一步的状态
+ $update_data = array();
+ if ($is_agree) {
+ $update_data[ 'status' ] = OrderRefundDict::STORE_AGREE_REFUND_WAIT_TRANSFER;
+ } else {
+ $update_data[ 'status' ] = OrderRefundDict::STORE_REFUSE_TAKE_REFUND_GOODS_WAIT_BUYER;
+ $update_data[ 'shop_reason' ] = $data[ 'shop_reason' ];
+ }
+ $order_refund_info->save($update_data);
+ $data[ 'order_refund_no' ] = $order_refund_no;
+ $data[ 'refund_data' ] = array_merge($order_refund_info->toArray(), $update_data);
+ //确认收货审核完毕后续事件
+ event('AfterShopOrderRefundAuditRefundGoods', $data);
+ return true;
+ }
+
+ /**
+ * 退款关闭
+ * @param $data
+ * @return void
+ */
+ public function close($data,$refund_status=OrderRefundDict::CLOSE)
+ {
+ $order_refund_no = $data[ 'order_refund_no' ];
+ //查询订单项信息
+ $main_type = $data[ 'main_type' ] ?? '';
+ $where = [
+ [ 'order_refund_no', '=', $order_refund_no ],
+
+ ];
+ if ($main_type == OrderRefundLogDict::MEMBER) {
+ $where[] = [ 'member_id', '=', $data[ 'main_id' ] ];
+ }
+ $order_refund_info = $this->model->where($where)->findOrEmpty();
+ if ($order_refund_info->isEmpty()) throw new CommonException('SHOP_ORDER_REFUND_IS_INVALID');//退款已失效
+ if (in_array($order_refund_info[ 'status' ], [ OrderRefundDict::STORE_AGREE_REFUND_WAIT_TRANSFER, OrderRefundDict::STORE_REFUND_TRANSFERING, OrderRefundDict::FINISH, OrderRefundDict::CLOSE, OrderRefundDict::SHOP_ACTIVE_CLOSE_REFUND ])) throw new CommonException('SHOP_ORDER_REFUND_IS_INVALID_OR_FINISH');//退款已失效(退款已完成或已关闭)
+ $update_data = array(
+ 'status' => $refund_status,
+ 'close_time' => time()
+ );
+ $order_refund_info->save($update_data);
+
+ //对应的要将订单项还原
+ $order_goods_where = array(
+ [ 'order_refund_no', '=', $order_refund_no ]
+ );
+ $order_goods_update_data = array(
+ 'status' => OrderGoodsDict::NORMAL
+ );
+ ( new OrderGoods() )->where($order_goods_where)->update($order_goods_update_data);
+ //订单申请退款后事件
+ $data[ 'order_refund_no' ] = $order_refund_no;
+ $data[ 'refund_data' ] = array_merge($order_refund_info->toArray(), $update_data);
+ event('AfterShopOrderRefundClose', $data);
+ return true;
+ }
+
+ /**
+ * 商家主动退款
+ * @param $data
+ * @return true
+ */
+ public function shopActiveRefund($data)
+ {
+ $order_goods_ids = $data[ 'order_goods_ids' ];
+ $shop_active_refund_money = $data[ 'shop_active_refund_money' ];
+
+ $check_data = ( new CoreRefundService() )->refundCheck($order_goods_ids, $shop_active_refund_money);
+ $order_goods_list = $check_data[ 'order_goods_list' ];
+
+ foreach ($order_goods_list as $order_goods_info) {
+ $order_refund_no = create_no();
+ $insert_data = [
+ 'order_id' => $order_goods_info[ 'order_id' ],
+ 'order_goods_id' => $order_goods_info[ 'order_goods_id' ],
+ 'order_refund_no' => $order_refund_no,
+ 'refund_type' => OrderRefundDict::ONLY_REFUND,
+ 'reason' => get_lang('dict_shop_order_refund_action.shop_active_refund'),
+ 'member_id' => $order_goods_info[ 'member_id' ],
+ 'apply_money' => $order_goods_info[ 'item_refund_money' ],
+ 'money' => $order_goods_info[ 'item_refund_money' ],
+ 'status' => OrderRefundDict::STORE_AGREE_REFUND_WAIT_TRANSFER,
+ 'remark' => $data[ 'shop_active_refund_remark' ],
+ 'voucher' => [],
+ 'source' => OrderRefundDict::ACTIVE_REFUND,
+ 'is_refund_delivery' => $order_goods_info[ 'is_refund_delivery' ],
+ ];
+ $order_refund_info = $this->model->create($insert_data);
+
+ //将订单项的退款单号覆盖
+ $order_goods_info->save([
+ 'order_refund_no' => $order_refund_no,
+ 'shop_active_refund' => 1,
+ 'shop_active_refund_money' => $order_goods_info[ 'item_refund_money' ],
+ 'status' => OrderGoodsDict::REFUNDING
+ ]);
+
+ $data[ 'refund_data' ] = $order_refund_info->toArray();
+ $data[ 'order_goods_data' ] = $order_goods_info->toArray();
+ event('AfterShopOrderRefundActiveCreate', $data);
+ }
+ return true;
+ }
+
+
+}
diff --git a/niucloud/addon/shop/app/service/core/refund/CoreRefundLogService.php b/niucloud/addon/shop/app/service/core/refund/CoreRefundLogService.php
new file mode 100644
index 000000000..5cc450450
--- /dev/null
+++ b/niucloud/addon/shop/app/service/core/refund/CoreRefundLogService.php
@@ -0,0 +1,40 @@
+model = new OrderRefundLog();
+ }
+
+ /**
+ * 添加日志
+ * @param $data
+ * @return true
+ */
+ public function add($data)
+ {
+ $this->model->create($data);
+ return true;
+ }
+
+}
diff --git a/niucloud/addon/shop/app/service/core/refund/CoreRefundService.php b/niucloud/addon/shop/app/service/core/refund/CoreRefundService.php
new file mode 100644
index 000000000..46a738c01
--- /dev/null
+++ b/niucloud/addon/shop/app/service/core/refund/CoreRefundService.php
@@ -0,0 +1,232 @@
+model = new OrderRefund();
+ }
+
+ /**
+ * 查询退款信息
+ * @param $order_refund_no
+ * @return array
+ */
+ public function getInfo($order_refund_no)
+ {
+ //查询订单
+ $where = array(
+ ['order_refund_no', '=', $order_refund_no]
+ );
+ return $this->model->where($where)->with(['order_main'])->findOrEmpty()->toArray();
+ }
+
+ /**
+ * 退款转账完成
+ * @param $data
+ * @return void
+ */
+ public function transferSuccess($data)
+ {
+ $order_refund_no = $data['order_refund_no'];
+ $refund_no = $data['refund_no'];
+ $update_data = array(
+ 'transfer_time' => time(),
+ 'refund_no' => $refund_no
+ );
+ $this->model->where([
+ [
+ 'order_refund_no', '=', $order_refund_no
+ ]
+ ])->update($update_data);
+ $this->finish([
+ 'order_refund_no' => $order_refund_no,
+ 'main_type' => OrderLogDict::SYSTEM,
+ ]);
+ return true;
+ }
+
+ /**
+ * 完成
+ * @param $data
+ * @return void
+ */
+ public function finish($data)
+ {
+ $order_refund_no = $data['order_refund_no'];
+ //查询订单项信息
+ $order_refund_info = $this->model->where([
+ ['order_refund_no', '=', $order_refund_no],
+ ])->findOrEmpty();
+ if ($order_refund_info->isEmpty()) throw new CommonException('SHOP_ORDER_REFUND_IS_NOT_FOUND');//退款已失效
+ if ($order_refund_info['status'] == OrderRefundDict::FINISH) throw new CommonException('SHOP_ORDER_REFUND_IS_INVALID_OR_FINISH');//退款已完成或已失效
+ $update_data = array(
+ 'status' => OrderRefundDict::FINISH,
+ );
+ $order_refund_info->save($update_data);
+
+ //对应的要将订单项设置为已完成
+ $order_goods_where = array(
+ ['order_refund_no', '=', $order_refund_no]
+ );
+ $order_goods_update_data = array(
+ 'status' => OrderGoodsDict::REFUND_FINISH,
+ 'is_enable_refund' => 0,//禁用退款
+ );
+ (new OrderGoods())->where($order_goods_where)->update($order_goods_update_data);
+ //订单完成退款后事件
+ $data['order_refund_no'] = $order_refund_no;
+ $data['refund_data'] = array_merge($order_refund_info->toArray(), $update_data);
+ event('AfterShopOrderRefundFinish', $data);
+
+ //新人专享活动退还参与资格
+ $newcomerRecords = (new NewcomerRecords())->field('sku_ids')->where([
+ ['member_id', '=', $order_refund_info->member_id],
+ ['order_id', '=', $order_refund_info->order_id],
+ ['is_join', '=', 1]
+ ])->findOrEmpty()->toArray();
+ if (!empty($newcomerRecords)) {
+ //判断是否还有未退款的
+ $not_refund_count = (new OrderGoods())->where([
+ ['order_id', '=', $order_refund_info->order_id],
+ ['sku_id', 'in', $newcomerRecords['sku_ids']],
+ ['status', '<>', OrderGoodsDict::REFUND_FINISH]
+ ])->count();
+ if ($not_refund_count == 0) {
+ event("NewcomerActiveJoin", ['member_id' => $order_refund_info->member_id, 'is_join' => 0, 'order_id' => $order_refund_info->order_id]);
+ }
+ }
+ return true;
+ }
+
+ /**
+ * 待转账
+ * @param $order_refund_data
+ * @param $main_type
+ * @param $main_id
+ * @return true
+ */
+ public function toTransfer($order_refund_data, $main_type, $main_id)
+ {
+ if ($order_refund_data['money'] > 0) {
+ $core_refund_service = new \app\service\core\pay\CoreRefundService();
+ $order = (new Order())->where([
+ ['order_id', '=', $order_refund_data['order_id']]
+ ])->findOrEmpty();
+ if ($order->isEmpty()) throw new CommonException('SHOP_ORDER_NOT_FOUND');
+ $refund_no = $core_refund_service->create( $order['out_trade_no'], $order_refund_data['money'], get_lang('SHOP_ORDER_BUYER_APPLY_REFUND'), OrderDict::TYPE, $order_refund_data['order_refund_no']);
+ $this->model->where(
+ [
+ ['order_refund_no', '=', $order_refund_data['order_refund_no']]
+ ]
+ )->update(
+ [
+ 'refund_no' => $refund_no,
+ 'status' => OrderRefundDict::STORE_REFUND_TRANSFERING
+ ]
+ );
+ $core_refund_service->refund( $refund_no, '', RefundDict::BACK, $main_type, $main_id);
+ }
+ //状态改变
+ return true;
+ }
+
+ /**
+ * 退款校验
+ * @param $order_goods_ids
+ * @param $apply_refund_money
+ * @return array
+ */
+ public function refundCheck($order_goods_ids, $apply_refund_money)
+ {
+ if ($apply_refund_money < 0) throw new CommonException('SHOP_ORDER_REFUND_MONEY_LESS_THAN_ZERO');//退款金额不能小于0
+ //查询最大可退款总额
+ $refund_money_array = $this->getOrderRefundMoney($order_goods_ids);
+ $refund_money = $refund_money_array['refund_money'];
+ $comparison = bccomp(bcsub($apply_refund_money, $refund_money), 0);//浮点数直接进行比较会出现精度问题
+ if ($comparison > 0) throw new CommonException('SHOP_ORDER_REFUND_MONEY_GT_ORDER_MONEY');//退款金额不能大于可退款总额
+ return $refund_money_array;
+ }
+
+
+ /**
+ * 获取订单最大可退金额
+ * @param $order_goods_ids
+ * @return array
+ */
+ public function getOrderRefundMoney($order_goods_ids)
+ {
+ //查询订单项信息
+ $refund_money = 0;
+ $order_goods_model = new OrderGoods();
+ $order_goods_list = $order_goods_model->where([['order_goods_id', 'in', $order_goods_ids]])->select();
+ if ($order_goods_list->isEmpty()) throw new CommonException('SHOP_ORDER_IS_INVALID');//订单已失效
+ $order_id = $order_goods_list[0]['order_id'];//订单id
+ $order = (new Order())->where([['order_id', '=', $order_id]])->findOrEmpty();
+ if ($order->isEmpty()) throw new CommonException('SHOP_ORDER_IS_INVALID');//订单已失效
+ if (!in_array($order['status'], [OrderDict::WAIT_DELIVERY, OrderDict::WAIT_TAKE, OrderDict::FINISH])) throw new CommonException('SHOP_ORDER_REFUND_WAIT_PAY_OR_CLOSE');
+ //查询是否是最后一笔退款且还没有退运费
+ $order_goods_count = $order_goods_model->where([['order_id', '=', $order_id], ['is_gift', '=', 0]])->count();
+ $refund_count = $this->model->where([['order_id', '=', $order_id]])->whereNotIn(
+ 'status', [OrderRefundDict::CLOSE, OrderRefundDict::SHOP_ACTIVE_CLOSE_REFUND]
+ )->count();
+ //是否包含运费
+ $is_refund_delivery = 0;
+ if (($refund_count + count($order_goods_ids)) >= $order_goods_count) {//最后一笔退款
+ //判断是否已经退过运费
+ $refund_delivery_count = $this->model->where([['order_id', '=', $order_id], ['is_refund_delivery', '=', 1]])->whereNotIn(
+ 'status', [OrderRefundDict::CLOSE, OrderRefundDict::SHOP_ACTIVE_CLOSE_REFUND]
+ )->count();
+ if ($refund_delivery_count == 0) {//已经退过运费的,就不需要重复再退了
+ $is_refund_delivery = 1;
+ }
+ }
+ foreach ($order_goods_list as $key => $value) {
+ if (!$value['is_enable_refund']) throw new CommonException('SHOP_ORDER_IS_NOT_ENABLE_REFUND');//订单不允许退款
+ //查询有没有正没有关闭的退款
+ if ($value['status'] != OrderGoodsDict::NORMAL) throw new CommonException('SHOP_ORDER_REFUND_IS_REFUND_FINISH');//订单已退款或存在未完成的退款
+ //当前订单项最大可退金额
+ $item_refund_money = $value['goods_money'] - $value['discount_money'] - $value['shop_active_refund_money'];//可退金额
+ if ($is_refund_delivery == 1 && $key == 0) {
+ $item_refund_money += $order['delivery_money'];
+ $order_goods_list[$key]['is_refund_delivery'] = $is_refund_delivery;
+ } else {
+ $order_goods_list[$key]['is_refund_delivery'] = 0;
+ }
+ $order_goods_list[$key]['item_refund_money'] = $item_refund_money;
+ $refund_money += $item_refund_money;
+ }
+ return [
+ 'refund_money' => $refund_money,
+ 'order_goods_list' => $order_goods_list
+ ];
+ }
+}
diff --git a/niucloud/addon/shop/app/service/core/third_addon/order/CoreCreateOrderService.php b/niucloud/addon/shop/app/service/core/third_addon/order/CoreCreateOrderService.php
new file mode 100644
index 000000000..984d7dee6
--- /dev/null
+++ b/niucloud/addon/shop/app/service/core/third_addon/order/CoreCreateOrderService.php
@@ -0,0 +1,733 @@
+ $relate_order_info) {
+ $order_index = $index + 1;
+ //兼容以后得数据 如果不是商城的订单全部跳过
+ if ($relate_order_info['source'] != 'shop') {
+ Log::warning("SHOP_PINTUAN - pintuanCreateOrder 接收到的订单数据 商品来源非商城 跳过,来源ID: {$source_id} 拼团数据来源:" . $relate_order_info['source']);
+ continue;
+ }
+ try {
+ // 提取SKU和商品信息
+ $sku_info = $relate_order_info['sku'] ?? [];
+ $goods_id = $sku_info['source_id'] ?? 0;
+ $sku_id = $sku_info['source_sku_id'] ?? 0;
+ $relate_order_id = $relate_order_info['id'] ?? 0;
+
+ list($check_res, $reason) = $this->checkGoods( $goods_id, $sku_id, $relate_order_info['num']);
+ if (!$check_res) {
+ $failed_orders[] = "第{$order_index}个订单(ID: {$relate_order_id})" . $reason;
+ $return_order_list[$relate_order_id] = [
+ 'relate_order_id' => 0,
+ 'relate_order_item_id' => 0,
+ 'is_success' => 0,
+ 'reason' => $reason
+ ];
+ continue;
+ }
+
+
+ // 检查必要参数
+ if (empty($goods_id) || empty($sku_id)) {
+ $failed_orders[] = "第{$order_index}个订单(ID: {$relate_order_id})缺少商品或SKU信息";
+ continue;
+ }
+
+ // 获取商品类型
+ $goods_model_info = (new Goods())->where([
+ 'goods_id' => $goods_id,
+ ])->field('goods_type')->findOrEmpty()->toArray();
+
+ $goods_type = $goods_model_info['goods_type'] ?? '';
+ $third_type = $goods_type == GoodsDict::VIRTUAL
+ ? OrderDeliveryDict::VIRTUAL
+ : OrderDeliveryDict::EXPRESS;
+ $has_goods_types = [$goods_type];
+
+ $third_cost_list = array_column($relate_order_info['third_cost_list'], null, 'key');
+ // 构建订单数据
+ $temp_order_data = [
+ 'order_type' => OrderDict::TYPE,
+ 'status' => OrderDict::WAIT_DELIVERY,
+ 'body' => $relate_order_info['body'] ?? '',
+ 'member_id' => $relate_order_info['member_id'] ?? 0,
+ 'goods_money' => $relate_order_info['goods_money'] ?? 0,
+ 'delivery_money' => $third_cost_list['delivery_money']['amount'] ?? 0,
+ 'discount_money' => 0,
+ 'order_from' => $relate_order_info['order_from'],
+ 'order_money' => $relate_order_info['order_money'] ?? 0,
+ 'has_goods_types' => $has_goods_types,
+ 'delivery_type' => $third_type,
+ 'taker_name' => $relate_order_info['taker_name'] ?? '',
+ 'taker_mobile' => $relate_order_info['taker_mobile'] ?? '',
+ 'buyer_ask_delivery_time' => '',
+ 'taker_province' => $relate_order_info['taker_province'] ?? 0,
+ 'taker_city' => $relate_order_info['taker_city'] ?? 0,
+ 'taker_district' => $relate_order_info['taker_district'] ?? 0,
+ 'taker_address' => $relate_order_info['taker_address'] ?? '',
+ 'taker_full_address' => $relate_order_info['taker_full_address'] ?? '',
+ 'taker_longitude' => $relate_order_info['taker_longitude'] ?? '',
+ 'taker_latitude' => $relate_order_info['taker_latitude'] ?? '',
+ 'take_store_id' => 0,
+ 'member_remark' => '',
+ 'order_no' => create_no(),
+ 'is_enable_refund' => 1,
+ 'invoice_id' => 0,
+ 'out_trade_no' => $relate_order_info['out_trade_no'] ?? '',
+ 'relate_id' => $source_id,
+ 'relate_order_id' => $relate_order_id,
+ 'relate_source' => $source,
+ 'activity_type' => $source,
+ 'create_time' => strtotime($relate_order_info['create_time']),
+ 'pay_time' => strtotime($relate_order_info['pay_time']),
+ 'pay_money' => $relate_order_info['pay_money'] ?? 0,
+ ];
+ $order_info = (new Order())->where([
+ 'relate_id' => $source_id,
+ 'relate_source' => $source,
+ 'relate_order_id' => $relate_order_id,
+ ])->findOrEmpty();
+ if (!$order_info->isEmpty()) {
+ // 修改订单
+ $shop_order_id = $order_info['order_id'];
+ Log::write("SHOP_PINTUAN - pintuanCreateOrder 订单已存在 订单ID: {$shop_order_id}");
+ } else {
+ // 创建订单
+ $shop_order_id = (new Order())->insertGetId($temp_order_data);
+ Log::write("SHOP_PINTUAN - pintuanCreateOrder 创建订单成功 订单ID: {$shop_order_id}");
+ }
+
+
+ if (!$shop_order_id) {
+ $failed_orders[] = "第{$order_index}个订单(ID: {$relate_order_id})创建失败";
+ continue;
+ }
+
+ // 构建订单商品数据
+ $goods_info = $sku_info['goods'] ?? [];
+ $goods_single_money = ($relate_order_info['goods_money'] ?? 0) / ($relate_order_info['num'] ?? 1);
+ $order_goods_data = [
+ 'member_id' => $relate_order_info['member_id'] ?? 0,
+ 'goods_id' => $goods_id,
+ 'sku_id' => $sku_id,
+ 'goods_name' => $goods_info['title'] ?? '',
+ 'sku_name' => $sku_info['sku_name'] ?? '',
+ 'goods_image' => $goods_info['cover'] ?? '',
+ 'sku_image' => $sku_info['sku_image'] ?? '',
+ 'price' => $goods_single_money,
+ 'original_price' => $sku_info['price_config']['original'] ?? 0,
+ 'num' => $relate_order_info['num'] ?? 0,
+ 'goods_money' => ($relate_order_info['goods_money'] ?? 0),
+ 'goods_type' => $goods_type,
+ 'order_goods_money' => $goods_single_money,
+ 'order_id' => $shop_order_id,
+ 'discount_money' => 0,
+ 'status' => OrderGoodsDict::NORMAL,
+ 'delivery_status' => OrderDeliveryDict::WAIT_DELIVERY,
+ 'extend' => '',
+ 'is_gift' => 0,
+ 'is_enable_refund' => 1,
+ ];
+ $order_goods_id = (new OrderGoods())->insertGetId($order_goods_data);
+ Log::write("SHOP_PINTUAN - pintuanCreateOrder 创建订单商品成功 订单商品ID: {$order_goods_id}");
+
+ $return_order_list[$relate_order_id] = [
+ 'relate_order_id' => $shop_order_id,
+ 'relate_order_item_id' => $order_goods_id,
+ 'is_success' => 1
+ ];
+ $temp_order_data['order_id'] = $shop_order_id;
+ Log::write("SHOP_PINTUAN - orderCreateAfter 触发事件");
+
+ CoreOrderEventService::orderCreateAfter([
+ 'order_id' => $shop_order_id,
+ 'order_data' => $temp_order_data,
+ 'order_goods_data' => [$order_goods_data],
+ 'cart_ids' => [],
+ 'basic' => [],
+ 'main_type' => OrderLogDict::MEMBER,
+ 'main_id' => $relate_order_info['member_id'] ?? 0,
+ 'time' => time()
+ ]);
+ Log::write("SHOP_PINTUAN - orderPayAfter 触发事件");
+
+ CoreOrderEventService::orderPayAfter([
+ 'order_id' => $shop_order_id,
+ 'order_data' => $temp_order_data,
+ 'order_goods_data' => [$order_goods_data],
+ 'cart_ids' => [],
+ 'basic' => [],
+ 'main_type' => OrderLogDict::MEMBER,
+ 'main_id' => $relate_order_info['member_id'] ?? 0,
+ 'time' => time(),
+ 'send_notice' => 0
+ ]);
+ $processed_orders++;
+ } catch (\Exception $e) {
+ $failed_orders[] = "第{$order_index}个订单(ID: {$shop_order_id})处理异常: {$e->getMessage()}";
+ Log::error("SHOP_PINTUAN - pintuanCreateOrder 拼团订单处理失败," . $e->getFile() . $e->getFile() . $e->getMessage() . $e->getTraceAsString());
+
+ }
+ }
+ // 合并结果日志:包含统计和失败信息
+ $result_log = ["总订单数: {$total_orders}", "成功处理: {$processed_orders}", "失败订单: " . count($failed_orders)];
+ if (!empty($failed_orders)) {
+ $result_log[] = "失败详情: " . implode('; ', $failed_orders);
+ }
+ Log::write("SHOP_PINTUAN - pintuanCreateOrder 拼团订单处理完成," . implode('; ', $result_log));
+
+ return $return_order_list;
+ }
+ public function friendHelpCreateOrder(array $data)
+ {
+ $return_order_list = [];
+ $source_id = $data['source_id'] ?? 0;
+ $source = $data['source'] ?? '';
+ $relate_order_list = $data['order_data'] ?? [];
+ $total_orders = count($relate_order_list);
+
+ // 合并初始日志:包含关键参数和总数
+ Log::write("SHOP_FRIEND_HELP - friend_helpCreateOrder 开始处理好友助力订单,订单信息" . json_encode($relate_order_list, 256));
+ Log::write("SHOP_FRIEND_HELP - friend_helpCreateOrder 开始处理好友助力订单,来源ID: {$source_id},总订单数: {$total_orders}");
+
+ if (empty($relate_order_list)) {
+ Log::warning("SHOP_FRIEND_HELP - friend_helpCreateOrder 接收到的订单数据为空,来源ID: {$source_id}");
+ return;
+ }
+
+ $processed_orders = 0;
+ $failed_orders = []; // 记录失败订单信息
+
+ foreach ($relate_order_list as $index => $relate_order_info) {
+ $order_index = $index + 1;
+ //兼容以后得数据 如果不是商城的订单全部跳过
+ if ($relate_order_info['source'] != 'shop') {
+ Log::warning("SHOP_FRIEND_HELP - friend_helpCreateOrder 接收到的订单数据 商品来源非商城 跳过,来源ID: {$source_id} 好友助力数据来源:" . $relate_order_info['source']);
+ continue;
+ }
+ try {
+ // 提取SKU和商品信息
+ $sku_info = $relate_order_info['sku'] ?? [];
+ $goods_id = $sku_info['source_id'] ?? 0;
+ $sku_id = $sku_info['source_sku_id'] ?? 0;
+ $relate_order_id = $relate_order_info['id'] ?? 0;
+
+ list($check_res, $reason) = $this->checkGoods( $goods_id, $sku_id, $relate_order_info['num']);
+ if (!$check_res) {
+ $failed_orders[] = "第{$order_index}个订单(ID: {$relate_order_id})" . $reason;
+ $return_order_list[$relate_order_id] = [
+ 'relate_order_id' => 0,
+ 'relate_order_item_id' => 0,
+ 'is_success' => 0,
+ 'reason' => $reason
+ ];
+ continue;
+ }
+
+
+ // 检查必要参数
+ if (empty($goods_id) || empty($sku_id)) {
+ $failed_orders[] = "第{$order_index}个订单(ID: {$relate_order_id})缺少商品或SKU信息";
+ continue;
+ }
+
+ // 获取商品类型
+ $goods_model_info = (new Goods())->where([
+ 'goods_id' => $goods_id,
+ ])->field('goods_type')->findOrEmpty()->toArray();
+
+ $goods_type = $goods_model_info['goods_type'] ?? '';
+ $third_type = $goods_type == GoodsDict::VIRTUAL
+ ? OrderDeliveryDict::VIRTUAL
+ : OrderDeliveryDict::EXPRESS;
+ $has_goods_types = [$goods_type];
+
+ $third_cost_list = array_column($relate_order_info['third_cost_list'], null, 'key');
+ // 构建订单数据
+ $temp_order_data = [
+ 'order_type' => OrderDict::TYPE,
+ 'status' => OrderDict::WAIT_DELIVERY,
+ 'body' => $relate_order_info['body'] ?? '',
+ 'member_id' => $relate_order_info['member_id'] ?? 0,
+ 'goods_money' => $relate_order_info['goods_money'] ?? 0,
+ 'delivery_money' => $third_cost_list['delivery_money']['amount'] ?? 0,
+ 'discount_money' => 0,
+ 'order_from' => $relate_order_info['order_from'],
+ 'order_money' => $relate_order_info['order_money'] ?? 0,
+ 'has_goods_types' => $has_goods_types,
+ 'delivery_type' => $third_type,
+ 'taker_name' => $relate_order_info['taker_name'] ?? '',
+ 'taker_mobile' => $relate_order_info['taker_mobile'] ?? '',
+ 'buyer_ask_delivery_time' => '',
+ 'taker_province' => $relate_order_info['taker_province'] ?? 0,
+ 'taker_city' => $relate_order_info['taker_city'] ?? 0,
+ 'taker_district' => $relate_order_info['taker_district'] ?? 0,
+ 'taker_address' => $relate_order_info['taker_address'] ?? '',
+ 'taker_full_address' => $relate_order_info['taker_full_address'] ?? '',
+ 'taker_longitude' => $relate_order_info['taker_longitude'] ?? '',
+ 'taker_latitude' => $relate_order_info['taker_latitude'] ?? '',
+ 'take_store_id' => 0,
+ 'member_remark' => '',
+ 'order_no' => create_no(),
+ 'is_enable_refund' => 1,
+ 'invoice_id' => 0,
+ 'out_trade_no' => $relate_order_info['out_trade_no'] ?? '',
+ 'relate_id' => $source_id,
+ 'relate_order_id' => $relate_order_id,
+ 'relate_source' => $source,
+ 'activity_type' => $source,
+ 'create_time' => strtotime($relate_order_info['create_time']),
+ 'pay_time' => strtotime($relate_order_info['pay_time']),
+ 'pay_money' => $relate_order_info['pay_money'] ?? 0,
+ ];
+ $order_info = (new Order())->where([
+ 'relate_id' => $source_id,
+ 'relate_source' => $source,
+ 'relate_order_id' => $relate_order_id,
+ ])->findOrEmpty();
+ if (!$order_info->isEmpty()) {
+ // 修改订单
+ $shop_order_id = $order_info['order_id'];
+ Log::write("SHOP_FRIEND_HELP - friend_helpCreateOrder 订单已存在 订单ID: {$shop_order_id}");
+ } else {
+ // 创建订单
+ $shop_order_id = (new Order())->insertGetId($temp_order_data);
+ Log::write("SHOP_FRIEND_HELP - friend_helpCreateOrder 创建订单成功 订单ID: {$shop_order_id}");
+ }
+
+
+ if (!$shop_order_id) {
+ $failed_orders[] = "第{$order_index}个订单(ID: {$relate_order_id})创建失败";
+ continue;
+ }
+
+ // 构建订单商品数据
+ $goods_info = $sku_info['goods'] ?? [];
+ $goods_single_money = ($relate_order_info['goods_money'] ?? 0) / ($relate_order_info['num'] ?? 1);
+ $order_goods_data = [
+ 'member_id' => $relate_order_info['member_id'] ?? 0,
+ 'goods_id' => $goods_id,
+ 'sku_id' => $sku_id,
+ 'goods_name' => $goods_info['title'] ?? '',
+ 'sku_name' => $sku_info['sku_name'] ?? '',
+ 'goods_image' => $goods_info['cover'] ?? '',
+ 'sku_image' => $sku_info['sku_image'] ?? '',
+ 'price' => $goods_single_money,
+ 'original_price' => $sku_info['price_config']['original'] ?? 0,
+ 'num' => $relate_order_info['num'] ?? 0,
+ 'goods_money' => ($relate_order_info['goods_money'] ?? 0),
+ 'goods_type' => $goods_type,
+ 'order_goods_money' => $goods_single_money,
+ 'order_id' => $shop_order_id,
+ 'discount_money' => 0,
+ 'status' => OrderGoodsDict::NORMAL,
+ 'delivery_status' => OrderDeliveryDict::WAIT_DELIVERY,
+ 'extend' => '',
+ 'is_gift' => 0,
+ 'is_enable_refund' => 1,
+ ];
+ $order_goods_id = (new OrderGoods())->insertGetId($order_goods_data);
+ Log::write("SHOP_FRIEND_HELP - friend_helpCreateOrder 创建订单商品成功 订单商品ID: {$order_goods_id}");
+
+ $return_order_list[$relate_order_id] = [
+ 'relate_order_id' => $shop_order_id,
+ 'relate_order_item_id' => $order_goods_id,
+ 'is_success' => 1
+ ];
+ $temp_order_data['order_id'] = $shop_order_id;
+ Log::write("SHOP_FRIEND_HELP - orderCreateAfter 触发事件");
+
+ CoreOrderEventService::orderCreateAfter([
+ 'order_id' => $shop_order_id,
+ 'order_data' => $temp_order_data,
+ 'order_goods_data' => [$order_goods_data],
+ 'cart_ids' => [],
+ 'basic' => [],
+ 'main_type' => OrderLogDict::MEMBER,
+ 'main_id' => $relate_order_info['member_id'] ?? 0,
+ 'time' => time()
+ ]);
+ Log::write("SHOP_FRIEND_HELP - orderPayAfter 触发事件");
+
+ CoreOrderEventService::orderPayAfter([
+ 'order_id' => $shop_order_id,
+ 'order_data' => $temp_order_data,
+ 'order_goods_data' => [$order_goods_data],
+ 'cart_ids' => [],
+ 'basic' => [],
+ 'main_type' => OrderLogDict::MEMBER,
+ 'main_id' => $relate_order_info['member_id'] ?? 0,
+ 'time' => time(),
+ 'send_notice' => 0
+ ]);
+ $processed_orders++;
+ } catch (\Exception $e) {
+ $failed_orders[] = "第{$order_index}个订单(ID: {$shop_order_id})处理异常: {$e->getMessage()}";
+ Log::error("SHOP_FRIEND_HELP - friend_helpCreateOrder 好友助力订单处理失败," . $e->getFile() . $e->getFile() . $e->getMessage() . $e->getTraceAsString());
+
+ }
+ }
+ // 合并结果日志:包含统计和失败信息
+ $result_log = ["总订单数: {$total_orders}", "成功处理: {$processed_orders}", "失败订单: " . count($failed_orders)];
+ if (!empty($failed_orders)) {
+ $result_log[] = "失败详情: " . implode('; ', $failed_orders);
+ }
+ Log::write("SHOP_FRIEND_HELP - friend_helpCreateOrder 好友助力订单处理完成," . implode('; ', $result_log));
+
+ return $return_order_list;
+ }
+
+ /**
+ * 接龙订单处理
+ * @param array $data
+ * @return array
+ */
+ public function relayCreateOrder(array $data): array
+ {
+ // 初始化返回数据
+ $return_order_list = [];
+
+ // 提取基础参数并设置默认值
+ $source_id = $data['source_id'] ?? 0;//接龙 一个订单的订单项可以来自不同的活动
+ $source = $data['source'] ?? '';
+ $relate_order_list = $data['order_data'] ?? [];
+ $total_orders = count($relate_order_list);
+
+ // 记录开始日志
+ Log::write("SHOP_RELAY - 开始处理接龙订单,来源ID: {$source_id},总订单数: {$total_orders}");
+ Log::write("SHOP_RELAY - 订单数据: " . json_encode($relate_order_list, JSON_UNESCAPED_UNICODE));
+
+ // 订单数据为空时直接返回
+ if (empty($relate_order_list)) {
+ Log::warning("SHOP_RELAY - 接收到的订单数据为空,来源ID: {$source_id}");
+ return $return_order_list;
+ }
+
+ // 初始化统计变量
+ $processed_orders = 0;
+ $failed_orders = [];
+
+ // 遍历处理每个订单
+ foreach ($relate_order_list as $index => $relate_order_info) {
+
+ $order_index = $index + 1;
+ $relay_order_id = $relate_order_info['id'] ?? 0;
+
+ // 过滤非商城来源订单
+ if ($relate_order_info['source'] != 'shop') {
+ Log::warning("SHOP_RELAY - 订单来源非商城,跳过处理,索引: {$order_index},来源: {$relate_order_info['source']}");
+ continue;
+ }
+
+ try {
+ // 1. 商品校验与类型获取
+ $goods_types = [];
+ $all_check_res = true;
+ //检测订单项 商品是否可用 主要是为了获取订单项的goods_type
+ foreach ($relate_order_info['goods'] as $order_item) {
+ if ($order_item['source'] != 'shop'){
+ continue;
+ }
+ $relay_order_goods_id = $order_item['id'] ?? 0;
+ $goods_id = $order_item['sku']['source_id'] ?? 0;
+ $sku_id = $order_item['sku']['source_sku_id'] ?? 0;
+ $num = $order_item['num'] ?? 1;
+
+ // 获取商品类型
+ $goods_model_info = (new Goods())->where([
+ 'goods_id' => $goods_id,
+ ])->field('goods_type')->findOrEmpty()->toArray();
+
+ $goods_type = $goods_model_info['goods_type'] ?? '';
+ $goods_types[$order_item['order_id']] = $goods_type;
+
+ // 商品规格校验
+ list($check_res, $reason) = $this->checkGoods($goods_id, $sku_id, $num);
+ if (!$check_res) {
+ $all_check_res = false;
+ $return_order_list[$relay_order_goods_id] = [
+ 'source_order_id' => $relay_order_id,
+ 'source_order_item_id' => $relay_order_goods_id,
+ 'relate_order_id' => 0,
+ 'relate_order_item_id' => 0,
+ 'is_success' => 0,
+ 'reason' => $reason,
+ ];
+ }
+ }
+
+ // 校验失败处理
+ if (!$all_check_res) {
+ //有校验未通过的订单项,停止同步订单
+ break;
+ }
+
+ // 2. 构建订单数据
+ $third_cost_list = array_column($relate_order_info['third_cost_list'], null, 'key');
+ $has_goods_types = array_values($goods_types);
+ $delivery_type = in_array(OrderDeliveryDict::EXPRESS, $has_goods_types)
+ ? OrderDeliveryDict::EXPRESS
+ : OrderDeliveryDict::VIRTUAL;
+
+ $temp_order_data = [
+ 'order_type' => OrderDict::TYPE,
+ 'status' => OrderDict::WAIT_DELIVERY,
+ 'body' => $relate_order_info['body'] ?? '',
+ 'member_id' => $relate_order_info['member_id'] ?? 0,
+ 'goods_money' => $relate_order_info['goods_money'] ?? 0,
+ 'delivery_money' => $third_cost_list['delivery_money']['amount'] ?? 0,
+ 'discount_money' => 0,
+ 'order_from' => $relate_order_info['order_from'] ?? '',
+ 'order_money' => $relate_order_info['order_money'] ?? 0,
+ 'has_goods_types' => $has_goods_types,
+ 'delivery_type' => $delivery_type,
+ 'taker_name' => $relate_order_info['taker_name'] ?? '',
+ 'taker_mobile' => $relate_order_info['taker_mobile'] ?? '',
+ 'buyer_ask_delivery_time' => '',
+ 'taker_province' => $relate_order_info['taker_province'] ?? 0,
+ 'taker_city' => $relate_order_info['taker_city'] ?? 0,
+ 'taker_district' => $relate_order_info['taker_district'] ?? 0,
+ 'taker_address' => $relate_order_info['taker_address'] ?? '',
+ 'taker_full_address' => $relate_order_info['taker_full_address'] ?? '',
+ 'taker_longitude' => $relate_order_info['taker_longitude'] ?? '',
+ 'taker_latitude' => $relate_order_info['taker_latitude'] ?? '',
+ 'take_store_id' => 0,
+ 'member_remark' => '',
+ 'order_no' => create_no(),
+ 'is_enable_refund' => 1,
+ 'invoice_id' => 0,
+ 'out_trade_no' => $relate_order_info['out_trade_no'] ?? '',
+ 'relate_id' => $source_id,
+ 'relate_order_id' => $relay_order_id,
+ 'relate_source' => $source,
+ 'activity_type' => $source,
+ 'create_time' => strtotime($relate_order_info['create_time'] ?? ''),
+ 'pay_time' => strtotime($relate_order_info['pay_time'] ?? ''),
+ 'pay_money' => $relate_order_info['pay_money'] ?? 0,
+ ];
+
+ // 3. 检查订单是否已存在,存在则更新,不存在则创建
+ $order_model = new Order();
+ $order_info = $order_model->where([
+ 'relate_id' => $source_id,
+ 'relate_source' => $source,
+ 'relate_order_id' => $relay_order_id,
+ ])->findOrEmpty();
+
+ if (!$order_info->isEmpty()) {
+ $shop_order_id = $order_info['order_id'];
+ Log::write("SHOP_RELAY - 订单已存在 订单ID: {$shop_order_id}");
+ } else {
+ $shop_order_id = $order_model->insertGetId($temp_order_data);
+ Log::write("SHOP_RELAY - 创建订单成功 订单ID: {$shop_order_id}");
+ }
+
+ // 订单创建失败处理
+ if (!$shop_order_id) {
+ $fail_msg = "第{$order_index}个订单(ID: {$relay_order_id})创建失败";
+ $failed_orders[] = $fail_msg;
+ $return_order_list['main_order'] = [
+ 'source_order_id' => $relay_order_id,
+ 'source_order_item_id' => 0,
+ 'relate_order_id' => $shop_order_id,
+ 'relate_order_item_id' => 0,
+ 'is_success' => 0,
+ 'reason' => $fail_msg,
+ ];
+ continue;
+ }else{
+ $return_order_list['main_order'] = [
+ 'source_order_id' => $relay_order_id,
+ 'source_order_item_id' => 0,
+ 'relate_order_id' => $shop_order_id,
+ 'relate_order_item_id' => 0,
+ 'is_success' => 1,
+ 'reason' => '',
+ ];
+ }
+
+ // 4. 处理订单商品
+ $order_goods_data = [];
+ $order_goods_ids = [];
+ foreach ($relate_order_info['goods'] as $order_item) {
+ if ($order_item['source'] != 'shop'){
+ continue;
+ }
+ $relay_order_goods_id = $order_item['id'] ?? [];
+ $goods_info = $order_item['sku']['goods'] ?? [];
+ $sku_info = $order_item['sku'] ?? [];
+ $goods_single_money = ($order_item['goods_money'] ?? 0) / ($order_item['num'] ?? 1);
+
+ $order_goods_item = [
+ 'order_id' => $shop_order_id,
+ 'member_id' => $order_item['member_id'] ?? 0,
+ 'goods_id' => $goods_info['source_id'] ?? 0,
+ 'sku_id' => $sku_info['source_sku_id'] ?? 0,
+ 'goods_name' => $goods_info['title'] ?? '',
+ 'sku_name' => $sku_info['sku_name'] ?? '',
+ 'goods_image' => $goods_info['cover'] ?? '',
+ 'sku_image' => $sku_info['sku_image'] ?? '',
+ 'price' => $goods_single_money,
+ 'original_price' => $sku_info['price_config']['original'] ?? 0,
+ 'num' => $order_item['num'] ?? 0,
+ 'goods_money' => $order_item['goods_money'] ?? 0,
+ 'goods_type' => $goods_types[$order_item['id']] ?? '',
+ 'order_goods_money' => $goods_single_money,
+ 'discount_money' => 0,
+ 'status' => OrderGoodsDict::NORMAL,
+ 'delivery_status' => OrderDeliveryDict::WAIT_DELIVERY,
+ 'extend' => '',
+ 'is_gift' => 0,
+ 'is_enable_refund' => 1,
+ ];
+ $relate_order_goods_info = (new OrderGoods())->where([
+ 'order_id' => $shop_order_id,
+ 'member_id' => $order_item['member_id'] ?? 0,
+ 'goods_id' => $goods_info['source_id'] ?? 0,
+ 'sku_id' => $sku_info['source_sku_id'] ?? 0,
+ ])->findOrEmpty();
+ if (!$relate_order_goods_info->isEmpty()) {
+ $relate_order_goods_id = $relate_order_goods_info->order_goods_id;
+ }else{
+ $relate_order_goods_id = (new OrderGoods())->insertGetId($order_goods_item);
+ }
+ //记录成功订单项
+ $return_order_list[$relay_order_goods_id] = [
+ 'source_order_id' => $relay_order_id,
+ 'source_order_item_id' => $relay_order_goods_id,
+ 'relate_order_id' => $shop_order_id,
+ 'relate_order_item_id' => $relate_order_goods_id,
+ 'is_success' => 1,
+ 'reason' => '',
+ ];
+ Log::write("SHOP_RELAY - 创建订单商品成功 订单商品ID: {$relay_order_goods_id}");
+
+ $order_goods_ids[$order_item['id']] = $relay_order_goods_id;
+ $order_goods_data[] = $order_goods_item;
+ }
+
+ // 5. 触发订单后续事件
+ $temp_order_data['order_id'] = $shop_order_id;
+ Log::write("SHOP_RELAY - 触发 orderCreateAfter 事件");
+
+ CoreOrderEventService::orderCreateAfter([
+ 'order_id' => $shop_order_id,
+ 'order_data' => $temp_order_data,
+ 'order_goods_data' => $order_goods_data,
+ 'cart_ids' => [],
+ 'basic' => [],
+ 'main_type' => OrderLogDict::MEMBER,
+ 'main_id' => $relate_order_info['member_id'] ?? 0,
+ 'time' => time()
+ ]);
+
+ Log::write("SHOP_RELAY - 触发 orderPayAfter 事件");
+ CoreOrderEventService::orderPayAfter([
+ 'order_id' => $shop_order_id,
+ 'order_data' => $temp_order_data,
+ 'order_goods_data' => $order_goods_data,
+ 'cart_ids' => [],
+ 'basic' => [],
+ 'main_type' => OrderLogDict::MEMBER,
+ 'main_id' => $relate_order_info['member_id'] ?? 0,
+ 'time' => time(),
+ 'send_notice' => 0
+ ]);
+ $processed_orders++;
+
+ } catch (\Exception $e) {
+ $failed_orders[] = "第{$order_index}个订单 处理异常: {$e->getMessage()}";
+ Log::error("SHOP_RELAY - relayCreateOrder 拼团订单处理失败," . $e->getFile() . $e->getFile() . $e->getMessage());
+ }
+ }
+
+ // 记录处理结果日志
+ $result_log = [
+ "总订单数: {$total_orders}",
+ "成功处理: {$processed_orders}",
+ "失败订单: " . count($failed_orders)
+ ];
+ if (!empty($failed_orders)) {
+ $result_log[] = "失败详情: " . implode('; ', $failed_orders);
+ }
+ Log::write("SHOP_RELAY - 接龙订单处理完成," . implode('; ', $result_log));
+ Log::write("SHOP_RELAY - 接龙订单处理完成, 返回数据:" . json_encode($return_order_list));
+
+ return $return_order_list;
+ }
+
+ private function checkGoods($goods_id, $sku_id, $num = 1)
+ {
+ $goods_info = (new Goods())->where([
+ 'goods_id' => $goods_id,
+ ])->findOrEmpty();
+ if ($goods_info->isEmpty()) {
+ return [false, get_lang('SHOP_GOODS_NOT_EXIST')];
+ }
+ $sku_info = (new GoodsSku())->where([
+ 'goods_id' => $goods_id,
+ 'sku_id' => $sku_id,
+ ])->findOrEmpty();
+ if ($sku_info->isEmpty()) {
+ return [false, get_lang('SHOP_GOODS_NOT_EXIST')];
+ }
+ $stock = $sku_info['stock'] ?? 0;
+ return [$stock >= $num, get_lang('SHOP_ORDER_GOODS_INSUFFICIENT')];
+ }
+}
diff --git a/niucloud/addon/shop/app/service/core/third_addon/order/CoreOrderDeliveryService.php b/niucloud/addon/shop/app/service/core/third_addon/order/CoreOrderDeliveryService.php
new file mode 100644
index 000000000..d61e43837
--- /dev/null
+++ b/niucloud/addon/shop/app/service/core/third_addon/order/CoreOrderDeliveryService.php
@@ -0,0 +1,166 @@
+model = new Order();
+ }
+
+ /**
+ * 订单参数设置
+ * @param $params
+ * @return void
+ */
+ public function setParams($params)
+ {
+ $param = [
+ 'delivery' => [
+ 'delivery_type' => 'express',
+ ],
+ 'take_address' => [
+ 'province_id' => $params['province_id'] ?? '',
+ 'city_id' => $params['city_id'] ?? '',
+ 'district_id' => $params['district_id'] ?? '',
+ ],
+ 'sku_data' => [
+ [
+ 'sku_id' => $params['source_sku_id'],
+ 'num' => $params['num'],
+ ]
+ ],
+ 'member_id'=>$params['member_id'] ?? ''
+ ];
+
+ if(empty($param['take_address']['province_id'])){
+ // 获取默认地址
+ $param['take_address'] = ( new CoreMemberAddressService() )->getDefaultAddressByMemberId($params['member_id']);
+ }
+ $this->member_id = $param['member_id'];
+ $this->delivery = $param['take_address'];
+ $this->param = $param;
+ $this->extend_data = $this->param[ 'extend_data' ] ?? [];
+ }
+
+
+ /**
+ * 计算运费
+ * @param array $data
+ * @return void
+ */
+ public function calculate(array $data)
+ {
+ //参数初始化
+ $this->setParams($data);
+ //查询商品信息
+ $this->getGoodsData();
+ if (in_array(GoodsDict::VIRTUAL, $this->basic['has_goods_types'])) {
+ $this->delivery['delivery_type'] = OrderDeliveryDict::VIRTUAL;
+ } else {
+ $this->delivery['delivery_type'] = 'express';
+ }
+ $this->getDelivery();
+ //计算运费
+ $this->calculateDelivery();
+ return $this->basic[ 'delivery_money' ];
+ }
+
+
+
+ /**
+ * 商品相关数据
+ * @return array
+ * @throws DataNotFoundException
+ * @throws DbException
+ * @throws ModelNotFoundException
+ */
+ public function getGoodsData()
+ {
+ $this->extend_data = $this->param['extend_data'] ?? [];
+ $sku_data = $this->param['sku_data'] ?? [];
+ if (empty($sku_data)) throw new CommonException(get_lang('SHOP_GOODS_DELISTED'));//无效的数据
+ $sku_ids = array_column($sku_data, 'sku_id');
+ $sku_condition = array(
+ ['sku_id', 'in', $sku_ids]
+ );
+ $sku_list = (new GoodsSku())->where($sku_condition)->with(['goods'])->field('sku_id, sku_name, sku_image, goods_id, price, stock, weight, volume,sku_id, sku_spec_format,member_price, sale_price')->select()->toArray();
+ $sku_list = array_column($sku_list, null, 'sku_id');
+ //商品数据 查询商品列表
+ $order_data = [];
+ $goods_list = [];
+ $goods_money = 0;
+ $total_num = 0;
+ $body = '';
+ //订单中包含的商品形式
+ $has_goods_types = [];
+ foreach ($sku_data as $v) {
+ $sku_id = $v['sku_id'];
+ $num = $v['num'];
+ $total_num += $num;
+ $market_type = $v['market_type'] ?? '';
+ $market_type_id = $v['market_type_id'] ?? 0;
+ $sku_info = $sku_list[$sku_id] ?? [];
+ if (empty($sku_info) || empty($sku_info['goods'])) throw new CommonException(get_lang('SHOP_GOODS_DELISTED'));//无效的商品
+ $sku_info['member_discount'] = $sku_info['goods']['member_discount'] ?? '';
+ //商品原价
+ $sku_info['original_price'] = $sku_info['price'];
+ //获取活动价格
+ $sku_info['show_type'] = 'original_price';
+ $sku_info['discount_money'] = 0;
+ $item_goods_type = $sku_info['goods']['goods_type'];
+
+ if (!in_array($item_goods_type, $has_goods_types)) $has_goods_types[] = $item_goods_type;
+
+ $sku_info['num'] = $num;
+ $sku_info['market_type'] = $market_type;//活动类型
+ $sku_info['market_type_id'] = $market_type_id;//活动id
+ // 计算商品小计
+ $price = $sku_info['price'];
+ $sku_info['goods_money'] = $price * $num;
+ $goods_money += $sku_info['goods_money'];
+ $body = $body ? $body . ($sku_info['sku_name'] . $sku_info['goods']['goods_name']) : ($sku_info['sku_name'] . $sku_info['goods']['goods_name']);
+ $goods_list[$sku_id] = $sku_info;
+ }
+
+ $this->basic['has_goods_types'] = $has_goods_types;
+ $this->basic['total_num'] = $total_num;
+ $this->goods_data = $goods_list;
+ $this->basic['goods_money'] = $goods_money;
+ $this->basic['body'] = $body;
+ return $order_data;
+ }
+
+
+}
diff --git a/niucloud/addon/shop/app/service/core/third_addon/order/CoreOrderNoticeService.php b/niucloud/addon/shop/app/service/core/third_addon/order/CoreOrderNoticeService.php
new file mode 100644
index 000000000..77be8c5a8
--- /dev/null
+++ b/niucloud/addon/shop/app/service/core/third_addon/order/CoreOrderNoticeService.php
@@ -0,0 +1,89 @@
+ 'shop',
+ 'source_order_id' => $refund_data['order_id'],
+ 'relate_source' => $relate_source,
+ 'relate_order_id' => $relate_order_id,
+ 'refund_type' => $refund_data[ 'refund_type' ],
+ 'refund_reason' => $refund_data[ 'reason' ],
+ 'remark' => $refund_data[ 'remark' ],
+ 'refund_voucher' => $refund_data[ 'voucher' ],
+ 'order_refund_no'=>$refund_data['order_refund_no'],
+ ]);
+ }
+
+ /**
+ * 发送给插件 - 商城订单退款关闭通知
+ * @param $refund_data
+ * @param $relate_source
+ * @param $relate_order_id
+ * @return void
+ */
+ public function sendRefundCloseNotice($refund_data, $relate_source, $relate_order_id)
+ {
+ event('ThirdOrderRefundCloseNotice', [
+ 'source' => 'shop',
+ 'source_order_id' => $refund_data['order_id'],
+ 'relate_source' => $relate_source,
+ 'relate_order_id' => $relate_order_id,
+ 'reason' => $refund_data['reason'],
+ 'refund_no' => $refund_data['refund_no'],
+ ]);
+ }
+ /**
+ * 发送给插件 - 商城订单退款完成通知
+ * @param $refund_data
+ * @param $relate_source
+ * @param $relate_order_id
+ * @return void
+ */
+ public function sendRefundFinishNotice($refund_data, $relate_source, $relate_order_id)
+ {
+ event('ThirdOrderRefundFinishNotice', [
+ 'source' => 'shop',
+ 'source_order_id' => $refund_data['order_id'],
+ 'source_order_item_id' => $refund_data['order_goods_id'],
+ 'relate_source' => $relate_source,
+ 'relate_order_id' => $relate_order_id,
+ 'reason' => $refund_data['reason'],
+ 'refund_type' => $refund_data['refund_type'],
+ 'apply_time' => $refund_data['create_time'],
+ 'apply_money' => $refund_data['apply_money'],
+ 'is_refund_third_cost' => $refund_data['is_refund_delivery'],//是否退三方费用 比如退配送费
+ 'money' => $refund_data['money'],
+ 'refund_no' => $refund_data['refund_no'],
+ 'order_refund_no'=>$refund_data['order_refund_no'],
+ ]);
+ }
+
+
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/app/service/core/third_addon/order/CoreSeckillOrderCreateService.php b/niucloud/addon/shop/app/service/core/third_addon/order/CoreSeckillOrderCreateService.php
new file mode 100644
index 000000000..b5ab7d276
--- /dev/null
+++ b/niucloud/addon/shop/app/service/core/third_addon/order/CoreSeckillOrderCreateService.php
@@ -0,0 +1,375 @@
+model = new Order();
+ }
+
+
+ /**
+ * 秒杀订单参数设置
+ * @param $params
+ * @return void
+ */
+ public function setSeckillParam($params)
+ {
+ $param = [
+ 'order_from' => $params['order_from'] ?? '',
+ 'member_id' => $params['member_id'],
+ 'extend_data' => [
+ 'relate_id' => $params['seckill_id'],
+ 'relate_order_id' => $params['id'],
+ 'relate_source' => 'seckill'
+ ],
+ 'delivery' => [
+ 'delivery_type' => 'express',
+ ],
+ 'take_address' => [
+ 'taker_name' => $params['taker_name'],
+ 'taker_mobile' => $params['taker_mobile'],
+ 'taker_province' => $params['taker_province'],
+ 'taker_city' => $params['taker_city'],
+ 'taker_district' => $params['taker_district'],
+ 'taker_address' => $params['taker_address'],
+ 'taker_full_address' => $params['taker_full_address'],
+ 'taker_longitude' => $params['taker_longitude'] ?? '',
+ 'taker_latitude' => $params['taker_latitude'] ?? '',
+ ],
+ 'sku_data' => [
+ [
+ 'sku_id' => $params['source_sku_id'],
+ 'num' => $params['num'],
+ 'seckill_price' => $params['goods_price']
+ ]
+ ],
+ 'pay' => $params['pay'],
+ 'delivery_money'=>$params['delivery_money'] ?? 0,
+ ];
+ $this->param = $param;
+ $this->extend_data = $this->param[ 'extend_data' ] ?? [];
+ }
+
+
+ /**
+ * 秒杀订单创建
+ * @param array $data
+ * @return array
+ */
+ public function create(array $data)
+ {
+ //参数赋值
+ $this->setSeckillParam($data);
+ //检查会员
+ $this->checkMember($data);
+ //订单计算
+ $this->calculate($data);
+ //普通订单校验库存
+ $this->checkStock($this->goods_data);
+
+ $order_data = [
+ //订单整体
+ 'order_no' => create_no(),
+ 'ip' => request()->ip(),
+ 'order_from' => $data['order_from'],
+ 'order_type' => OrderDict::TYPE,
+ 'status' => OrderDict::WAIT_PAY,
+ 'body' => $this->basic['body'],
+ 'member_id' => $data['member_id'],
+ 'goods_money' => $this->basic['goods_money'],
+ 'delivery_money' => $this->basic['delivery_money'] ?? 0,
+ 'discount_money' => $this->basic['discount_money'] ?? 0,
+ 'order_money' => $this->basic['order_money'],
+ 'pay_money' => $this->basic['order_money'],
+ 'has_goods_types' => $this->basic['has_goods_types'],//包含的商品形式
+ 'delivery_type' => $this->delivery['delivery_type'] ?? '',
+ 'taker_name' => $this->delivery['take_address']['taker_name'] ?? '',
+ 'taker_mobile' => $this->delivery['take_address']['taker_mobile'] ?? '',
+ 'taker_province' => $this->delivery['take_address']['taker_province'] ?? 0,
+ 'taker_city' => $this->delivery['take_address']['taker_city'] ?? 0,
+ 'taker_district' => $this->delivery['take_address']['taker_district'] ?? 0,
+ 'taker_address' => $this->delivery['take_address']['taker_address'] ?? '',
+ 'taker_full_address' => $this->delivery['take_address']['taker_full_address'] ?? '',
+ 'taker_longitude' => $this->delivery['take_address']['taker_longitude'] ?? '',
+ 'taker_latitude' => $this->delivery['take_address']['taker_latitude'] ?? '',
+ 'take_store_id' => $this->delivery['take_store']['store_id'] ?? 0,
+ 'member_remark' => $this->param['member_remark'] ?? '',//买家留言
+ 'relate_id' => $this->extend_data['relate_id'] ?? 0,//关联id
+ 'activity_type' => $this->extend_data['relate_source'] ?? '', // 活动类型
+ 'relate_order_id' => $this->extend_data['relate_order_id'] ?? 0,
+ 'relate_source' => $this->extend_data['relate_source'] ?? '',
+ 'out_trade_no' => isset($data['pay']) ? $data['pay']['out_trade_no'] : '',
+ ];
+
+ $order_goods_data = [];//项
+ $write_goods_data = array_merge($this->goods_data, $this->impulse_buy_list);
+ foreach ($write_goods_data as $v) {
+ $order_goods_data[] = [
+ 'member_id' => $data['member_id'],
+ 'goods_id' => $v['goods_id'],
+ 'sku_id' => $v['sku_id'],
+ 'goods_name' => $v['goods']['goods_name'],
+ 'sku_name' => $v['sku_name'],
+ 'goods_image' => $v['goods']['goods_cover'],
+ 'sku_image' => $v['sku_image'],
+ 'price' => $v['price'],
+ 'original_price' => $v['original_price'] ?? 0,
+ 'num' => $v['num'],
+ 'goods_money' => $v['goods_money'],
+ 'goods_type' => $v['goods']['goods_type'],
+ 'order_id' => &$this->order_id,
+ 'discount_money' => $v['discount_money'] ?? 0,
+ 'status' => OrderGoodsDict::NORMAL,
+ 'extend' => $v['extend'] ?? '',
+ 'is_gift' => $v['is_gift'] ?? 0,
+ 'order_goods_money' => $v['goods_money']
+ ];
+ }
+
+ $result = $this->model->transaction(function () use ($data, $order_data, $order_goods_data) {
+ //生成订单
+ $order = (new Order())->create($order_data);
+ $this->order_id = $order['order_id'];
+ //添加订单项目表
+ $order_goods_model = new OrderGoods();
+ $order_goods_model->insertAll($order_goods_data);
+ $order_data['order_id'] = $this->order_id;
+ $main_type = OrderLogDict::MEMBER;
+ $main_id = $order_data['member_id'];
+ //订单创建后事件
+ CoreOrderEventService::orderCreateAfter([ 'order_id' => $this->order_id, 'order_data' => $order_data, 'order_goods_data' => $order_goods_data, 'cart_ids' => $this->cart_ids, 'basic' => get_object_vars($this), 'main_type' => $main_type, 'main_id' => $main_id, 'time' => time() ]);
+ //支付
+
+ $this->pay($data['pay'] ?? [], $order_data);
+
+ $order_goods_ids = $order_goods_model->where(['order_id' => $this->order_id])->column("order_goods_id");
+ return [
+ 'trade_type' => $order_data['order_type'],
+ 'order_id' => $this->order_id,
+ 'order_goods_id' => $order_goods_ids,
+ 'seckill_order_id' => $order_data['relate_order_id']
+ ];
+ });
+
+ return $result;
+ }
+
+
+ public function pay($pay_info, $order_data)
+ {
+ $data = array(
+ 'out_trade_no' => $pay_info['out_trade_no'] ?? '',
+ 'trade_type' => 'shop',
+ 'trade_id' => $order_data['order_id'],
+ 'main_id' => $pay_info['main_id'] ?? '',
+ );
+ //秒杀推送的订单不添加交易记录
+ // $pay_model = new \app\model\pay\Pay();
+ // $pay_model->create($data);
+ if ($order_data['pay_money'] > 0) {
+ event('PaySuccess', ['out_trade_no' => $data['out_trade_no'], 'trade_type' => $data['trade_type'], 'trade_id' => $data['trade_id'], 'main_id' => $data['main_id']]);
+ } else {
+ (new CoreOrderPayService())->pay($data);
+ }
+ }
+
+ public function checkMember($data): void
+ {
+ $this->delivery['take_address'] = $data['take_address'] ?? [];
+ $member_info = (new CoreMemberService())->getInfoByMemberId( $data['member_id'], 'status');
+ if (empty($member_info)) throw new CommonException(get_lang('SHOP_ORDER_BUYER_NOT_FOUND'));//无效的账号
+ if ($member_info['status'] == MemberDict::OFF) throw new CommonException(get_lang('SHOP_ORDER_BUYER_LOCKED'));//账号被锁定
+ }
+
+ /**
+ * 整理
+ * @param array $data
+ * @return void
+ */
+ public function calculate(array $data)
+ {
+ //参数赋值
+ $this->delivery['take_address'] = $data['take_address'] ?? [];
+ $this->order_key = $this->param['order_key'] ?? '';
+ $is_need_recalculate = $data['is_need_recalculate'] ?? 0;
+ if (empty($this->order_key) || $is_need_recalculate == 1) {
+ $this->confirm($this->order_key);
+ }
+ if (in_array(GoodsDict::VIRTUAL, $this->basic['has_goods_types'])) {
+ $this->delivery['delivery_type'] = OrderDeliveryDict::VIRTUAL;
+ } else {
+ $this->delivery['delivery_type'] = 'express';
+ }
+
+ //金额格式化
+ $discount_money = $this->moneyFormat($this->basic['discount_money'] ?? 0);//优惠金额
+ $delivery_money = $this->moneyFormat($this->param['delivery_money'] ?? 0);
+ $goods_money = $this->moneyFormat($this->basic['goods_money'] ?? 0);
+ $order_money = $this->moneyFormat($this->basic['order_money'] ?? 0);
+ $order_money = $this->moneyFormat($this->moneyCalculate($order_money, $delivery_money, $goods_money, -$discount_money));
+ $this->basic['discount_money'] = $discount_money;
+ $this->basic['delivery_money'] = $delivery_money;
+ $this->basic['goods_money'] = $goods_money;
+ $this->basic['order_money'] = $order_money;
+ }
+
+ /**
+ * 订单确认(基础信息查询并缓存)
+ * @return array|mixed
+ * @throws DataNotFoundException
+ * @throws DbException
+ * @throws ModelNotFoundException
+ */
+ public function confirm($order_key = '')
+ {
+ //查看会员信息
+ $member_id = $this->param['member_id'];
+ $this->member_id = $member_id;
+ $member_info = (new CoreMemberService())->getInfoByMemberId($member_id, 'nickname, headimg, balance, point, member_level,member_label');
+ if (empty($member_info)) throw new CommonException(get_lang('SHOP_ORDER_BUYER_NOT_FOUND'));//无效的账号
+ // 查询会员等级信息
+ $member_info['member_level_id'] = $member_info['member_level'];
+ $member_info['member_level'] = (new MemberLevel())->where([['level_id', '=', $member_info['member_level']]])->field('level_id,level_benefits')->findOrEmpty()->toArray();
+ //会员账户信息
+ $this->buyer = $member_info;
+ $order_config = (new CoreOrderConfigService())->getConfig() ?? [];
+ $this->form_id = $order_config['form_id'];
+ //查询商品信息
+ $this->getGoodsData();
+ return true;
+ }
+
+
+ /**
+ * 商品相关数据
+ * @return array
+ * @throws DataNotFoundException
+ * @throws DbException
+ * @throws ModelNotFoundException
+ */
+ public function getGoodsData()
+ {
+ $this->extend_data = $this->param['extend_data'] ?? [];
+ $sku_data = $this->param['sku_data'] ?? [];
+ if (empty($sku_data)) throw new CommonException(get_lang('SHOP_GOODS_DELISTED'));//无效的数据
+ $sku_ids = array_column($sku_data, 'sku_id');
+ $sku_condition = array(
+ ['sku_id', 'in', $sku_ids]
+ );
+ $sku_list = (new GoodsSku())->where($sku_condition)->with(['goods'])->field('sku_id, sku_name, sku_image, goods_id, price, stock, weight, volume,sku_id, sku_spec_format,member_price, sale_price')->select()->toArray();
+ $sku_list = array_column($sku_list, null, 'sku_id');
+ //商品数据 查询商品列表
+ $order_data = [];
+ $goods_list = [];
+ $goods_money = 0;
+ $total_num = 0;
+ $body = '';
+ //订单中包含的商品形式
+ $has_goods_types = [];
+ foreach ($sku_data as $v) {
+ $sku_id = $v['sku_id'];
+ $num = $v['num'];
+ $total_num += $num;
+ $market_type = $v['market_type'] ?? '';
+ $market_type_id = $v['market_type_id'] ?? 0;
+ $sku_info = $sku_list[$sku_id] ?? [];
+ if (empty($sku_info)) throw new CommonException(get_lang('SHOP_GOODS_DELISTED'));//无效的商品
+ $sku_info['member_discount'] = $sku_info['goods']['member_discount'] ?? '';
+ //商品原价
+ $sku_info['original_price'] = $sku_info['price'];
+ //获取活动价格
+ $sku_info['show_type'] = 'original_price';
+ $sku_info['price'] = $v['seckill_price'];
+ $sku_info['active_id'] = $v['seckill_id'] ?? '';
+ $sku_info['discount_money'] = 0;
+ $item_goods_type = $sku_info['goods']['goods_type'];
+
+ // 商品限购处理
+ if (isset($this->limit_buy['goods_' . $sku_info['goods_id']])) {
+ $this->limit_buy['goods_' . $sku_info['goods_id']]['num'] += $num;
+ } else {
+ $this->limit_buy['goods_' . $sku_info['goods_id']] = [
+ 'goods_id' => $sku_info['goods_id'],
+ 'goods_name' => $sku_info['goods']['goods_name'],
+ 'stock' => $sku_info['goods']['stock'],
+ 'num' => $num,
+ 'is_limit' => $sku_info['goods']['is_limit'],
+ 'limit_type' => $sku_info['goods']['limit_type'],
+ 'max_buy' => $sku_info['goods']['max_buy'],
+ 'min_buy' => $sku_info['goods']['min_buy']
+ ];
+ }
+
+ if (!in_array($item_goods_type, $has_goods_types)) $has_goods_types[] = $item_goods_type;
+
+ $sku_info['num'] = $num;
+ $sku_info['market_type'] = $market_type;//活动类型
+ $sku_info['market_type_id'] = $market_type_id;//活动id
+
+ // 计算商品小计
+ $price = $sku_info['price'];
+ $sku_info['goods_money'] = $price * $num;
+ $goods_money += $sku_info['goods_money'];
+ $body = $body ? $body . ($sku_info['sku_name'] . $sku_info['goods']['goods_name']) : ($sku_info['sku_name'] . $sku_info['goods']['goods_name']);
+ $goods_list[$sku_id] = $sku_info;
+ }
+
+ $this->basic['has_goods_types'] = $has_goods_types;
+ $this->basic['total_num'] = $total_num;
+ $this->goods_data = $goods_list;
+ $this->basic['goods_money'] = $goods_money;
+ $this->basic['body'] = $body;
+ return $order_data;
+ }
+
+
+}
diff --git a/niucloud/addon/shop/app/upgrade/v621/upgrade.sql b/niucloud/addon/shop/app/upgrade/v621/upgrade.sql
new file mode 100644
index 000000000..672e6c30a
--- /dev/null
+++ b/niucloud/addon/shop/app/upgrade/v621/upgrade.sql
@@ -0,0 +1,149 @@
+
+CREATE TABLE `shop_point_exchange_order` (
+ `order_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '兑换记录id',
+ `order_no` varchar(255) NOT NULL DEFAULT '' COMMENT '订单编号',
+ `out_trade_no` varchar(255) NOT NULL DEFAULT '' COMMENT '支付流水表',
+ `exchange_id` int(11) NOT NULL DEFAULT '0' COMMENT '兑换活动id',
+ `exchange_name` varchar(255) NOT NULL DEFAULT '' COMMENT '兑换商品名称',
+ `exchange_image` varchar(600) NOT NULL DEFAULT '' COMMENT '兑换商品图片 ',
+ `type` varchar(50) NOT NULL DEFAULT '' COMMENT '兑换类型',
+ `member_id` int(11) NOT NULL DEFAULT '0' COMMENT '消费会员id',
+ `member_address_id` int(11) NOT NULL DEFAULT '0' COMMENT '会员地址id',
+ `relate_id` int(11) NOT NULL DEFAULT '0' COMMENT '关联业务id',
+ `relate_order_id` int(11) NOT NULL DEFAULT '0' COMMENT '关联订单id',
+ `point` int(11) NOT NULL DEFAULT '0' COMMENT '使用积分',
+ `price` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '支付金额',
+ `balance` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '赠送余额',
+ `create_time` int(11) NOT NULL DEFAULT '0' COMMENT '创建时间',
+ `pay_time` int(11) NOT NULL DEFAULT '0' COMMENT '兑换时间',
+ `close_time` int(11) NOT NULL DEFAULT '0' COMMENT '关闭时间',
+ `delete_time` int(11) NOT NULL DEFAULT '0' COMMENT '订单删除',
+ `num` int(11) NOT NULL DEFAULT '0' COMMENT '兑换数量',
+ `status` varchar(50) NOT NULL DEFAULT '' COMMENT '订单状态',
+ `order_money` decimal(10,2) NOT NULL COMMENT '订单金额',
+ PRIMARY KEY (`order_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_general_ci COMMENT='积分兑换订单表';
+
+
+CREATE TABLE `shop_point_exchange` (
+ `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '兑换活动主键id',
+ `type` varchar(255) NOT NULL DEFAULT '' COMMENT '兑换类型(商品、优惠券、红包)',
+ `names` varchar(255) NOT NULL DEFAULT '' COMMENT '兑换标题',
+ `title` varchar(255) NOT NULL COMMENT '副标题',
+ `image` text COMMENT '图片',
+ `status` int(11) NOT NULL DEFAULT '0' COMMENT '兑换状态 0 下架 1上架 -1 删除',
+ `product_detail` text COMMENT '兑换产品信息',
+ `point` int(11) NOT NULL DEFAULT '0' COMMENT '兑换所需积分',
+ `price` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '兑换所需金额',
+ `limit_num` int(11) NOT NULL DEFAULT '0' COMMENT '限制数量',
+ `content` text COMMENT '产品介绍',
+ `sort` int(11) NOT NULL DEFAULT '0' COMMENT '排序',
+ `total_point_num` int(11) DEFAULT '0' COMMENT '积分消费总额',
+ `total_price_num` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '总支付金额',
+ `total_order_num` int(11) DEFAULT '0' COMMENT '订单笔数',
+ `total_member_num` int(11) DEFAULT '0' COMMENT '参与会员数',
+ `update_time` int(11) NOT NULL DEFAULT '0' COMMENT '更新时间',
+ `create_time` int(11) NOT NULL DEFAULT '0' COMMENT '创建时间',
+ `stock` int(11) NOT NULL DEFAULT '0' COMMENT '库存',
+ `total_exchange_num` int(11) NOT NULL DEFAULT '0' COMMENT '兑换数量',
+ PRIMARY KEY (`id`,`total_price_num`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_general_ci COMMENT='积分兑换表';
+
+
+ALTER TABLE `shop_order_goods` ADD COLUMN `extend` VARCHAR(1000) NOT NULL DEFAULT '' COMMENT '数据项扩展';
+
+ALTER TABLE `shop_order_goods` ADD COLUMN `verify_count` INT(11) NOT NULL DEFAULT 0 COMMENT '已核销次数';
+
+ALTER TABLE `shop_order_goods` ADD COLUMN `verify_expire_time` INT(11) NOT NULL DEFAULT 0 COMMENT '过期时间 0 为永久';
+
+ALTER TABLE `shop_order_goods` ADD COLUMN `is_verify` INT(11) NOT NULL DEFAULT 0 COMMENT '是否需要核销';
+
+ALTER TABLE `shop_order` ADD COLUMN `relate_id` INT(11) NOT NULL DEFAULT 0 COMMENT '关联id';
+
+ALTER TABLE `shop_order` ADD COLUMN `point` INT(11) NOT NULL DEFAULT 0 COMMENT '积分兑换';
+
+ALTER TABLE `shop_order` ADD COLUMN `activity_type` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '营销类型';
+
+ALTER TABLE `shop_goods_sku` ADD COLUMN `member_price` TEXT DEFAULT NULL COMMENT '会员价,json格式,指定会员价,数据结构为:{"level_1":"10.00","level_2":"10.00"}';
+
+CREATE TABLE `shop_goods_attr` (
+ `attr_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '商品参数id',
+ `attr_name` varchar(255) NOT NULL DEFAULT '' COMMENT '参数名称',
+ `attr_value_format` text COMMENT '参数值,json格式',
+ `sort` int(11) NOT NULL DEFAULT '0' COMMENT '参数排序号',
+ PRIMARY KEY (`attr_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_general_ci COMMENT='商品参数表';
+
+
+ALTER TABLE `shop_goods` ADD COLUMN `virtual_auto_delivery` TINYINT(4) NOT NULL DEFAULT 0 COMMENT '虚拟商品是否自动发货';
+
+ALTER TABLE `shop_goods` ADD COLUMN `virtual_receive_type` VARCHAR(255) NOT NULL DEFAULT 'artificial' COMMENT '虚拟商品收货方式,auto:自动收货,artificial:买家确认收货,verify:到店核销';
+
+ALTER TABLE `shop_goods` ADD COLUMN `virtual_verify_type` TINYINT(4) NOT NULL DEFAULT 0 COMMENT '虚拟商品核销有效期类型,0:不限,1:购买后几日有效,2:指定过期日期';
+
+ALTER TABLE `shop_goods` ADD COLUMN `virtual_indate` INT(11) NOT NULL DEFAULT 0 COMMENT '虚拟到期时间';
+
+ALTER TABLE `shop_goods` ADD COLUMN `attr_id` INT(11) NOT NULL DEFAULT 0 COMMENT '商品参数id';
+
+ALTER TABLE `shop_goods` ADD COLUMN `attr_format` TEXT DEFAULT NULL COMMENT '商品参数内容,json格式';
+
+ALTER TABLE `shop_goods` ADD COLUMN `is_discount` INT(11) NOT NULL DEFAULT 0 COMMENT '是否参与限时折扣';
+
+ALTER TABLE `shop_goods` ADD COLUMN `member_discount` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '会员等级折扣,不参与:空,会员折扣:discount,指定会员价:fixed_price';
+
+ALTER TABLE `shop_goods` ADD COLUMN `poster_id` INT(11) NOT NULL DEFAULT 0 COMMENT '海报id';
+
+ALTER TABLE `shop_goods` MODIFY `supplier_id` INT(11) NOT NULL DEFAULT 0 COMMENT '供应商id' AFTER `virtual_indate`;
+
+ALTER TABLE `shop_goods` MODIFY `create_time` INT(11) NOT NULL DEFAULT 0 COMMENT '创建时间' AFTER `poster_id`;
+
+ALTER TABLE `shop_goods` MODIFY `update_time` INT(11) NOT NULL DEFAULT 0 COMMENT '修改时间' AFTER `create_time`;
+
+ALTER TABLE `shop_goods` MODIFY `delete_time` INT(11) NOT NULL DEFAULT 0 COMMENT '删除时间' AFTER `update_time`;
+
+
+CREATE TABLE `shop_active` (
+ `active_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '活动id',
+ `active_name` varchar(255) NOT NULL DEFAULT '' COMMENT '活动名称',
+ `active_desc` text COMMENT '活动说明',
+ `active_type` varchar(255) NOT NULL DEFAULT '' COMMENT '活动类型(店铺活动,会员活动,商品活动)',
+ `active_goods_type` varchar(255) NOT NULL DEFAULT '' COMMENT '商品活动类型(单品,独立商品,店铺整体商品)',
+ `active_goods_info` text COMMENT '参与活动商品信息',
+ `active_class` varchar(255) NOT NULL DEFAULT '' COMMENT '活动类别',
+ `active_class_category` varchar(255) NOT NULL DEFAULT '' COMMENT '活动类别子分类(活动管理)',
+ `relate_member` varchar(1000) NOT NULL DEFAULT '' COMMENT '参与会员条件(默认全部)',
+ `active_value` text COMMENT '活动扩展信息数据',
+ `start_time` int(11) NOT NULL DEFAULT '0' COMMENT '活动开始时间',
+ `end_time` int(11) NOT NULL DEFAULT '0' COMMENT '活动结束时间',
+ `active_status` varchar(50) NOT NULL DEFAULT '' COMMENT '活动状态',
+ `create_time` int(11) NOT NULL DEFAULT '0' COMMENT '添加时间',
+ `update_time` int(11) NOT NULL DEFAULT '0' COMMENT '修改时间',
+ `active_order_money` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '活动累计金额',
+ `active_order_num` int(11) NOT NULL DEFAULT '0' COMMENT '活动累计订单数',
+ `active_member_num` int(11) NOT NULL DEFAULT '0' COMMENT '活动参与会员数',
+ `active_success_num` int(11) NOT NULL DEFAULT '0' COMMENT '活动成功参与会员数',
+ PRIMARY KEY (`active_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_general_ci COMMENT='店铺营销活动表(整体活动)';
+
+
+CREATE TABLE `shop_active_goods` (
+ `active_goods_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '活动商品id',
+ `active_id` int(11) NOT NULL DEFAULT '0' COMMENT '活动id',
+ `goods_id` int(11) NOT NULL DEFAULT '0' COMMENT '商品id',
+ `active_goods_type` varchar(255) NOT NULL DEFAULT '' COMMENT '商品活动类型(单品,独立商品,店铺整体商品)',
+ `active_class` varchar(255) NOT NULL DEFAULT '' COMMENT '商品活动类别',
+ `active_goods_label` varchar(1000) NOT NULL DEFAULT '' COMMENT '活动商品标签(针对活动有标签)',
+ `active_goods_category` varchar(1000) NOT NULL DEFAULT '' COMMENT '活动商品分类(针对活动有分类)',
+ `active_goods_value` text COMMENT '活动商品信息数据',
+ `active_goods_status` varchar(50) NOT NULL DEFAULT '' COMMENT '活动状态',
+ `active_goods_point` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '活动商品积分(展示,搜索)',
+ `active_goods_price` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '活动商品价格(展示,搜索)',
+ `active_goods_stock` int(11) NOT NULL DEFAULT '0' COMMENT '活动商品库存(针对参与库存)',
+ `active_goods_order_money` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '活动累计金额',
+ `active_goods_order_num` int(11) NOT NULL DEFAULT '0' COMMENT '活动累计订单数',
+ `active_goods_member_num` int(11) NOT NULL DEFAULT '0' COMMENT '活动参与会员数',
+ `active_goods_success_num` int(11) NOT NULL DEFAULT '0' COMMENT '活动成功参与会员数',
+ PRIMARY KEY (`active_goods_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_general_ci COMMENT='店铺营销活动';
+
+ALTER TABLE `shop_order_refund` ADD COLUMN `is_refund_delivery` INT(11) NOT NULL DEFAULT 0 COMMENT '是否退运费';
diff --git a/niucloud/addon/shop/app/upgrade/v630/Upgrade.php b/niucloud/addon/shop/app/upgrade/v630/Upgrade.php
new file mode 100644
index 000000000..f3e0fed5f
--- /dev/null
+++ b/niucloud/addon/shop/app/upgrade/v630/Upgrade.php
@@ -0,0 +1,50 @@
+handleData();
+ }
+
+ /**
+ * 处理商品数据
+ */
+ private function handleData()
+ {
+
+ $poster = new CorePosterService();
+ $poster_model = new Poster();
+
+ // 删除旧模板
+ $poster_model->where([ [ 'addon', '=', 'shop' ] ])->delete();
+
+ // 创建默认商品海报
+ $template = $poster->getTemplateList('shop', 'shop_goods')[ 0 ];
+ $poster->add('shop', [
+ 'name' => $template[ 'name' ],
+ 'type' => $template[ 'type' ],
+ 'value' => $template[ 'data' ],
+ 'status' => 1,
+ 'is_default' => 1
+ ]);
+
+ // 创建默认积分商品海报
+ $template = $poster->getTemplateList('shop', 'shop_point_goods')[ 0 ];
+ $poster->add('shop', [
+ 'name' => $template[ 'name' ],
+ 'type' => $template[ 'type' ],
+ 'value' => $template[ 'data' ],
+ 'status' => 1,
+ 'is_default' => 1
+ ]);
+
+ }
+
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/app/upgrade/v630/upgrade.sql b/niucloud/addon/shop/app/upgrade/v630/upgrade.sql
new file mode 100644
index 000000000..4ad2ade40
--- /dev/null
+++ b/niucloud/addon/shop/app/upgrade/v630/upgrade.sql
@@ -0,0 +1,64 @@
+
+ALTER TABLE `shop_point_exchange` CHANGE COLUMN `product_detail` `product_detail` TEXT DEFAULT NULL COMMENT '兑换产品信息';
+
+DROP TABLE IF EXISTS `shop_order_batch_delivery`;
+CREATE TABLE `shop_order_batch_delivery` (
+ `id` INT(11) NOT NULL AUTO_INCREMENT COMMENT 'id',
+ `main_id` INT(11) NOT NULL DEFAULT 0 COMMENT '操作人id',
+ `status` INT(11) NOT NULL DEFAULT 1 COMMENT '状态 进行中 已完成 已失败',
+ `type` VARCHAR(255) NOT NULL DEFAULT '操作类型 批量发货 批量打单 ....' COMMENT '操作类型',
+ `total_num` INT(11) NOT NULL DEFAULT 0 COMMENT '总发货单数',
+ `success_num` INT(11) NOT NULL DEFAULT 0 COMMENT '成功发货单数',
+ `fail_num` INT(11) NOT NULL DEFAULT 0 COMMENT '失败发货单数',
+ `data` VARCHAR(2000) NOT NULL DEFAULT '' COMMENT '导入文件的路径',
+ `output` VARCHAR(500) NOT NULL DEFAULT '' COMMENT '对外输出记录',
+ `fail_output` VARCHAR(500) NOT NULL DEFAULT '' COMMENT '失败记录',
+ `fail_remark` VARCHAR(1000) NOT NULL DEFAULT '' COMMENT '失败原因',
+ `create_time` INT(11) NOT NULL COMMENT '创建时间',
+ `update_time` INT(11) NOT NULL DEFAULT 0 COMMENT '操作时间',
+ PRIMARY KEY (`id`)
+)
+ENGINE = INNODB,
+CHARACTER SET utf8mb4,
+COLLATE utf8mb4_general_ci,
+COMMENT = '订单批量发货表';
+
+
+DROP TABLE IF EXISTS `shop_delivery_electronic_sheet`;
+CREATE TABLE `shop_delivery_electronic_sheet` (
+ `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
+ `template_name` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '模板名称',
+ `express_company_id` INT(11) NOT NULL DEFAULT 0 COMMENT '物流公司id',
+ `customer_name` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '电子面单客户账号(CustomerName)',
+ `customer_pwd` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '电子面单密码(CustomerPwd)',
+ `send_site` VARCHAR(255) NOT NULL DEFAULT '' COMMENT 'SendSite',
+ `send_staff` VARCHAR(255) NOT NULL DEFAULT '' COMMENT 'SendStaff',
+ `month_code` VARCHAR(255) NOT NULL DEFAULT '' COMMENT 'MonthCode',
+ `pay_type` TINYINT(4) NOT NULL DEFAULT 0 COMMENT '邮费支付方式(1:现付,2:到付,3:月结)',
+ `is_notice` TINYINT(4) NOT NULL DEFAULT 0 COMMENT '快递员上门揽件(0:否,1:是)',
+ `status` TINYINT(4) NOT NULL DEFAULT 0 COMMENT '状态(1:开启,0:关闭)',
+ `exp_type` INT(11) NOT NULL DEFAULT 0 COMMENT '物流公司业务类型',
+ `print_style` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '电子面单打印模板样式',
+ `is_default` TINYINT(4) NOT NULL DEFAULT 0 COMMENT '是否默认(1:是,0:否)',
+ `create_time` INT(11) NOT NULL DEFAULT 0 COMMENT '创建时间',
+ `update_time` INT(11) NOT NULL DEFAULT 0 COMMENT '修改时间',
+ PRIMARY KEY (`id`)
+)
+ENGINE = INNODB,
+CHARACTER SET utf8mb4,
+COLLATE utf8mb4_general_ci,
+COMMENT = '电子面单';
+
+ALTER TABLE `shop_delivery_company` CHANGE COLUMN `express_no` `express_no` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '物流公司编号(用于物流跟踪)';
+
+ALTER TABLE `shop_delivery_company` ADD COLUMN `express_no_electronic_sheet` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '物流公司编号(用于电子面单)';
+
+ALTER TABLE `shop_delivery_company` ADD COLUMN `electronic_sheet_switch` TINYINT(4) NOT NULL DEFAULT 0 COMMENT '是否支持电子面单(0:不支持,1:支持)';
+
+ALTER TABLE `shop_delivery_company` ADD COLUMN `print_style` VARCHAR(2000) NOT NULL DEFAULT '' COMMENT '电子面单打印模板样式,json字符串';
+
+ALTER TABLE `shop_delivery_company` ADD COLUMN `exp_type` VARCHAR(2000) NOT NULL DEFAULT '' COMMENT '物流公司业务类型,json字符串';
+
+ALTER TABLE `shop_delivery_company` MODIFY `create_time` INT(11) NOT NULL DEFAULT 0 AFTER `exp_type`;
+
+ALTER TABLE `shop_delivery_company` MODIFY `update_time` INT(11) NOT NULL DEFAULT 0 AFTER `create_time`;
diff --git a/niucloud/addon/shop/app/upgrade/v631/Upgrade.php b/niucloud/addon/shop/app/upgrade/v631/Upgrade.php
new file mode 100644
index 000000000..e97a676d4
--- /dev/null
+++ b/niucloud/addon/shop/app/upgrade/v631/Upgrade.php
@@ -0,0 +1,49 @@
+handleData();
+ }
+
+ /**
+ * 处理商品数据
+ */
+ private function handleData()
+ {
+ $diy_model = new Diy();
+ $where = [
+ [ 'value', '<>', '' ]
+ ];
+ $field = 'id,name,title,template,value';
+ $list = $diy_model->where($where)->field($field)->select()->toArray();
+
+ if (!empty($list)) {
+ foreach ($list as $k => $v) {
+ $diy_data = json_decode($v[ 'value' ], true);
+
+ foreach ($diy_data[ 'value' ] as $ck => $cv) {
+ if ($cv[ 'componentName' ] == 'ShopMemberInfo') {
+ if (!isset($diy_data[ 'value' ][ $ck ][ 'isShowAccount' ])) {
+ $diy_data[ 'value' ][ $ck ][ 'isShowAccount' ] = true;
+ }
+
+ }
+ }
+
+ $diy_data = json_encode($diy_data);
+ $diy_model->where([ [ 'id', '=', $v[ 'id' ] ] ])->update([ 'value' => $diy_data ]);
+ }
+ }
+
+ }
+
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/app/upgrade/v631/upgrade.sql b/niucloud/addon/shop/app/upgrade/v631/upgrade.sql
new file mode 100644
index 000000000..65eb4c254
--- /dev/null
+++ b/niucloud/addon/shop/app/upgrade/v631/upgrade.sql
@@ -0,0 +1,2 @@
+
+ALTER TABLE `shop_order_refund` CHANGE COLUMN `delivery` `delivery` VARCHAR(3000) NOT NULL DEFAULT '' COMMENT '退货配送信息';
diff --git a/niucloud/addon/shop/app/upgrade/v640/Upgrade.php b/niucloud/addon/shop/app/upgrade/v640/Upgrade.php
new file mode 100644
index 000000000..1d4d87a49
--- /dev/null
+++ b/niucloud/addon/shop/app/upgrade/v640/Upgrade.php
@@ -0,0 +1,750 @@
+handleData();
+ }
+
+ /**
+ * 处理商品数据
+ */
+ private function handleData()
+ {
+
+ $label_group_model = new LabelGroup();
+ $label_model = new Label();
+
+ // 添加默认商品标签分组
+ $label_group_info = $label_group_model->where([
+ [ 'group_name', '=', '默认' ]
+ ])->field('group_id')->findOrEmpty()->toArray();
+
+ if (!empty($label_group_info)) {
+ $group_id = $label_group_info[ 'group_id' ];
+ } else {
+ $res = $label_group_model->create([
+ 'group_name' => '默认',
+ 'create_time' => time(),
+ ]);
+ $group_id = $res->group_id;
+ }
+
+ // 更新商品标签数据,标签分组id、效果设置、自定义颜色、图标、状态
+ $label_model->where([ [ 'label_id', '>', 0 ] ])->update([
+ 'group_id' => $group_id,
+ 'status' => 1,
+ 'style_type' => 'diy',
+ 'color_json' => [
+ 'text_color' => 'rgba(255, 255, 255, 1)',
+ 'bg_color' => 'rgba(255, 65, 66, 1)',
+ 'border_color' => ''
+ ]
+ ]);
+
+ $label_model = new Label();
+ $label_list = $label_model->where([
+ [ 'icon', 'in', [ 'addon/shop/goods/label/icon1.jpg', 'addon/shop/goods/label/icon2.jpg', 'addon/shop/goods/label/icon3.jpg' ] ]
+ ])->field('label_id,icon')->select()->toArray();
+ if(!empty($label_list)) {
+ foreach ($label_list as $k => $v) {
+ if ($v[ 'icon' ] == 'addon/shop/goods/label/icon1.jpg') {
+ $label_model->where([ [ 'label_id', '=', $v[ 'label_id' ] ] ])->update([
+ 'icon' => 'addon/shop/goods/label/icon1.png'
+ ]);
+ } else if ($v[ 'icon' ] == 'addon/shop/goods/label/icon2.jpg') {
+ $label_model->where([ [ 'label_id', '=', $v[ 'label_id' ] ] ])->update([
+ 'icon' => 'addon/shop/goods/label/icon2.png'
+ ]);
+ } else if ($v[ 'icon' ] == 'addon/shop/goods/label/icon3.jpg') {
+ $label_model->where([ [ 'label_id', '=', $v[ 'label_id' ] ] ])->update([
+ 'icon' => 'addon/shop/goods/label/icon3.png'
+ ]);
+ }
+ }
+ }else{
+ // 添加商品标签
+ $label_list = [
+ [
+ 'label_name' => '热卖',
+ 'group_id' => $group_id,
+ 'style_type' => 'diy',
+ 'color_json' => [
+ 'text_color' => 'rgba(255, 255, 255, 1)',
+ 'bg_color' => 'rgba(250, 35, 28, 1)',
+ 'border_color' => ''
+ ],
+ 'icon' => '',
+ 'status' => 1,
+ 'sort' => 0,
+ 'create_time' => time()
+ ],
+ [
+ 'label_name' => '新品推荐',
+ 'group_id' => $group_id,
+ 'style_type' => 'diy',
+ 'color_json' => [
+ 'text_color' => 'rgba(255, 255, 255, 1)',
+ 'bg_color' => 'rgba(250, 35, 28, 1)',
+ 'border_color' => ''
+ ],
+ 'icon' => '',
+ 'status' => 1,
+ 'sort' => 1,
+ 'create_time' => time()
+ ],
+ [
+ 'label_name' => '甄选优品',
+ 'group_id' => $group_id,
+ 'style_type' => 'diy',
+ 'color_json' => [
+ 'text_color' => 'rgba(255, 255, 255, 1)',
+ 'bg_color' => 'rgba(250, 35, 28, 1)',
+ 'border_color' => ''
+ ],
+ 'icon' => '',
+ 'status' => 1,
+ 'sort' => 2,
+ 'create_time' => time()
+ ],
+ [
+ 'label_name' => '百亿补贴',
+ 'group_id' => $group_id,
+ 'style_type' => 'icon',
+ 'color_json' => [
+ 'text_color' => 'rgba(255, 255, 255, 1)',
+ 'bg_color' => 'rgba(250, 35, 28, 1)',
+ 'border_color' => ''
+ ],
+ 'icon' => 'addon/shop/goods/label/icon1.png',
+ 'status' => 1,
+ 'sort' => 3,
+ 'create_time' => time()
+ ],
+ [
+ 'label_name' => '双11',
+ 'group_id' => $group_id,
+ 'style_type' => 'icon',
+ 'color_json' => [
+ 'text_color' => 'rgba(255, 255, 255, 1)',
+ 'bg_color' => 'rgba(250, 35, 28, 1)',
+ 'border_color' => ''
+ ],
+ 'icon' => 'addon/shop/goods/label/icon2.png',
+ 'status' => 1,
+ 'sort' => 4,
+ 'create_time' => time()
+ ],
+ [
+ 'label_name' => '双12',
+ 'group_id' => $group_id,
+ 'style_type' => 'icon',
+ 'color_json' => [
+ 'text_color' => 'rgba(255, 255, 255, 1)',
+ 'bg_color' => 'rgba(250, 35, 28, 1)',
+ 'border_color' => ''
+ ],
+ 'icon' => 'addon/shop/goods/label/icon3.png',
+ 'status' => 1,
+ 'sort' => 5,
+ 'create_time' => time()
+ ]
+ ];
+ $exist_label_list = $label_model->where([
+ [ 'label_name', 'in', array_column($label_list, 'label_name', '') ]
+ ])->field('label_name')->select()->toArray();
+
+ if (!empty($exist_label_list)) {
+ $label_name_list = array_column($exist_label_list, 'label_name', '');
+
+ foreach ($label_list as $k => $v) {
+ if (in_array($v[ 'label_name' ], $label_name_list)) {
+ unset($label_list[ $k ]);
+ }
+ }
+ $label_list = array_values($label_list);
+ }
+ if (!empty($label_list)) {
+ $label_model->insertAll($label_list);
+ }
+ }
+
+ // 创建素材
+ $category_model = new SysAttachmentCategory();
+ $category_info = $category_model->where([
+ [ 'name', '=', '商城素材' ]
+ ])->field('id')->findOrEmpty()->toArray();
+
+ if (!empty($category_info)) {
+ $category_id = $category_info[ 'id' ];
+ } else {
+ $attachment_category = $category_model->create([
+ 'pid' => 0,
+ 'type' => 'image',
+ 'name' => '商城素材',
+ 'sort' => 1
+ ]);
+ $category_id = $attachment_category->id;
+ }
+
+ $attachment_model = new SysAttachment();
+ $attachment_list = [
+ [
+ 'name' => time() . $category_id . 'banner1.jpg', // 附件名称
+ 'real_name' => '轮播素材01', // 原始文件名
+ 'path' => 'addon/shop/attachment/banner1.jpg', // 完整地址
+ 'url' => 'addon/shop/attachment/banner1.jpg', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '82918', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ],
+ [
+ 'name' => time() . $category_id . 'banner2.png', // 附件名称
+ 'real_name' => '轮播素材02', // 原始文件名
+ 'path' => 'addon/shop/attachment/banner2.png', // 完整地址
+ 'url' => 'addon/shop/attachment/banner2.png', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '95324', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ],
+ [
+ 'name' => time() . $category_id . 'banner3.png', // 附件名称
+ 'real_name' => '轮播素材03', // 原始文件名
+ 'path' => 'addon/shop/attachment/banner3.png', // 完整地址
+ 'url' => 'addon/shop/attachment/banner3.png', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '97570', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ],
+ [
+ 'name' => time() . $category_id . 'logo.png', // 附件名称
+ 'real_name' => '生活圈', // 原始文件名
+ 'path' => 'addon/shop/attachment/logo.png', // 完整地址
+ 'url' => 'addon/shop/attachment/logo.png', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '1517', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ],
+ [
+ 'name' => time() . $category_id . 'nav_coupon.png', // 附件名称
+ 'real_name' => '优惠券', // 原始文件名
+ 'path' => 'addon/shop/attachment/nav_coupon.png', // 完整地址
+ 'url' => 'addon/shop/attachment/nav_coupon.png', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '30937', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ],
+ [
+ 'name' => time() . $category_id . 'nav_discount.png', // 附件名称
+ 'real_name' => '限时折扣', // 原始文件名
+ 'path' => 'addon/shop/attachment/nav_discount.png', // 完整地址
+ 'url' => 'addon/shop/attachment/nav_discount.png', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '33870', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ],
+ [
+ 'name' => time() . $category_id . 'nav_fenxiao.png', // 附件名称
+ 'real_name' => '分销管理', // 原始文件名
+ 'path' => 'addon/shop/attachment/nav_fenxiao.png', // 完整地址
+ 'url' => 'addon/shop/attachment/nav_fenxiao.png', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '24026', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ],
+ [
+ 'name' => time() . $category_id . 'nav_fenxiao_zone.png', // 附件名称
+ 'real_name' => '分销专区', // 原始文件名
+ 'path' => 'addon/shop/attachment/nav_fenxiao_zone.png', // 完整地址
+ 'url' => 'addon/shop/attachment/nav_fenxiao_zone.png', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '33429', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ],
+ [
+ 'name' => time() . $category_id . 'nav_giftcard.png', // 附件名称
+ 'real_name' => '礼品卡', // 原始文件名
+ 'path' => 'addon/shop/attachment/nav_giftcard.png', // 完整地址
+ 'url' => 'addon/shop/attachment/nav_giftcard.png', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '29399', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ],
+ [
+ 'name' => time() . $category_id . 'nav_my_address.png', // 附件名称
+ 'real_name' => '收货地址', // 原始文件名
+ 'path' => 'addon/shop/attachment/nav_my_address.png', // 完整地址
+ 'url' => 'addon/shop/attachment/nav_my_address.png', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '25280', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ],
+ [
+ 'name' => time() . $category_id . 'nav_my_newcomer.png', // 附件名称
+ 'real_name' => '新人专享', // 原始文件名
+ 'path' => 'addon/shop/attachment/nav_my_newcomer.png', // 完整地址
+ 'url' => 'addon/shop/attachment/nav_my_newcomer.png', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '32123', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ],
+ [
+ 'name' => time() . $category_id . 'nav_news_info.png', // 附件名称
+ 'real_name' => '新闻资讯', // 原始文件名
+ 'path' => 'addon/shop/attachment/nav_news_info.png', // 完整地址
+ 'url' => 'addon/shop/attachment/nav_news_info.png', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '27934', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ],
+ [
+ 'name' => time() . $category_id . 'nav_point_index.png', // 附件名称
+ 'real_name' => '积分商城', // 原始文件名
+ 'path' => 'addon/shop/attachment/nav_point_index.png', // 完整地址
+ 'url' => 'addon/shop/attachment/nav_point_index.png', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '27946 ', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ],
+ [
+ 'name' => time() . $category_id . 'nav_sign_in.png', // 附件名称
+ 'real_name' => '签到', // 原始文件名
+ 'path' => 'addon/shop/attachment/nav_sign_in.png', // 完整地址
+ 'url' => 'addon/shop/attachment/nav_sign_in.png', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '33576', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ],
+ [
+ 'name' => time() . $category_id . 'notice.png', // 附件名称
+ 'real_name' => '新闻咨询', // 原始文件名
+ 'path' => 'addon/shop/attachment/notice.png', // 完整地址
+ 'url' => 'addon/shop/attachment/notice.png', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '3069', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ],
+ [
+ 'name' => time() . $category_id . 'picture_show_head_text2.png', // 附件名称
+ 'real_name' => '品牌特卖', // 原始文件名
+ 'path' => 'addon/shop/attachment/picture_show_head_text2.png', // 完整地址
+ 'url' => 'addon/shop/attachment/picture_show_head_text2.png', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '2825', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ],
+ [
+ 'name' => time() . $category_id . 'picture_show_head_text3.png', // 附件名称
+ 'real_name' => '官方补贴', // 原始文件名
+ 'path' => 'addon/shop/attachment/picture_show_head_text3.png', // 完整地址
+ 'url' => 'addon/shop/attachment/picture_show_head_text3.png', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '2549', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ],
+ [
+ 'name' => time() . $category_id . 'single_recommend_banner1.png', // 附件名称
+ 'real_name' => '精选推荐01', // 原始文件名
+ 'path' => 'addon/shop/attachment/single_recommend_banner1.png', // 完整地址
+ 'url' => 'addon/shop/attachment/single_recommend_banner1.png', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '73548', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ],
+ [
+ 'name' => time() . $category_id . 'single_recommend_banner2.png', // 附件名称
+ 'real_name' => '精选推荐02', // 原始文件名
+ 'path' => 'addon/shop/attachment/single_recommend_banner2.png', // 完整地址
+ 'url' => 'addon/shop/attachment/single_recommend_banner2.png', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '61033', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ],
+ [
+ 'name' => time() . $category_id . 'single_recommend_text1.png', // 附件名称
+ 'real_name' => '精选推荐', // 原始文件名
+ 'path' => 'addon/shop/attachment/single_recommend_text1.png', // 完整地址
+ 'url' => 'addon/shop/attachment/single_recommend_text1.png', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '3664', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ],
+ [
+ 'name' => time() . $category_id . 'my_cart.png', // 附件名称
+ 'real_name' => '购物车', // 原始文件名
+ 'path' => 'addon/shop/attachment/my_cart.png', // 完整地址
+ 'url' => 'addon/shop/attachment/my_cart.png', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '31921', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ],
+ [
+ 'name' => time() . $category_id . 'home_delivery.png', // 附件名称
+ 'real_name' => '送货上门', // 原始文件名
+ 'path' => 'addon/shop/attachment/home_delivery.png', // 完整地址
+ 'url' => 'addon/shop/attachment/home_delivery.png', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '30811', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ],
+ [
+ 'name' => time() . $category_id . 'nav_all_class.png', // 附件名称
+ 'real_name' => '全部分类', // 原始文件名
+ 'path' => 'addon/shop/attachment/nav_all_class.png', // 完整地址
+ 'url' => 'addon/shop/attachment/nav_all_class.png', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '25427', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ],
+ [
+ 'name' => time() . $category_id . 'nav_balance.png', // 附件名称
+ 'real_name' => '我的余额', // 原始文件名
+ 'path' => 'addon/shop/attachment/nav_balance.png', // 完整地址
+ 'url' => 'addon/shop/attachment/nav_balance.png', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '31437', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ],
+ [
+ 'name' => time() . $category_id . 'nav_collect.png', // 附件名称
+ 'real_name' => '我的收藏', // 原始文件名
+ 'path' => 'addon/shop/attachment/nav_collect.png', // 完整地址
+ 'url' => 'addon/shop/attachment/nav_collect.png', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '24533', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ],
+ [
+ 'name' => time() . $category_id . 'nav_coupon_01.png', // 附件名称
+ 'real_name' => '瓜分好券', // 原始文件名
+ 'path' => 'addon/shop/attachment/nav_coupon_01.png', // 完整地址
+ 'url' => 'addon/shop/attachment/nav_coupon_01.png', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '27068', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ],
+ [
+ 'name' => time() . $category_id . 'nav_leaderboard.png', // 附件名称
+ 'real_name' => '排行榜', // 原始文件名
+ 'path' => 'addon/shop/attachment/nav_leaderboard.png', // 完整地址
+ 'url' => 'addon/shop/attachment/nav_leaderboard.png', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '30098', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ],
+ [
+ 'name' => time() . $category_id . 'nav_member.png', // 附件名称
+ 'real_name' => '会员中心', // 原始文件名
+ 'path' => 'addon/shop/attachment/nav_member.png', // 完整地址
+ 'url' => 'addon/shop/attachment/nav_member.png', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '30793', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ],
+ [
+ 'name' => time() . $category_id . 'nav_point.png', // 附件名称
+ 'real_name' => '我的积分', // 原始文件名
+ 'path' => 'addon/shop/attachment/nav_point.png', // 完整地址
+ 'url' => 'addon/shop/attachment/nav_point.png', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '28112', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ],
+ [
+ 'name' => time() . $category_id . 'nav_shop.png', // 附件名称
+ 'real_name' => '线上商城', // 原始文件名
+ 'path' => 'addon/shop/attachment/nav_shop.png', // 完整地址
+ 'url' => 'addon/shop/attachment/nav_shop.png', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '23057', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ],
+ [
+ 'name' => time() . $category_id . 'nav_travel.png', // 附件名称
+ 'real_name' => '旅游出行', // 原始文件名
+ 'path' => 'addon/shop/attachment/nav_travel.png', // 完整地址
+ 'url' => 'addon/shop/attachment/nav_travel.png', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '27429', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ],
+ [
+ 'name' => time() . $category_id . 'nva_group_booking.png', // 附件名称
+ 'real_name' => '拼团返利', // 原始文件名
+ 'path' => 'addon/shop/attachment/nva_group_booking.png', // 完整地址
+ 'url' => 'addon/shop/attachment/nva_group_booking.png', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '30421', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ],
+ [
+ 'name' => time() . $category_id . 'head_01.png', // 附件名称
+ 'real_name' => '超值爆款', // 原始文件名
+ 'path' => 'addon/shop/attachment/head_01.png', // 完整地址
+ 'url' => 'addon/shop/attachment/head_01.png', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '3958', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ],
+ [
+ 'name' => time() . $category_id . 'head_02.png', // 附件名称
+ 'real_name' => '限时折扣', // 原始文件名
+ 'path' => 'addon/shop/attachment/head_02.png', // 完整地址
+ 'url' => 'addon/shop/attachment/head_02.png', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '2408', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ],
+ [
+ 'name' => time() . $category_id . 'head_03.png', // 附件名称
+ 'real_name' => '商品榜单', // 原始文件名
+ 'path' => 'addon/shop/attachment/head_03.png', // 完整地址
+ 'url' => 'addon/shop/attachment/head_03.png', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '2621', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ],
+ [
+ 'name' => time() . $category_id . 'image_ads_01.png', // 附件名称
+ 'real_name' => '商品低至五折', // 原始文件名
+ 'path' => 'addon/shop/attachment/image_ads_01.png', // 完整地址
+ 'url' => 'addon/shop/attachment/image_ads_01.png', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '44566', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ],
+ [
+ 'name' => time() . $category_id . 'active_cube_01.png', // 附件名称
+ 'real_name' => '魔方素材01', // 原始文件名
+ 'path' => 'addon/shop/attachment/active_cube_01.png', // 完整地址
+ 'url' => 'addon/shop/attachment/active_cube_01.png', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '36850', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ],
+ [
+ 'name' => time() . $category_id . 'active_cube_02.png', // 附件名称
+ 'real_name' => '魔方素材02', // 原始文件名
+ 'path' => 'addon/shop/attachment/active_cube_02.png', // 完整地址
+ 'url' => 'addon/shop/attachment/active_cube_02.png', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '26463', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ],
+ [
+ 'name' => time() . $category_id . 'active_cube_03.png', // 附件名称
+ 'real_name' => '魔方素材03', // 原始文件名
+ 'path' => 'addon/shop/attachment/active_cube_03.png', // 完整地址
+ 'url' => 'addon/shop/attachment/active_cube_03.png', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '29142', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ],
+ [
+ 'name' => time() . $category_id . 'active_cube_04.png', // 附件名称
+ 'real_name' => '魔方素材04', // 原始文件名
+ 'path' => 'addon/shop/attachment/active_cube_04.png', // 完整地址
+ 'url' => 'addon/shop/attachment/active_cube_04.png', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '26068', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ],
+ [
+ 'name' => time() . $category_id . 'active_cube_05.png', // 附件名称
+ 'real_name' => '魔方素材05', // 原始文件名
+ 'path' => 'addon/shop/attachment/active_cube_05.png', // 完整地址
+ 'url' => 'addon/shop/attachment/active_cube_05.png', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '107422', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ],
+ [
+ 'name' => time() . $category_id . 'active_cube_06.png', // 附件名称
+ 'real_name' => '魔方素材06', // 原始文件名
+ 'path' => 'addon/shop/attachment/active_cube_06.png', // 完整地址
+ 'url' => 'addon/shop/attachment/active_cube_06.png', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '130868', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ],
+ [
+ 'name' => time() . $category_id . 'active_cube_07.png', // 附件名称
+ 'real_name' => '魔方素材07', // 原始文件名
+ 'path' => 'addon/shop/attachment/active_cube_07.png', // 完整地址
+ 'url' => 'addon/shop/attachment/active_cube_07.png', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '129386', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ],
+ [
+ 'name' => time() . $category_id . 'active_cube_08.png', // 附件名称
+ 'real_name' => '魔方素材08', // 原始文件名
+ 'path' => 'addon/shop/attachment/active_cube_08.png', // 完整地址
+ 'url' => 'addon/shop/attachment/active_cube_08.png', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '81778', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ]
+ ];
+ $exist_attachment_list = $attachment_model->where([
+ [ 'path', 'in', array_column($attachment_list, 'path', '') ]
+ ])->field('path')->select()->toArray();
+
+ if (!empty($exist_attachment_list)) {
+ $attachment_path_list = array_column($exist_attachment_list, 'path', '');
+
+ foreach ($attachment_list as $k => $v) {
+ if (in_array($v[ 'path' ], $attachment_path_list)) {
+ unset($attachment_list[ $k ]);
+ }
+ }
+ $attachment_list = array_values($attachment_list);
+ }
+ if (!empty($attachment_list)) {
+ $attachment_model->insertAll($attachment_list);
+ }
+
+ }
+
+}
diff --git a/niucloud/addon/shop/app/upgrade/v640/upgrade.sql b/niucloud/addon/shop/app/upgrade/v640/upgrade.sql
new file mode 100644
index 000000000..53766094d
--- /dev/null
+++ b/niucloud/addon/shop/app/upgrade/v640/upgrade.sql
@@ -0,0 +1,140 @@
+
+ALTER TABLE `shop_order_refund` CHANGE COLUMN `delivery` `delivery` VARCHAR(3000) NOT NULL DEFAULT '' COMMENT '退货配送信息';
+
+ALTER TABLE `shop_order_goods` ADD COLUMN `shop_active_refund` TINYINT(4) NOT NULL DEFAULT 0 COMMENT '商家主动退款(0否 1是)';
+
+ALTER TABLE `shop_order_goods` ADD COLUMN `shop_active_refund_money` DECIMAL(10, 2) NOT NULL DEFAULT 0.00 COMMENT '商家主动退款金额';
+
+DROP TABLE IF EXISTS `shop_newcomer_member_records`;
+CREATE TABLE `shop_newcomer_member_records` (
+ `record_id` INT(11) NOT NULL AUTO_INCREMENT COMMENT '主键id',
+ `member_id` INT(11) NOT NULL DEFAULT 0 COMMENT '会员id',
+ `validity_time` INT(11) NOT NULL DEFAULT 0 COMMENT '有效期',
+ `create_time` INT(11) NOT NULL DEFAULT 0 COMMENT '参与时间',
+ `update_time` INT(11) NOT NULL DEFAULT 0 COMMENT '更新时间',
+ `is_join` TINYINT(4) NOT NULL DEFAULT 0 COMMENT '是否参与',
+ `order_id` INT(11) NOT NULL DEFAULT 0 COMMENT '参与订单id',
+ `goods_ids` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '参与商品id集合',
+ `sku_ids` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '参与商品规格id集合',
+ PRIMARY KEY (`record_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_general_ci COMMENT='新人专享会员参与记录表';
+
+
+DROP TABLE IF EXISTS `shop_goods_stat`;
+CREATE TABLE `shop_goods_stat` (
+ `id` INT(11) NOT NULL AUTO_INCREMENT,
+ `date` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '日期',
+ `date_time` INT(11) NOT NULL DEFAULT 0 COMMENT '时间戳',
+ `goods_id` INT(11) NOT NULL DEFAULT 0 COMMENT '商品id',
+ `cart_num` INT(11) NOT NULL DEFAULT 0 COMMENT '加入购物车数量',
+ `sale_num` INT(11) NOT NULL DEFAULT 0 COMMENT '商品销量(下单数)',
+ `pay_num` INT(11) NOT NULL DEFAULT 0 COMMENT '支付件数',
+ `pay_money` DECIMAL(10, 2) NOT NULL DEFAULT 0.00 COMMENT '支付总金额',
+ `refund_num` INT(11) NOT NULL DEFAULT 0 COMMENT '退款件数',
+ `refund_money` DECIMAL(10, 2) NOT NULL DEFAULT 0.00 COMMENT '退款总额',
+ `access_num` INT(11) NOT NULL DEFAULT 0 COMMENT '访问次数(浏览量)',
+ `collect_num` INT(11) NOT NULL DEFAULT 0 COMMENT '收藏数量',
+ `evaluate_num` INT(11) NOT NULL DEFAULT 0 COMMENT '评论数量',
+ `goods_visit_member_count` INT(11) NOT NULL DEFAULT 0 COMMENT '商品访客数',
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_general_ci COMMENT='商品数据统计';
+
+
+DROP TABLE IF EXISTS `shop_goods_label_group`;
+CREATE TABLE `shop_goods_label_group` (
+ group_id INT(11) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '分组ID',
+ group_name VARCHAR(255) NOT NULL DEFAULT '' COMMENT '分组名称',
+ sort INT(11) NOT NULL DEFAULT 0 COMMENT '排序',
+ create_time INT(11) NOT NULL DEFAULT 0 COMMENT '创建时间',
+ update_time INT(11) NOT NULL DEFAULT 0 COMMENT '更新时间',
+ PRIMARY KEY (group_id)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_general_ci COMMENT='商品标签分组表';
+
+ALTER TABLE `shop_goods_label` ADD COLUMN `group_id` INT(11) NOT NULL DEFAULT 0 COMMENT '标签分组id';
+
+ALTER TABLE `shop_goods_label` ADD COLUMN `style_type` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '效果设置,diy:自定义,icon:图片';
+
+ALTER TABLE `shop_goods_label` ADD COLUMN `color_json` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '自定义颜色(文字、背景、边框),json格式';
+
+ALTER TABLE `shop_goods_label` ADD COLUMN `icon` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '图标';
+
+ALTER TABLE `shop_goods_label` ADD COLUMN status INT(11) NOT NULL DEFAULT 0 COMMENT '状态,1:启用,0;关闭';
+
+ALTER TABLE `shop_goods_label` MODIFY `memo` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '标签说明' AFTER `status`;
+
+ALTER TABLE `shop_goods_label` MODIFY `sort` INT(11) NOT NULL DEFAULT 0 COMMENT '排序' AFTER `memo`;
+
+ALTER TABLE `shop_goods_label` MODIFY `create_time` INT(11) NOT NULL DEFAULT 0 COMMENT '创建时间' AFTER `sort`;
+
+ALTER TABLE `shop_goods_label` MODIFY `update_time` INT(11) NOT NULL DEFAULT 0 COMMENT '更新时间' AFTER `create_time`;
+
+
+DROP TABLE IF EXISTS `shop_goods_browse`;
+CREATE TABLE `shop_goods_browse` (
+ `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
+ `member_id` INT(11) NOT NULL DEFAULT 0 COMMENT '浏览人',
+ `sku_id` INT(11) NOT NULL DEFAULT 0 COMMENT 'sku_id',
+ `goods_id` INT(11) NOT NULL DEFAULT 0 COMMENT '商品id',
+ `browse_time` INT(11) NOT NULL DEFAULT 0 COMMENT '浏览时间',
+ `goods_cover` VARCHAR(2000) NOT NULL DEFAULT '' COMMENT '商品图片',
+ `goods_name` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '商品名称',
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_general_ci COMMENT='商品浏览历史';
+
+ALTER TABLE `shop_goods` ADD COLUMN `goods_video` VARCHAR(555) DEFAULT '' COMMENT '商品视频';
+
+ALTER TABLE `shop_goods` ADD COLUMN `is_limit` TINYINT(4) NOT NULL DEFAULT 0 COMMENT '商品是否限购(0:否 1:是)';
+
+ALTER TABLE `shop_goods` ADD COLUMN `limit_type` TINYINT(4) NOT NULL DEFAULT 1 COMMENT '限购类型,1:单次限购,2:单人限购';
+
+ALTER TABLE `shop_goods` ADD COLUMN `max_buy` INT(11) NOT NULL DEFAULT 0 COMMENT '限购数';
+
+ALTER TABLE `shop_goods` ADD COLUMN `min_buy` INT(11) NOT NULL DEFAULT 0 COMMENT '起购数';
+
+ALTER TABLE `shop_goods` ADD COLUMN `is_gift` TINYINT(4) NOT NULL DEFAULT 0 COMMENT '商品是否赠品(0:否 1:是)';
+
+ALTER TABLE `shop_goods` ADD COLUMN `access_num` INT(11) NOT NULL DEFAULT 0 COMMENT '访问次数(浏览量)';
+
+ALTER TABLE `shop_goods` ADD COLUMN `cart_num` INT(11) NOT NULL DEFAULT 0 COMMENT '加入购物车数量';
+
+ALTER TABLE `shop_goods` ADD COLUMN `pay_num` INT(11) NOT NULL DEFAULT 0 COMMENT '支付件数';
+
+ALTER TABLE `shop_goods` ADD COLUMN `pay_money` DECIMAL(10, 2) NOT NULL DEFAULT 0.00 COMMENT '支付总金额';
+
+ALTER TABLE `shop_goods` ADD COLUMN `collect_num` INT(11) NOT NULL DEFAULT 0 COMMENT '收藏数量';
+
+ALTER TABLE `shop_goods` ADD COLUMN `evaluate_num` INT(11) NOT NULL DEFAULT 0 COMMENT '评论数量';
+
+ALTER TABLE `shop_goods` ADD COLUMN `refund_num` INT(11) NOT NULL DEFAULT 0 COMMENT '退款件数';
+
+ALTER TABLE `shop_goods` ADD COLUMN `refund_money` DECIMAL(10, 2) NOT NULL DEFAULT 0.00 COMMENT '退款总额';
+
+ALTER TABLE `shop_goods` MODIFY `goods_video` VARCHAR(555) DEFAULT '' COMMENT '商品视频' AFTER `goods_image`;
+
+ALTER TABLE `shop_goods` MODIFY `create_time` INT(11) NOT NULL DEFAULT 0 COMMENT '创建时间' AFTER `refund_money`;
+
+ALTER TABLE `shop_goods` MODIFY `update_time` INT(11) NOT NULL DEFAULT 0 COMMENT '修改时间' AFTER `create_time`;
+
+ALTER TABLE `shop_goods` MODIFY `delete_time` INT(11) NOT NULL DEFAULT 0 COMMENT '删除时间' AFTER `update_time`;
+
+ALTER TABLE `shop_delivery_local_delivery` ADD COLUMN `time_is_open` TINYINT(4) NOT NULL DEFAULT 0 COMMENT '配送时间设置 0 关闭 1 开启';
+
+ALTER TABLE `shop_delivery_local_delivery` ADD COLUMN `time_type` TINYINT(4) NOT NULL DEFAULT 0 COMMENT '时间选取类型 0 每天 1 自定义';
+
+ALTER TABLE `shop_delivery_local_delivery` ADD COLUMN `time_week` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '营业时间 周一 周二.......';
+
+ALTER TABLE `shop_delivery_local_delivery` ADD COLUMN `time_interval` INT(11) NOT NULL DEFAULT 30 COMMENT '时段设置单位分钟';
+
+ALTER TABLE `shop_delivery_local_delivery` ADD COLUMN `advance_day` INT(11) NOT NULL DEFAULT 0 COMMENT '时间选择需提前多少天';
+
+ALTER TABLE `shop_delivery_local_delivery` ADD COLUMN `most_day` INT(11) NOT NULL DEFAULT 7 COMMENT '最多可预约多少天';
+
+ALTER TABLE `shop_delivery_local_delivery` ADD COLUMN `start_time` INT(11) NOT NULL DEFAULT 0 COMMENT '当日的起始时间';
+
+ALTER TABLE `shop_delivery_local_delivery` ADD COLUMN `end_time` INT(11) NOT NULL DEFAULT 0 COMMENT '当日的营业结束时间';
+
+ALTER TABLE `shop_delivery_local_delivery` ADD COLUMN `delivery_time` VARCHAR(2000) NOT NULL DEFAULT '' COMMENT '配送时间段';
+
+ALTER TABLE `shop_active_goods` ADD COLUMN `sku_id` INT(11) DEFAULT 0 COMMENT '商品规格id';
+
+ALTER TABLE `shop_active_goods` MODIFY `sku_id` INT(11) DEFAULT 0 COMMENT '商品规格id' AFTER `goods_id`;
diff --git a/niucloud/addon/shop/app/upgrade/v641/Upgrade.php b/niucloud/addon/shop/app/upgrade/v641/Upgrade.php
new file mode 100644
index 000000000..720e44c49
--- /dev/null
+++ b/niucloud/addon/shop/app/upgrade/v641/Upgrade.php
@@ -0,0 +1,82 @@
+handleData();
+ }
+
+ /**
+ * 处理商品数据
+ */
+ private function handleData()
+ {
+
+ // 同步最近两天的商品统计
+ $start_time = Carbon::today()->getTimestamp();
+ $date_arr = [];
+ for ($i = 1; $i >= 0; $i--) {
+ $date_arr[] = date('Y-m-d', $start_time - ( 86400 * $i ));
+ }
+ ( new StatisticsService() )->syncStatGoods($date_arr);
+
+ $diy_model = new Diy();
+ $where = [
+ [ 'value', '<>', '' ]
+ ];
+ $field = 'id,name,title,template,value';
+ $list = $diy_model->where($where)->field($field)->select()->toArray();
+
+ if (!empty($list)) {
+ foreach ($list as $k => $v) {
+ $diy_data = json_decode($v[ 'value' ], true);
+
+ foreach ($diy_data[ 'value' ] as $ck => $cv) {
+
+ // 精选推荐 组件
+ if ($cv[ 'componentName' ] == 'SingleRecommend') {
+
+ if ($diy_data[ 'value' ][ $ck ][ 'list' ]) {
+
+ foreach ($diy_data[ 'value' ][ $ck ][ 'list' ] as $ps_k => $ps_v) {
+ if ($ps_v[ 'imageUrl' ] == 'addon/shop/diy/index/style3/single_recommend_banner1.png') {
+ $diy_data[ 'value' ][ $ck ][ 'list' ][ $ps_k ][ 'imageUrl' ] = 'addon/shop/diy/index/style3/single_recommend_banner1.jpg';
+ } else if ($ps_v[ 'imageUrl' ] == 'addon/shop/diy/index/style3/single_recommend_banner2.png') {
+ $diy_data[ 'value' ][ $ck ][ 'list' ][ $ps_k ][ 'imageUrl' ] = 'addon/shop/diy/index/style3/single_recommend_banner2.jpg';
+ }
+ }
+ }
+
+ }
+
+ // 轮播搜索 组件
+ if ($cv[ 'componentName' ] == 'CarouselSearch') {
+
+ if (!empty($diy_data[ 'value' ][ $ck ][ 'swiper' ][ 'list' ]) && $diy_data[ 'value' ][ $ck ][ 'swiper' ][ 'list' ][ 0 ][ 'imageUrl' ] == 'addon/shop/diy/index/style3/banner1.jpg') {
+ $diy_data[ 'value' ][ $ck ][ 'swiper' ][ 'imageHeight' ] = 274;
+ $diy_data[ 'value' ][ $ck ][ 'swiper' ][ 'list' ][ 0 ][ 'imgWidth' ] = 750;
+ $diy_data[ 'value' ][ $ck ][ 'swiper' ][ 'list' ][ 0 ][ 'imgHeight' ] = 580;
+ $diy_data[ 'value' ][ $ck ][ 'swiper' ][ 'list' ][ 0 ][ 'width' ] = 355;
+ $diy_data[ 'value' ][ $ck ][ 'swiper' ][ 'list' ][ 0 ][ 'height' ] = 274.53;
+ }
+
+ }
+
+ }
+
+ $diy_data = json_encode($diy_data);
+ $diy_model->where([ [ 'id', '=', $v[ 'id' ] ] ])->update([ 'value' => $diy_data ]);
+ }
+ }
+
+ }
+
+}
diff --git a/niucloud/addon/shop/app/upgrade/v641/upgrade.sql b/niucloud/addon/shop/app/upgrade/v641/upgrade.sql
new file mode 100644
index 000000000..fd3e72791
--- /dev/null
+++ b/niucloud/addon/shop/app/upgrade/v641/upgrade.sql
@@ -0,0 +1,84 @@
+
+DROP TABLE IF EXISTS `shop_manjian_record`;
+
+ALTER TABLE `shop_order_goods` ADD COLUMN `is_gift` TINYINT(4) NOT NULL DEFAULT 0 COMMENT '是否是赠品(0否 1是)';
+
+
+DROP TABLE IF EXISTS `shop_manjian_give_records`;
+CREATE TABLE `shop_manjian_give_records` (
+ `record_id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '赠送记录id',
+ `manjian_id` INT(11) NOT NULL DEFAULT 0 COMMENT '满减送活动id',
+ `order_id` INT(11) NOT NULL DEFAULT 0 COMMENT '订单id',
+ `member_id` INT(11) NOT NULL DEFAULT 0 COMMENT '会员id',
+ `level` INT(11) NOT NULL DEFAULT 0 COMMENT '优惠层级',
+ `point` INT(11) NOT NULL DEFAULT 0 COMMENT '赠送积分数量',
+ `balance` DECIMAL(10, 2) NOT NULL DEFAULT 0.00 COMMENT '赠送余额',
+ `coupon_json` TEXT DEFAULT NULL COMMENT '赠送优惠券',
+ `goods_json` TEXT DEFAULT NULL COMMENT '赠送商品',
+ `sku_ids` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '满足条件的商品规格id',
+ `create_time` int NOT NULL DEFAULT 0 COMMENT '创建时间',
+ PRIMARY KEY (`record_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_general_ci COMMENT='满减送记录表';
+
+
+ALTER TABLE `shop_goods` CHANGE COLUMN `is_gift` `is_gift` TINYINT NOT NULL DEFAULT 0 COMMENT '商品是否赠品(0:否 1:是)';
+
+
+DROP TABLE IF EXISTS `shop_manjian_goods`;
+CREATE TABLE `shop_manjian_goods` (
+ `manjian_goods_id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '满减商品活动id',
+ `manjian_id` INT(11) NOT NULL DEFAULT 0 COMMENT '满减活动id',
+ `goods_id` INT(11) NOT NULL DEFAULT 0 COMMENT '商品id',
+ `sku_id` INT(11) NOT NULL DEFAULT 0 COMMENT '规格id',
+ `goods_type` VARCHAR(255) NOT NULL DEFAULT 'all_goods' COMMENT '参与商品 all_goods:全部商品参与 selected_goods:指定商品 selected_goods_not:指定商品不参与 ',
+ `status` TINYINT(4) NOT NULL DEFAULT 0 COMMENT '状态(0未开始1进行中2已结束-1已关闭)',
+ PRIMARY KEY (`manjian_goods_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_general_ci COMMENT='满减商品表';
+
+
+DROP TABLE IF EXISTS `shop_manjian`;
+CREATE TABLE `shop_manjian` (
+ `manjian_id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '满减活动id',
+ `manjian_name` VARCHAR(50) NOT NULL DEFAULT '' COMMENT '名称',
+ `condition_type` VARCHAR(255) NOT NULL DEFAULT 'over_n_yuan' COMMENT '条件类型 over_n_yuan:满N元 over_n_piece:满N件',
+ `goods_type` VARCHAR(255) NOT NULL DEFAULT 'all_goods' COMMENT '参与商品 all_goods:全部商品参与 selected_goods:指定商品 selected_goods_not:指定商品不参与 ',
+ `join_member_type` VARCHAR(255) NOT NULL DEFAULT 'all_member' COMMENT '参与会员 all_member:所有会员参与 selected_member_level:指定会员等级 selected_member_label:指定会员标签 ',
+ `rule_type` VARCHAR(255) NOT NULL DEFAULT 'ladder' COMMENT '优惠规格 ladder:阶梯优惠 cycle:循环优惠',
+ `rule_json` TEXT DEFAULT NULL COMMENT '优惠规则json',
+ `goods_ids` TEXT DEFAULT NULL COMMENT '商品id集',
+ `level_ids` TEXT DEFAULT NULL COMMENT '会员等级id集',
+ `label_ids` TEXT DEFAULT NULL COMMENT '会员标签id集',
+ `status` INT(11) NOT NULL DEFAULT 0 COMMENT '状态(0未开始1进行中2已结束-1已关闭)',
+ `start_time` INT(11) NOT NULL DEFAULT 0 COMMENT '开始时间',
+ `end_time` INT(11) NOT NULL DEFAULT 0 COMMENT '结束时间',
+ `create_time` INT(11) NOT NULL DEFAULT 0 COMMENT '创建时间',
+ `update_time` INT(11) NOT NULL DEFAULT 0 COMMENT '修改时间',
+ `remark` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '备注',
+ `total_order_money` DECIMAL(10, 2) NOT NULL DEFAULT 0.00 COMMENT '活动累计金额',
+ `total_order_num` INT(11) NOT NULL DEFAULT 0 COMMENT '活动累计订单数',
+ `total_member_num` INT(11) NOT NULL DEFAULT 0 COMMENT '活动参与会员数',
+ `total_point` INT(11) NOT NULL DEFAULT 0 COMMENT '活动累计赠送积分',
+ `total_balance` DECIMAL(10, 2) NOT NULL DEFAULT 0.00 COMMENT '活动累计赠送余额',
+ `total_coupon_num` INT(11) NOT NULL DEFAULT 0 COMMENT '活动累计赠送优惠券数',
+ `total_goods_num` INT(11) NOT NULL DEFAULT 0 COMMENT '活动累计赠送商品数',
+ PRIMARY KEY (`manjian_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_general_ci COMMENT='满减活动表';
+
+
+DROP TABLE IF EXISTS `shop_goods_rank`;
+CREATE TABLE `shop_goods_rank` (
+ `rank_id` INT(11) NOT NULL AUTO_INCREMENT,
+ `name` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '榜单名称',
+ `rank_type` VARCHAR(100) NOT NULL DEFAULT '' COMMENT '排行周期 day=天,week=周,month=月, quarter=季度',
+ `goods_source` VARCHAR(100) NOT NULL DEFAULT '' COMMENT '来源类型 goods=指定商品,category=指定分类,brand=指定品牌, label=指定标签',
+ `rule_type` VARCHAR(100) NOT NULL DEFAULT '' COMMENT '排序规则 sale=按照销量,collect=按收藏数,evaluate=按评价数, access=按照浏览量',
+ `goods_json` TEXT DEFAULT NULL COMMENT '商品信息',
+ `category_ids` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '商品分类id',
+ `brand_ids` VARCHAR(255) NOT NULL DEFAULT '0' COMMENT '商品品牌id',
+ `label_ids` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '商品标签id,多个逗号隔开',
+ `sort` INT(11) NOT NULL DEFAULT 0 COMMENT '排序号',
+ `status` INT(11) NOT NULL DEFAULT 1 COMMENT '显示状态(0不显示 1显示)',
+ `create_time` INT(11) NOT NULL DEFAULT 0 COMMENT '创建时间',
+ `update_time` INT(11) NOT NULL DEFAULT 0 COMMENT '修改时间',
+ PRIMARY KEY (`rank_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_general_ci COMMENT='商品排行榜';
diff --git a/niucloud/addon/shop/app/upgrade/v643/Upgrade.php b/niucloud/addon/shop/app/upgrade/v643/Upgrade.php
new file mode 100644
index 000000000..c9b5b4618
--- /dev/null
+++ b/niucloud/addon/shop/app/upgrade/v643/Upgrade.php
@@ -0,0 +1,63 @@
+handleData();
+ }
+
+ /**
+ * 处理商品数据
+ */
+ private function handleData()
+ {
+ // 创建素材
+ $category_model = new SysAttachmentCategory();
+ $category_info = $category_model->where([
+ [ 'name', '=', '商城素材' ]
+ ])->field('id')->findOrEmpty()->toArray();
+
+ if (!empty($category_info)) {
+ $category_id = $category_info[ 'id' ];
+ } else {
+ $attachment_category = $category_model->create([
+ 'pid' => 0,
+ 'type' => 'image',
+ 'name' => '商城素材',
+ 'sort' => 1
+ ]);
+ $category_id = $attachment_category->id;
+ }
+
+ $attachment_model = new SysAttachment();
+
+ $attachment_list = [
+ 'name' => time() . $category_id . 'nav_sow_community.png', // 附件名称
+ 'real_name' => '种草社区', // 原始文件名
+ 'path' => 'addon/shop/attachment/nav_sow_community.png', // 完整地址
+ 'url' => 'addon/shop/attachment/nav_sow_community.png', // 网络地址
+ 'dir' => 'addon/shop/attachment', // 附件路径
+ 'att_size' => '24576', // 附件大小
+ 'att_type' => 'image', // 附件类型image,video
+ 'storage_type' => 'local', // 图片上传类型 local本地 aliyun 阿里云oss qiniu 七牛 ....
+ 'cate_id' => $category_id, // 素材分类id
+ 'create_time' => time()
+ ];
+ $exist_attachment_list = $attachment_model->where([
+ [ 'path', '=', 'addon/shop/attachment/nav_sow_community.png' ]
+ ])->field('path')->findOrEmpty()->toArray();
+
+ if (empty($exist_attachment_list)) {
+ $attachment_model->create($attachment_list);
+ }
+
+ }
+
+}
diff --git a/niucloud/addon/shop/app/upgrade/v643/upgrade.sql b/niucloud/addon/shop/app/upgrade/v643/upgrade.sql
new file mode 100644
index 000000000..6cd1523ea
--- /dev/null
+++ b/niucloud/addon/shop/app/upgrade/v643/upgrade.sql
@@ -0,0 +1,12 @@
+
+ALTER TABLE `shop_order_goods` ADD COLUMN `form_record_id` INT(11) NOT NULL DEFAULT 0 COMMENT '万能表单记录id';
+
+ALTER TABLE `shop_order` ADD COLUMN `form_record_id` INT(11) NOT NULL DEFAULT 0 COMMENT '万能表单记录id';
+
+ALTER TABLE `shop_goods` ADD COLUMN `form_id` INT(11) NOT NULL DEFAULT 0 COMMENT '万能表单id';
+
+ALTER TABLE `shop_goods` MODIFY `form_id` INT(11) NOT NULL DEFAULT 0 COMMENT '万能表单id' AFTER `poster_id`;
+
+ALTER TABLE `shop_goods_brand` ADD COLUMN `color_json` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '自定义颜色(文字、背景、边框),json格式';
+
+ALTER TABLE `shop_goods_brand` MODIFY `color_json` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '自定义颜色(文字、背景、边框),json格式' AFTER `desc`;
diff --git a/niucloud/addon/shop/app/upgrade/v644/Upgrade.php b/niucloud/addon/shop/app/upgrade/v644/Upgrade.php
new file mode 100644
index 000000000..3ecdd92d6
--- /dev/null
+++ b/niucloud/addon/shop/app/upgrade/v644/Upgrade.php
@@ -0,0 +1,51 @@
+handleData();
+ $this->handleThemeColorData();
+ }
+
+ /**
+ * 处理商品数据
+ */
+ private function handleData()
+ {
+ try {
+
+ $brand_model = new Brand();
+ // 更新商品品牌自定义颜色
+ $brand_model->where([ [ 'brand_id', '>', 0 ] ])->update([
+ 'color_json' => [
+ 'text_color' => 'rgba(255, 255, 255, 1)',
+ 'bg_color' => 'rgba(255, 65, 66, 1)',
+ 'border_color' => ''
+ ]
+ ]);
+ } catch (\Exception $e) {
+
+ }
+
+ }
+
+ /**
+ * 处理主题风格配色数据
+ */
+ private function handleThemeColorData()
+ {
+ $listener = new ThemeColorListener();
+ $addon_theme = $listener->handle([ 'key' => 'shop' ]);
+ $diy_service = new DiyService();
+ $diy_service->initAddonThemeColorData('shop', $addon_theme);
+ }
+
+}
diff --git a/niucloud/addon/shop/app/upgrade/v644/upgrade.sql b/niucloud/addon/shop/app/upgrade/v644/upgrade.sql
new file mode 100644
index 000000000..e7094cd5e
--- /dev/null
+++ b/niucloud/addon/shop/app/upgrade/v644/upgrade.sql
@@ -0,0 +1,4 @@
+
+ALTER TABLE `shop_coupon` ADD COLUMN `give_count` INT(11) NOT NULL DEFAULT 0 COMMENT '已发放数量';
+
+ALTER TABLE `shop_coupon` MODIFY `give_count` INT(11) NOT NULL DEFAULT 0 COMMENT '已发放数量' AFTER `receive_count`;
diff --git a/niucloud/addon/shop/app/upgrade/v645/Upgrade.php b/niucloud/addon/shop/app/upgrade/v645/Upgrade.php
new file mode 100644
index 000000000..741091af1
--- /dev/null
+++ b/niucloud/addon/shop/app/upgrade/v645/Upgrade.php
@@ -0,0 +1,86 @@
+handleDiscountData();
+ }
+
+ /**
+ * 处理限时折扣数据
+ */
+ private function handleDiscountData()
+ {
+ $data = ( new Active() )->where([ [ 'active_class', '=', ActiveDict::DISCOUNT ] ])->with([ 'activeGoods' ])->select()->toArray();
+ try {
+ if (!empty($data)) {
+ $discount_data = $discount_goods_data = [];
+ foreach ($data as $value) {
+ $discount_data[] = [
+ 'discount_id' => $value[ 'active_id' ],
+ 'name' => $value[ 'active_name' ],
+ 'remark' => $value[ 'active_desc' ],
+ 'start_time' => $this->getFormatTime($value[ 'start_time' ]),
+ 'end_time' => $this->getFormatTime($value[ 'end_time' ]),
+ 'status' => $value[ 'active_status' ],
+ 'create_time' => $this->getFormatTime($value[ 'create_time' ]),
+ 'update_time' => $this->getFormatTime($value[ 'update_time' ]),
+ ];
+ if (!empty($value[ 'activeGoods' ])) {
+ foreach ($value[ 'activeGoods' ] as $v) {
+ $active_goods_value = json_decode($v[ 'active_goods_value' ], true);
+ if (!empty($active_goods_value)) {
+ foreach ($active_goods_value as $item) {
+ $discount_goods_data[] = [
+ 'discount_id' => $v[ 'active_id' ],
+ 'goods_id' => $v[ 'goods_id' ],
+ 'sku_id' => $item[ 'sku_id' ],
+ 'status' => $v[ 'active_goods_status' ],
+ 'type' => $item[ 'discount_type' ],
+ 'rate' => $item[ 'discount_rate' ],
+ 'reduce_money' => $item[ 'reduce_money' ],
+ 'discount_price' => $item[ 'discount_price' ],
+ 'is_enabled' => $item[ 'is_enabled' ] ?? 0,
+ ];
+ }
+ }
+ }
+ }
+ }
+ }
+ Db::startTrans();
+ if (!empty($discount_data) && !empty($discount_goods_data)) {
+ ( new Discount() )->where([ [ 'discount_id', '>', 0 ] ])->delete();
+ ( new DiscountGoods() )->where([ [ 'discount_goods_id', '>', 0 ] ])->delete();
+ ( new Discount() )->insertAll($discount_data);
+ ( new DiscountGoods() )->insertAll($discount_goods_data);
+ }
+ Db::commit();
+ return true;
+ } catch (\Exception $e) {
+ Db::rollback();
+ }
+ }
+
+ public function getFormatTime($time)
+ {
+ if (is_numeric($time) && ( strlen($time) == 10 || strlen($time) == 13 )) {
+ return (int) $time;
+ }
+
+ $timestamp = strtotime($time);
+
+ return $timestamp !== false ? $timestamp : 0;
+ }
+
+}
diff --git a/niucloud/addon/shop/app/upgrade/v645/upgrade.sql b/niucloud/addon/shop/app/upgrade/v645/upgrade.sql
new file mode 100644
index 000000000..165dd04d1
--- /dev/null
+++ b/niucloud/addon/shop/app/upgrade/v645/upgrade.sql
@@ -0,0 +1,89 @@
+
+DROP TABLE IF EXISTS `shop_discount`;
+CREATE TABLE `shop_discount`
+(
+ `discount_id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '活动id',
+ `name` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '活动名称',
+ `remark` TEXT NOT NULL COMMENT '活动说明',
+ `start_time` INT(11) NOT NULL DEFAULT 0 COMMENT '活动开始时间',
+ `end_time` INT(11) NOT NULL DEFAULT 0 COMMENT '活动结束时间',
+ `status` VARCHAR(50) NOT NULL DEFAULT '' COMMENT '活动状态',
+ `create_time` INT(11) NOT NULL DEFAULT 0 COMMENT '添加时间',
+ `update_time` INT(11) NOT NULL DEFAULT 0 COMMENT '修改时间',
+ `order_money` DECIMAL(10, 2) NOT NULL DEFAULT 0.00 COMMENT '活动累计金额',
+ `order_num` INT(11) NOT NULL DEFAULT 0 COMMENT '活动累计订单数',
+ `member_num` INT(11) NOT NULL DEFAULT 0 COMMENT '活动参与会员数',
+ `success_num` INT(11) NOT NULL DEFAULT 0 COMMENT '活动成功参与会员数',
+ PRIMARY KEY (`discount_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_general_ci COMMENT='限时折扣表';
+
+
+DROP TABLE IF EXISTS `shop_discount_goods`;
+CREATE TABLE `shop_discount_goods`
+(
+ `discount_goods_id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '活动商品id',
+ `discount_id` INT(11) NOT NULL DEFAULT 0 COMMENT '活动id',
+ `goods_id` INT(11) NOT NULL DEFAULT 0 COMMENT '商品id',
+ `sku_id` INT(11) NOT NULL DEFAULT 0 COMMENT '商品规格id',
+ `status` VARCHAR(50) NOT NULL DEFAULT '' COMMENT '商品状态',
+ `type` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '折扣类型',
+ `rate` DECIMAL(10, 2) NOT NULL DEFAULT 0.00 COMMENT '折扣',
+ `reduce_money` DECIMAL(10, 2) NOT NULL DEFAULT 0.00 COMMENT '减钱',
+ `discount_price` DECIMAL(10, 2) NOT NULL DEFAULT 0.00 COMMENT '活动商品价格(展示,搜索)',
+ `order_money` DECIMAL(10, 2) NOT NULL DEFAULT 0.00 COMMENT '活动累计金额',
+ `order_num` INT(11) NOT NULL DEFAULT 0 COMMENT '活动累计订单数',
+ `member_num` INT(11) NOT NULL DEFAULT 0 COMMENT '活动参与会员数',
+ `success_num` INT(11) NOT NULL DEFAULT 0 COMMENT '活动成功参与会员数',
+ `is_enabled` INT(11) NOT NULL DEFAULT 1 COMMENT '是否参与活动',
+ PRIMARY KEY (`discount_goods_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_general_ci COMMENT='限时折扣商品表';
+
+
+DROP TABLE IF EXISTS `shop_coupon_send_records`;
+CREATE TABLE `shop_coupon_send_records`
+(
+ `id` INT(11) NOT NULL AUTO_INCREMENT COMMENT '主键id',
+ `coupon_id` INT(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '优惠券id',
+ `send_num` INT(11) NOT NULL COMMENT '每位会员发放数量',
+ `range_type` VARCHAR(20) NOT NULL DEFAULT '' COMMENT '发券范围',
+ `range_param` TEXT DEFAULT NULL COMMENT '范围对应参数',
+ `success_num` INT(11) NOT NULL DEFAULT 0 COMMENT '发放成功数',
+ `status` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '状态 wait-待发送 process-发送中 finish-结束',
+ `member_num` INT(11) NOT NULL DEFAULT 0 COMMENT '发放会员数',
+ `end_time` INT(11) NOT NULL DEFAULT 0 COMMENT '发放结束时间',
+ `admin_uid` INT(11) NOT NULL DEFAULT 0 COMMENT '操作人id',
+ `admin_username` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '操作人名称',
+ `create_time` INT(11) NOT NULL DEFAULT 0 COMMENT '创建时间',
+ `update_time` INT(11) NOT NULL DEFAULT 0 COMMENT '更新时间',
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_general_ci COMMENT='优惠券发券记录表';
+
+ALTER TABLE `shop_store` CHANGE COLUMN `trade_time` `trade_time` VARCHAR (255) NOT NULL DEFAULT '' COMMENT '营业时间(文本展示使用)';
+
+ALTER TABLE `shop_store` ADD COLUMN `time_week` TEXT DEFAULT NULL COMMENT '自定义的营业时间["0","1","2","3","4","5","6"]周日-周六';
+
+ALTER TABLE `shop_store` ADD COLUMN `trade_time_json` TEXT DEFAULT NULL COMMENT '营业时间';
+
+ALTER TABLE `shop_store` ADD COLUMN `time_interval` INT(11) NOT NULL DEFAULT 0 COMMENT '时段设置(分钟)';
+
+ALTER TABLE `shop_store` MODIFY `create_time` INT (11) NOT NULL DEFAULT 0 COMMENT '添加时间' AFTER `time_interval`;
+
+ALTER TABLE `shop_store` MODIFY `update_time` INT (11) NOT NULL DEFAULT 0 COMMENT '更新时间' AFTER `create_time`;
+
+ALTER TABLE `shop_order` CHANGE COLUMN `delivery_time` `delivery_time` INT NOT NULL DEFAULT 0 COMMENT '订单发货时间/自提订单自提时间';
+
+ALTER TABLE `shop_order` ADD COLUMN `buyer_ask_delivery_time` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '购买人要求的配送/发货/自提时间(文本)';
+
+ALTER TABLE `shop_order` MODIFY `buyer_ask_delivery_time` VARCHAR (255) NOT NULL DEFAULT '' COMMENT '购买人要求的配送/发货/自提时间(文本)' AFTER `delivery_time`;
+
+ALTER TABLE `shop_point_exchange_order` MODIFY COLUMN `order_money` DECIMAL(10, 2) NOT NULL DEFAULT 0.00 COMMENT '订单金额';
+
+ALTER TABLE `shop_order_batch_delivery` CHANGE COLUMN type type VARCHAR(255) NOT NULL DEFAULT '' COMMENT '操作类型 批量发货 批量打单 ....';
+
+ALTER TABLE `shop_order_batch_delivery` MODIFY COLUMN create_time INT NOT NULL DEFAULT 0 COMMENT '创建时间';
+
+ALTER TABLE `shop_goods_evaluate` MODIFY COLUMN content VARCHAR(3000) NOT NULL DEFAULT '' COMMENT '评价内容';
+
+ALTER TABLE `shop_delivery_local_delivery` COMMENT = '自提点表';
+
+ALTER TABLE `shop_delivery_company` COMMENT = '站点快递表';
diff --git a/niucloud/addon/shop/app/upgrade/v647/Upgrade.php b/niucloud/addon/shop/app/upgrade/v647/Upgrade.php
new file mode 100644
index 000000000..eed4c5e71
--- /dev/null
+++ b/niucloud/addon/shop/app/upgrade/v647/Upgrade.php
@@ -0,0 +1,55 @@
+handleGoodsData();
+ }
+
+ /**
+ * 处理商品数据,参数模板结构调整
+ */
+ private function handleGoodsData()
+ {
+ try {
+ $delete_list = ( new Goods() )->onlyTrashed()->where([ [ 'attr_ids', '<>', '' ] ])->field('goods_id,attr_ids')->select()->toArray();
+ if (!empty($delete_list)) {
+ foreach ($delete_list as $k => $v) {
+ if (gettype($v[ 'attr_ids' ]) != 'array') {
+ if (!empty($v[ 'attr_ids' ])) {
+ $delete_list[ $k ][ 'attr_ids' ] = [ $v[ 'attr_ids' ] ];
+ } else {
+ $delete_list[ $k ][ 'attr_ids' ] = [];
+ }
+ ( new Goods() )->onlyTrashed()->where([ [ 'goods_id', '=', $v[ 'goods_id' ] ] ])->update([ 'attr_ids' => $delete_list[ $k ][ 'attr_ids' ] ]);
+ }
+ }
+ }
+
+ $list = ( new Goods() )->where([ [ 'attr_ids', '<>', '' ] ])->field('goods_id,attr_ids')->select()->toArray();
+ if (!empty($list)) {
+ foreach ($list as $k => $v) {
+ if (gettype($v[ 'attr_ids' ]) != 'array') {
+ if (!empty($v[ 'attr_ids' ])) {
+ $list[ $k ][ 'attr_ids' ] = [ $v[ 'attr_ids' ] ];
+ } else {
+ $list[ $k ][ 'attr_ids' ] = [];
+ }
+ ( new Goods() )->where([ [ 'goods_id', '=', $v[ 'goods_id' ] ] ])->update([ 'attr_ids' => $list[ $k ][ 'attr_ids' ] ]);
+ }
+ }
+ }
+
+ } catch (\Exception $e) {
+ Log::write('商城插件升级v6.4.7版本,发生错误,Line:' . $e->getLine() . ',Message:' . $e->getMessage() . ',File:' . $e->getFile());
+ }
+ }
+
+}
diff --git a/niucloud/addon/shop/app/upgrade/v647/upgrade.sql b/niucloud/addon/shop/app/upgrade/v647/upgrade.sql
new file mode 100644
index 000000000..37fd49c3a
--- /dev/null
+++ b/niucloud/addon/shop/app/upgrade/v647/upgrade.sql
@@ -0,0 +1,10 @@
+
+ALTER TABLE `shop_order_delivery` ADD COLUMN third_delivery VARCHAR(50) NOT NULL DEFAULT '' COMMENT '配送方(三方配送)';
+
+ALTER TABLE `shop_order_delivery` MODIFY `remark` VARCHAR(1000) NOT NULL DEFAULT '' AFTER `third_delivery`;
+
+ALTER TABLE `shop_order_delivery` MODIFY `create_time` INT(11) NOT NULL DEFAULT 0 COMMENT '创建时间' AFTER `remark`;
+
+ALTER TABLE `shop_goods` CHANGE COLUMN `attr_id` `attr_ids` TEXT DEFAULT NULL COMMENT '商品参数id,支持多个';
+
+ALTER TABLE `shop_delivery_local_delivery` CHANGE COLUMN `delivery_time` `delivery_time` TEXT DEFAULT NULL COMMENT '配送时间段';
diff --git a/niucloud/addon/shop/app/upgrade/v648/Upgrade.php b/niucloud/addon/shop/app/upgrade/v648/Upgrade.php
new file mode 100644
index 000000000..4511274c7
--- /dev/null
+++ b/niucloud/addon/shop/app/upgrade/v648/Upgrade.php
@@ -0,0 +1,15 @@
+handle();
+ }
+
+}
diff --git a/niucloud/addon/shop/app/upgrade/v648/upgrade.sql b/niucloud/addon/shop/app/upgrade/v648/upgrade.sql
new file mode 100644
index 000000000..e29d9a49d
--- /dev/null
+++ b/niucloud/addon/shop/app/upgrade/v648/upgrade.sql
@@ -0,0 +1,60 @@
+
+ALTER TABLE `shop_discount_goods` CHANGE COLUMN `rate` `rate` DECIMAL (10, 2) NOT NULL DEFAULT 0.00 COMMENT '折扣';
+
+ALTER TABLE `shop_order_refund_log` CHANGE COLUMN `main_type` `main_type` VARCHAR (255) NOT NULL DEFAULT '' COMMENT '操作人类型';
+
+ALTER TABLE `shop_order_refund_log` CHANGE COLUMN `status` `status` INT NOT NULL DEFAULT 0 COMMENT '退款状态';
+
+ALTER TABLE `shop_order_refund_log` CHANGE COLUMN `content` `content` VARCHAR (255) NOT NULL DEFAULT '' COMMENT '日志内容';
+
+ALTER TABLE `shop_order_refund_log` CHANGE COLUMN `create_time` `create_time` INT NOT NULL DEFAULT 0 COMMENT '创建时间';
+
+ALTER TABLE `shop_order_refund` ADD COLUMN `delete_time` INT(11) NOT NULL DEFAULT 0 COMMENT '是否删除(针对后台)';
+
+ALTER TABLE `shop_order_log` CHANGE COLUMN `main_type` `main_type` VARCHAR (255) NOT NULL DEFAULT '' COMMENT '操作人类型';
+
+ALTER TABLE `shop_order_log` CHANGE COLUMN `content` `content` VARCHAR (255) NOT NULL DEFAULT '' COMMENT '日志内容';
+
+ALTER TABLE `shop_order_goods` ADD COLUMN `delete_time` INT(11) NOT NULL DEFAULT 0 COMMENT '是否删除(针对后台)';
+
+ALTER TABLE `shop_order_discount` ADD COLUMN `member_id` INT(11) NOT NULL DEFAULT 0 COMMENT '会员id';
+
+ALTER TABLE `shop_order_discount` ADD COLUMN `goods_id` INT(11) NOT NULL DEFAULT 0 COMMENT '商品id';
+
+ALTER TABLE `shop_order_discount` ADD COLUMN `sku_id` INT(11) NOT NULL DEFAULT 0 COMMENT 'sku_id';
+
+ALTER TABLE `shop_order_delivery` CHANGE COLUMN `third_delivery` `third_delivery` VARCHAR (50) NOT NULL DEFAULT '' COMMENT '配送方(三方配送)';
+
+ALTER TABLE `shop_order_delivery` CHANGE COLUMN `remark` `remark` VARCHAR (1000) NOT NULL DEFAULT '' COMMENT '备注';
+
+ALTER TABLE `shop_order` ADD COLUMN `relate_order_id` INT(11) NOT NULL DEFAULT 0 COMMENT '关联活动来源订单id';
+
+ALTER TABLE `shop_order` ADD COLUMN `relate_source` VARCHAR(255) NOT NULL DEFAULT '' COMMENT 'seckill 秒杀系统 ';
+
+ALTER TABLE `shop_goods` ADD COLUMN `diy_detail_id` INT(11) NOT NULL DEFAULT 0 COMMENT '自定义详情id';
+
+ALTER TABLE `shop_goods` MODIFY `diy_detail_id` INT (11) NOT NULL DEFAULT 0 COMMENT '自定义详情id' AFTER form_id;
+
+ALTER TABLE `shop_delivery_electronic_sheet` ADD COLUMN `interface_type` CHAR(20) NOT NULL DEFAULT '' COMMENT '快递公司类型 kdbird:快递鸟 kd100:快递100';
+
+ALTER TABLE `shop_delivery_electronic_sheet` ADD COLUMN `exp_type_name` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '物流公司业务类型名称';
+
+ALTER TABLE `shop_delivery_electronic_sheet` ADD COLUMN `temp_id` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '主模版:快递100用';
+
+ALTER TABLE `shop_delivery_electronic_sheet` ADD COLUMN `child_temp_id` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '子模版:快递100用';
+
+ALTER TABLE `shop_delivery_electronic_sheet` ADD COLUMN `back_temp_id` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '回单模版:快递100用';
+
+ALTER TABLE `shop_delivery_electronic_sheet` ADD COLUMN `interface_data` TEXT DEFAULT NULL COMMENT '接口参数';
+
+ALTER TABLE `shop_delivery_company` CHANGE COLUMN `express_no` `express_no` VARCHAR (255) NOT NULL DEFAULT '' COMMENT '快递鸟:物流公司编号(用于物流跟踪)';
+
+ALTER TABLE `shop_delivery_company` CHANGE COLUMN `express_no_electronic_sheet` `express_no_electronic_sheet` VARCHAR (255) NOT NULL DEFAULT '' COMMENT '快递鸟:物流公司编号(用于电子面单)';
+
+ALTER TABLE `shop_delivery_company` ADD COLUMN `kd100_express_no` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '快递100:物流公司编号(用于物流跟踪)';
+
+ALTER TABLE `shop_delivery_company` ADD COLUMN `kd100_express_no_electronic_sheet` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '快递100:物流公司编号(用于电子面单)';
+
+ALTER TABLE `shop_point_exchange` MODIFY COLUMN `title` VARCHAR (255) NOT NULL DEFAULT '' COMMENT '副标题';
+
+ALTER TABLE `shop_coupon_send_records` MODIFY COLUMN `send_num` INT NOT NULL DEFAULT 0 COMMENT '每位会员发放数量';
diff --git a/niucloud/addon/shop/app/upgrade/v649/upgrade.sql b/niucloud/addon/shop/app/upgrade/v649/upgrade.sql
new file mode 100644
index 000000000..2b13e8cbf
--- /dev/null
+++ b/niucloud/addon/shop/app/upgrade/v649/upgrade.sql
@@ -0,0 +1,5 @@
+ALTER TABLE `shop_invoice`
+ CHANGE COLUMN trade_id trade_id VARCHAR(1000) NOT NULL DEFAULT '' COMMENT '业务id集';
+
+ALTER TABLE `shop_invoice`
+ ADD COLUMN pay_voucher TEXT DEFAULT NULL COMMENT '支付凭证';
\ No newline at end of file
diff --git a/niucloud/addon/shop/app/validate/cart/Cart.php b/niucloud/addon/shop/app/validate/cart/Cart.php
new file mode 100644
index 000000000..b6f5f1f25
--- /dev/null
+++ b/niucloud/addon/shop/app/validate/cart/Cart.php
@@ -0,0 +1,42 @@
+ 'require|gt:0',
+ 'goods_id' => 'require|gt:0',
+ 'sku_id' => 'require|gt:0',
+ 'num' => 'require',
+ ];
+
+ protected $message = [
+ 'goods_id.require' => [ 'common_validate.require', [ 'goods_id' ] ],
+ 'sku_id.require' => [ 'common_validate.require', [ 'sku_id' ] ],
+ 'num.require' => [ 'common_validate.require', [ 'num' ] ],
+ ];
+
+ protected $scene = [
+ "add" => [ 'member_id', 'goods_id', 'sku_id', 'num', 'status', 'invalid_remark' ],
+ "edit" => [ 'member_id', 'sku_id', 'num', 'status', 'invalid_remark' ]
+ ];
+
+}
diff --git a/niucloud/addon/shop/app/validate/delivery/Company.php b/niucloud/addon/shop/app/validate/delivery/Company.php
new file mode 100644
index 000000000..fc3b616c6
--- /dev/null
+++ b/niucloud/addon/shop/app/validate/delivery/Company.php
@@ -0,0 +1,37 @@
+ 'require',
+ ];
+
+ protected $message = [
+ 'company_name.require' => [ 'common_validate.require', [ 'company_name' ] ],
+ ];
+
+ protected $scene = [
+ "add" => [ 'company_name' ],
+ "edit" => [ 'company_name' ]
+ ];
+
+}
diff --git a/niucloud/addon/shop/app/validate/delivery/ElectronicSheet.php b/niucloud/addon/shop/app/validate/delivery/ElectronicSheet.php
new file mode 100644
index 000000000..8eaa72386
--- /dev/null
+++ b/niucloud/addon/shop/app/validate/delivery/ElectronicSheet.php
@@ -0,0 +1,39 @@
+ 'require',
+ 'express_company_id' => 'require',
+ ];
+
+ protected $message = [
+ 'template_name.require' => [ 'common_validate.require', [ 'template_name' ] ],
+ 'express_company_id.require' => [ 'common_validate.require', [ 'express_company_id' ] ],
+ ];
+
+ protected $scene = [
+ "add" => [ 'template_name', 'express_company_id' ],
+ "edit" => [ 'template_name', 'express_company_id' ]
+ ];
+
+}
diff --git a/niucloud/addon/shop/app/validate/delivery/Store.php b/niucloud/addon/shop/app/validate/delivery/Store.php
new file mode 100644
index 000000000..a8eccd331
--- /dev/null
+++ b/niucloud/addon/shop/app/validate/delivery/Store.php
@@ -0,0 +1,44 @@
+ 'require',
+ 'store_mobile' => 'require|mobile',
+ 'address' => 'require',
+ 'trade_time' => 'require',
+ ];
+
+ protected $message = [
+ 'store_name.require' => [ 'common_validate.require', [ 'store_name' ] ],
+ 'store_mobile.require' => [ 'common_validate.require', [ 'store_mobile' ] ],
+ 'store_mobile.mobile' => [ 'common_validate.mobile', [ 'store_mobile' ] ],
+ 'address.require' => [ 'common_validate.require', [ 'address' ] ],
+ 'trade_time.require' => [ 'common_validate.require', [ 'trade_time' ] ],
+ ];
+
+ protected $scene = [
+ "add" => [ 'store_name', 'store_mobile', 'address', 'trade_time' ],
+ "edit" => [ 'store_name', 'store_mobile', 'address', 'trade_time' ]
+ ];
+
+}
diff --git a/niucloud/addon/shop/app/validate/goods/Attr.php b/niucloud/addon/shop/app/validate/goods/Attr.php
new file mode 100644
index 000000000..b19bc041c
--- /dev/null
+++ b/niucloud/addon/shop/app/validate/goods/Attr.php
@@ -0,0 +1,39 @@
+ 'require',
+ 'attr_value_format' => 'require',
+ ];
+
+ protected $message = [
+ 'attr_name.require' => [ 'common_validate.require', [ 'attr_name' ] ],
+ 'attr_value_format.require' => [ 'common_validate.require', [ 'attr_value_format' ] ],
+ ];
+
+ protected $scene = [
+ "add" => [ 'attr_name', 'sort' ],
+ "edit" => [ 'attr_name', 'sort' ]
+ ];
+
+}
diff --git a/niucloud/addon/shop/app/validate/goods/Brand.php b/niucloud/addon/shop/app/validate/goods/Brand.php
new file mode 100644
index 000000000..408cfde27
--- /dev/null
+++ b/niucloud/addon/shop/app/validate/goods/Brand.php
@@ -0,0 +1,37 @@
+ 'require',
+ ];
+
+ protected $message = [
+ 'brand_name.require' => [ 'common_validate.require', [ 'brand_name' ] ],
+ ];
+
+ protected $scene = [
+ "add" => [ 'brand_name', 'logo', 'desc', 'sort' ],
+ "edit" => [ 'brand_name', 'logo', 'desc', 'sort' ]
+ ];
+
+}
diff --git a/niucloud/addon/shop/app/validate/goods/Category.php b/niucloud/addon/shop/app/validate/goods/Category.php
new file mode 100644
index 000000000..c601049a5
--- /dev/null
+++ b/niucloud/addon/shop/app/validate/goods/Category.php
@@ -0,0 +1,39 @@
+ 'require',
+ 'pid' => 'require',
+ ];
+
+ protected $message = [
+ 'category_name.require' => [ 'common_validate.require', [ 'category_name' ] ],
+ 'pid.require' => [ 'common_validate.require', [ 'pid' ] ],
+ ];
+
+ protected $scene = [
+ "add" => [ 'category_name', 'pid' ],
+ "edit" => [ 'category_name', 'pid' ]
+ ];
+
+}
diff --git a/niucloud/addon/shop/app/validate/goods/Evaluate.php b/niucloud/addon/shop/app/validate/goods/Evaluate.php
new file mode 100644
index 000000000..6713f7041
--- /dev/null
+++ b/niucloud/addon/shop/app/validate/goods/Evaluate.php
@@ -0,0 +1,66 @@
+ 'require',
+ 'order_goods_id' => 'require',
+ 'goods_id' => 'require',
+ 'member_id' => 'require',
+ 'content' => 'require',
+ 'images' => 'require',
+ 'is_anonymous' => 'require',
+ 'scores' => 'require',
+ 'is_audit' => 'require',
+ 'explain_first' => 'require',
+ 'again_content' => 'require',
+ 'again_images' => 'require',
+ 'again_explain' => 'require',
+ 'again_time' => 'require',
+ 'again_is_audit' => 'require',
+ 'is_show' => 'require',
+ ];
+
+ protected $message = [
+ 'order_id.require' => [ 'common_validate.require', [ 'order_id' ] ],
+ 'order_goods_id.require' => [ 'common_validate.require', [ 'order_goods_id' ] ],
+ 'goods_id.require' => [ 'common_validate.require', [ 'goods_id' ] ],
+ 'member_id.require' => [ 'common_validate.require', [ 'member_id' ] ],
+ 'content.require' => [ 'common_validate.require', [ 'content' ] ],
+ 'images.require' => [ 'common_validate.require', [ 'images' ] ],
+ 'is_anonymous.require' => [ 'common_validate.require', [ 'is_anonymous' ] ],
+ 'scores.require' => [ 'common_validate.require', [ 'scores' ] ],
+ 'is_audit.require' => [ 'common_validate.require', [ 'is_audit' ] ],
+ 'explain_first.require' => [ 'common_validate.require', [ 'explain_first' ] ],
+ 'again_content.require' => [ 'common_validate.require', [ 'again_content' ] ],
+ 'again_images.require' => [ 'common_validate.require', [ 'again_images' ] ],
+ 'again_explain.require' => [ 'common_validate.require', [ 'again_explain' ] ],
+ 'again_time.require' => [ 'common_validate.require', [ 'again_time' ] ],
+ 'again_is_audit.require' => [ 'common_validate.require', [ 'again_is_audit' ] ],
+ 'is_show.require' => [ 'common_validate.require', [ 'is_show' ] ],
+ ];
+
+ protected $scene = [
+ "add" => [ 'goods_id', 'content', 'is_anonymous', 'scores', 'is_show' ],
+ ];
+
+}
diff --git a/niucloud/addon/shop/app/validate/goods/Goods.php b/niucloud/addon/shop/app/validate/goods/Goods.php
new file mode 100644
index 000000000..be75cc5c9
--- /dev/null
+++ b/niucloud/addon/shop/app/validate/goods/Goods.php
@@ -0,0 +1,49 @@
+ 'require',
+ 'goods_type' => 'require',
+ 'goods_image' => 'require',
+ 'goods_category' => 'require',
+ 'stock' => 'require',
+ 'status' => 'number|between:0,1',
+ 'goods_desc' => 'require',
+ ];
+
+ protected $message = [
+ 'goods_name.require' => [ 'common_validate.require', [ 'goods_name' ] ],
+ 'goods_type.require' => [ 'common_validate.require', [ 'goods_type' ] ],
+ 'goods_image.require' => [ 'common_validate.require', [ 'goods_image' ] ],
+ 'goods_category.require' => [ 'common_validate.require', [ 'goods_category' ] ],
+ 'stock.require' => [ 'common_validate.require', [ 'stock' ] ],
+ 'status.require' => [ 'common_validate.require', [ 'status' ] ],
+ 'goods_desc.require' => [ 'common_validate.require', [ 'goods_desc' ] ],
+ ];
+
+ protected $scene = [
+ "add" => [ 'goods_name', 'goods_type', 'goods_cover', 'goods_image', 'goods_desc', 'brand_id', 'goods_category', 'label_ids', 'service_ids', 'unit', 'stock', 'sale_num', 'virtual_sale_num', 'status', 'sort', 'delivery_type', 'is_free_shipping', 'fee_type', 'delivery_money', 'delivery_template_id' ],
+ "edit" => [ 'goods_name', 'goods_type', 'goods_cover', 'goods_image', 'goods_desc', 'brand_id', 'goods_category', 'label_ids', 'service_ids', 'unit', 'stock', 'sale_num', 'virtual_sale_num', 'status', 'sort', 'delivery_type', 'is_free_shipping', 'fee_type', 'delivery_money', 'delivery_template_id' ],
+ ];
+
+}
diff --git a/niucloud/addon/shop/app/validate/goods/Label.php b/niucloud/addon/shop/app/validate/goods/Label.php
new file mode 100644
index 000000000..1fd68cc9d
--- /dev/null
+++ b/niucloud/addon/shop/app/validate/goods/Label.php
@@ -0,0 +1,37 @@
+ 'require',
+ ];
+
+ protected $message = [
+ 'label_name.require' => [ 'common_validate.require', [ 'label_name' ] ],
+ ];
+
+ protected $scene = [
+ "add" => [ 'label_name', 'memo', 'sort' ],
+ "edit" => [ 'label_name', 'memo', 'sort' ]
+ ];
+
+}
diff --git a/niucloud/addon/shop/app/validate/goods/LabelGroup.php b/niucloud/addon/shop/app/validate/goods/LabelGroup.php
new file mode 100644
index 000000000..9bd2766b5
--- /dev/null
+++ b/niucloud/addon/shop/app/validate/goods/LabelGroup.php
@@ -0,0 +1,37 @@
+ 'require',
+ ];
+
+ protected $message = [
+ 'group_name.require' => [ 'common_validate.require', [ 'group_name' ] ],
+ ];
+
+ protected $scene = [
+ "add" => [ 'group_name', 'sort' ],
+ "edit" => [ 'group_name', 'sort' ]
+ ];
+
+}
diff --git a/niucloud/addon/shop/app/validate/goods/Rank.php b/niucloud/addon/shop/app/validate/goods/Rank.php
new file mode 100644
index 000000000..9edecc086
--- /dev/null
+++ b/niucloud/addon/shop/app/validate/goods/Rank.php
@@ -0,0 +1,82 @@
+ 'require',
+ 'banner' => 'require',
+ 'rank_type' => 'require|in:day,week,month,quarter',
+ 'goods_source' => 'require|in:goods,category,brand,label,all',
+ 'rule_type' => 'require|in:sale,collect,evaluate,access',
+ 'goods_json' => 'checkGoodsSource',
+ 'category_ids' => 'checkGoodsSource',
+ 'brand_ids' => 'checkGoodsSource',
+ 'label_ids' => 'checkGoodsSource',
+ ];
+
+ protected $message = [
+ 'name.require' => [ 'common_validate.require', [ 'name' ] ],
+ 'banner.require' => [ 'common_validate.require', [ 'banner' ] ],
+ 'rank_type.require' => [ 'common_validate.require', [ 'rank_type' ] ],
+ 'goods_source.require' => [ 'common_validate.require', [ 'goods_source' ] ],
+ 'rule_type.require' => [ 'common_validate.require', [ 'rule_type' ] ],
+ ];
+
+ protected $scene = [
+ "add" => [ 'name', 'rank_type', 'goods_source', 'rule_type', 'goods_json', 'category_ids', 'brand_ids', 'label_ids', 'sort','status'],
+ "edit" => [ 'name', 'rank_type', 'goods_source', 'rule_type', 'goods_json', 'category_ids', 'brand_ids', 'label_ids', 'sort','status']
+ ];
+
+ // 自定义验证规则
+ protected function checkGoodsSource($value, $rule, $data=[])
+ {
+ if ($data['goods_source'] == RankDict::GOODS) {
+ if (empty($data['goods_json'])) {
+ return 'goods_json不能为空';
+ }
+ return true;
+ }
+ if ($data['goods_source'] == RankDict::CATEGORY) {
+ if (empty($data['category_ids'])) {
+ return 'category_ids不能为空';
+ }
+ return true;
+ }
+ if ($data['goods_source'] == RankDict::BRAND) {
+ if (empty($data['brand_ids'])) {
+ return 'brand_ids不能为空';
+ }
+ return true;
+ }
+ if ($data['goods_source'] == RankDict::LABEL) {
+ if (empty($data['label_ids'])) {
+ return 'label_ids不能为空';
+ }
+ return true;
+ }
+ if ($data['goods_source'] == RankDict::ALL) {
+ return true;
+ }
+ }
+
+}
diff --git a/niucloud/addon/shop/app/validate/goods/Service.php b/niucloud/addon/shop/app/validate/goods/Service.php
new file mode 100644
index 000000000..1b43a46e7
--- /dev/null
+++ b/niucloud/addon/shop/app/validate/goods/Service.php
@@ -0,0 +1,37 @@
+ 'require',
+ ];
+
+ protected $message = [
+ 'service_name.require' => [ 'common_validate.require', [ 'service_name' ] ],
+ ];
+
+ protected $scene = [
+ "add" => [ 'service_name', 'desc' ],
+ "edit" => [ 'service_name', 'desc' ]
+ ];
+
+}
diff --git a/niucloud/addon/shop/app/validate/marketing/Coupon.php b/niucloud/addon/shop/app/validate/marketing/Coupon.php
new file mode 100644
index 000000000..dab024631
--- /dev/null
+++ b/niucloud/addon/shop/app/validate/marketing/Coupon.php
@@ -0,0 +1,46 @@
+ 'require',
+ 'price' => 'require',
+ 'receive_type' => 'require',
+ 'type' => 'require',
+ 'start_time' => 'require',
+ 'end_time' => 'require',
+ ];
+
+ protected $message = [
+ 'title.require' => [ 'common_validate.require', [ 'title' ] ],
+ 'price.require' => [ 'common_validate.require', [ 'price' ] ],
+ 'receive_type.require' => [ 'common_validate.require', [ 'receive_type' ] ],
+ 'type.require' => [ 'common_validate.require', [ 'type' ] ],
+ 'start_time.require' => [ 'common_validate.require', [ 'start_time' ] ],
+ 'end_time.require' => [ 'common_validate.require', [ 'end_time' ] ],
+ ];
+
+ protected $scene = [
+ "add" => [ 'title', 'price', 'receive_type', 'type', 'start_time', 'end_time' ],
+ ];
+
+}
diff --git a/niucloud/addon/shop/app/validate/shop_address/ShopAddress.php b/niucloud/addon/shop/app/validate/shop_address/ShopAddress.php
new file mode 100644
index 000000000..1403298ff
--- /dev/null
+++ b/niucloud/addon/shop/app/validate/shop_address/ShopAddress.php
@@ -0,0 +1,61 @@
+ 'require',
+ 'mobile' => 'require',
+ 'province_id' => 'require',
+ 'city_id' => 'require',
+ 'district_id' => 'require',
+ 'address' => 'require',
+ 'full_address' => 'require',
+ 'lat' => 'require',
+ 'lng' => 'require',
+ 'is_delivery_address' => 'require',
+ 'is_refund_address' => 'require',
+ 'is_default_delivery' => 'require',
+ 'is_default_refund' => 'require',
+ ];
+
+ protected $message = [
+ 'contact_name.require' => [ 'common_validate.require', [ 'contact_name' ] ],
+ 'mobile.require' => [ 'common_validate.require', [ 'mobile' ] ],
+ 'province_id.require' => [ 'common_validate.require', [ 'province_id' ] ],
+ 'city_id.require' => [ 'common_validate.require', [ 'city_id' ] ],
+ 'district_id.require' => [ 'common_validate.require', [ 'district_id' ] ],
+ 'address.require' => [ 'common_validate.require', [ 'address' ] ],
+ 'full_address.require' => [ 'common_validate.require', [ 'full_address' ] ],
+ 'lat.require' => [ 'common_validate.require', [ 'lat' ] ],
+ 'lng.require' => [ 'common_validate.require', [ 'lng' ] ],
+ 'is_delivery_address.require' => [ 'common_validate.require', [ 'is_delivery_address' ] ],
+ 'is_refund_address.require' => [ 'common_validate.require', [ 'is_refund_address' ] ],
+ 'is_default_delivery.require' => [ 'common_validate.require', [ 'is_default_delivery' ] ],
+ 'is_default_refund.require' => [ 'common_validate.require', [ 'is_default_refund' ] ],
+ ];
+
+ protected $scene = [
+ "add" => [ 'contact_name', 'mobile', 'province_id', 'city_id', 'district_id', 'address', 'full_address', 'lat', 'lng', 'is_delivery_address', 'is_refund_address', 'is_default_delivery', 'is_default_refund' ],
+ "edit" => [ 'contact_name', 'mobile', 'province_id', 'city_id', 'district_id', 'address', 'full_address', 'lat', 'lng', 'is_delivery_address', 'is_refund_address', 'is_default_delivery', 'is_default_refund' ]
+ ];
+
+}
diff --git a/niucloud/addon/shop/config/third_delivery.php b/niucloud/addon/shop/config/third_delivery.php
new file mode 100644
index 000000000..db86d8eb9
--- /dev/null
+++ b/niucloud/addon/shop/config/third_delivery.php
@@ -0,0 +1,28 @@
+ 'dada',
+ 'drivers' => [
+ //达达
+ 'dada' => [
+ 'driver' => 'addon\shop\app\service\core\delivery\third_delivery\Dada', //反射类的名字
+ 'app_key' => '',
+ 'secret_key' => '',
+ 'sign' => '',
+ ],
+ ]
+];
+
+return (new DictLoader("Config"))->load(['data' => $system, 'name' => 'third_delivery']);
diff --git a/niucloud/addon/shop/info.json b/niucloud/addon/shop/info.json
new file mode 100644
index 000000000..9be8690ad
--- /dev/null
+++ b/niucloud/addon/shop/info.json
@@ -0,0 +1,10 @@
+{
+ "title": "商城系统",
+ "desc": "实物虚拟商品,订单,物流同城配送,门店自提",
+ "key": "shop",
+ "version": "6.4.9",
+ "author": "niucloud",
+ "type": "app",
+ "support_app": "",
+ "support_version": "1.5.7"
+}
diff --git a/niucloud/addon/shop/install.php b/niucloud/addon/shop/install.php
new file mode 100644
index 000000000..92ff839a9
--- /dev/null
+++ b/niucloud/addon/shop/install.php
@@ -0,0 +1,61 @@
+ 'NIUSHOP',
+ // logo
+ 'logo' => 'niushop_logo.jpg',
+ // 官网地址
+ 'website_url' => 'https://www.niushop.com',
+ // 论坛地址
+ 'bbs_url' => 'https://www.niushop.com/web/community/index.html',
+ // 编译帮助手册
+ 'build_manual' => 'https://www.kancloud.cn/niushop/niushop_v6/3224842',
+ // 安装协议
+ 'agreement' => '版权所有 (c)2016,Niushop开源商城团队保留所有权利。
+
+ 感谢您选择Niushop开源商城(以下简称NiuShop)NiuShop基于 PHP + MySQL的技术开发,全部源码开放。
+ 为了使你正确并合法的使用本软件,请你在使用前务必阅读清楚下面的协议条款:
+
+
+ 一、本授权协议适用且仅适用于Niushop开源商城系统(以下简称Niushop)任何版本,Niushop开源商城官方对本授权协议的最终解释权。
+
+
+ 二、协议许可的权利
+
+ - 非授权用户允许商用,严禁去除Niushop相关的版权信息。
+ - 请尊重Niushop开发人员劳动成果,严禁使用本系统转卖、销售或二次开发后转卖、销售等商业行为。
+ - 任何企业和个人不允许对程序代码以任何形式任何目的再发布。
+ - 您可以在协议规定的约束和限制范围内修改Niushop开源商城源代码或界面风格以适应您的网站要求。
+ - 您拥有使用本软件构建的网站全部内容所有权,并独立承担与这些内容的相关法律义务。
+ -
+ 获得商业授权之后,您可以将本软件应用于商业用途,同时依据所购买的授权类型中确定的技术支持内容,自购买时刻起,在技术支持期限内拥有通过指定的方式获得指定范围内的技术支持服务。商业授权用户享有反映和提出意见的权力,相关意见将被作为首要考虑,但没有一定被采纳的承诺或保证。
+
+
+
+
+ 三、协议规定的约束和限制
+
+ - 未获商业授权之前,允许您对Niushop应用于商业用途,但严禁去除Niushop任何相关的版权信息。
+ - 未经官方许可,不得对本软件或与之关联的商业授权进行出租、出售、抵押或发放子许可证。
+ - 未经官方许可,禁止在Niushop开源商城的整体或任何部分基础上以发展任何派生版本、修改版本或第三方版本用于重新分发。
+ - 如果您未能遵守本协议的条款,您的授权将被终止,所被许可的权利将被收回,并承担相应法律责任。
+
+
+
+ 四、有限担保和免责声明
+
+ - 本软件及所附带的文件是作为不提供任何明确的或隐含的赔偿或担保的形式提供的。
+ - 用户出于自愿而使用本软件,您必须了解使用本软件的风险,在尚未购买产品技术服务之前,我们不承诺对免费用户提供任何形式的技术支持、使用担保,也不承担任何因使用本软件而产生问题的相关责任。
+ - 电子文本形式的授权协议如同双方书面签署的协议一样,具有完全的和等同的法律效力。您一旦开始确认本协议并安装
+ Niushop,即被视为完全理解并接受本协议的各项条款,在享有上述条款授予的权力的同时,受到相关的约束和限制。协议许可范围以外的行为,将直接违反本授权协议并构成侵权,我们有权随时终止授权,责令停止损害,并保留追究相关责任的权力。
+
+ - 如果本软件带有其它软件的整合API示范例子包,这些文件版权不属于本软件官方,并且这些文件是没经过授权发布的,请参考相关软件的使用许可合法的使用。
+
+ ',
+ // 站点名称
+ 'admin_site_name' => 'NIUSHOP V6',
+ // admin 端登录页默认图
+ 'admin_login_bg' => 'install/img/niushop_login_index_left.jpg',
+ // admin 端默认logo
+ 'admin_logo' => 'install/img/niushop_logo.jpg'
+];
diff --git a/niucloud/addon/shop/package/uni-app-pages.php b/niucloud/addon/shop/package/uni-app-pages.php
new file mode 100644
index 000000000..4885108e1
--- /dev/null
+++ b/niucloud/addon/shop/package/uni-app-pages.php
@@ -0,0 +1,287 @@
+ <<) {
+ return request.get(`shop/cart`, params)
+}
+
+/**
+ * 获取购物车商品列表
+ */
+export function getCartGoodsList(params: Record) {
+ return request.get(`shop/cart/goods`, params)
+}
+
+/**
+ * 获取购物车数量
+ */
+export function getCartSum(params: Record) {
+ return request.get(`shop/cart/sum`, params)
+}
+
+/**
+ * 购物车计算
+ */
+export function getCartCalculate(params: Record) {
+ return request.get(`shop/cart/calculate`, params)
+}
diff --git a/niucloud/addon/shop/uni-app/api/config.ts b/niucloud/addon/shop/uni-app/api/config.ts
new file mode 100644
index 000000000..71a3541ac
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/api/config.ts
@@ -0,0 +1,8 @@
+import request from '@/utils/request'
+
+/**
+ * 获取发票配置
+ */
+export function getInvoiceConfig() {
+ return request.get(`shop/config/invoice`)
+}
diff --git a/niucloud/addon/shop/uni-app/api/coupon.ts b/niucloud/addon/shop/uni-app/api/coupon.ts
new file mode 100644
index 000000000..27b1b4c99
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/api/coupon.ts
@@ -0,0 +1,65 @@
+import request from '@/utils/request'
+
+/**
+ * 优惠券列表
+ */
+export function getShopCouponList(params: Record) {
+ return request.get(`shop/coupon`, params)
+}
+
+/**
+ * 优惠券详情
+ */
+export function getShopCouponInfo(id: number) {
+ return request.get(`shop/coupon/${ id }`)
+}
+
+/**
+ * 优惠券二维码
+ */
+export function getShopCouponQrocde(id: number) {
+ return request.get(`shop/coupon/qrcode/${ id }`)
+}
+
+/**
+ * 领取优惠券
+ */
+export function getCoupon(params: Record) {
+ return request.post(`shop/coupon`, params, { showSuccessMessage: true })
+}
+
+/**
+ * 获取我的优惠券
+ */
+export function getMyCouponList(params: Record) {
+ return request.get(`shop/member/coupon`, params)
+}
+
+/**
+ * 获取优惠券列表供组件调用
+ */
+export function getShopCouponComponents(params: Record) {
+ return request.get(`shop/coupon/components`, params)
+}
+
+/**
+ * 获取我的优惠券数量
+ * status 1:待使用,2:已使用,3:已过期,4:已失效
+ */
+export function getMyCouponCount(params: Record) {
+ return request.get(`shop/member/coupon/count`, params)
+}
+
+/**
+ * 获取我的优惠券类型
+ */
+export function getMyCouponType() {
+ return request.get(`shop/coupon_type`)
+}
+
+/**
+ * 获取我的优惠数量
+ */
+export function getMyCouponStatusCount() {
+ return request.get(`shop/member/coupon/status_count`)
+}
diff --git a/niucloud/addon/shop/uni-app/api/discount.ts b/niucloud/addon/shop/uni-app/api/discount.ts
new file mode 100644
index 000000000..db42d5535
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/api/discount.ts
@@ -0,0 +1,25 @@
+import request from '@/utils/request'
+
+/**
+ * 获取限时折扣轮播
+ * @returns
+ */
+export function getActiveDiscountConfig() {
+ return request.get(`shop/discount/config`);
+}
+
+/**
+ * 获取限时折扣列表
+ * @returns
+ */
+export function getActiveDiscountList(params: Record) {
+ return request.get(`shop/discount`, params)
+}
+
+/**
+ * 获取限时折扣商品列表
+ * @returns
+ */
+export function getActiveDiscountGoodsList(params: Record) {
+ return request.get(`shop/discount/goods`, params)
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/uni-app/api/evaluate.ts b/niucloud/addon/shop/uni-app/api/evaluate.ts
new file mode 100644
index 000000000..1d022b2c9
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/api/evaluate.ts
@@ -0,0 +1,29 @@
+import request from '@/utils/request'
+
+/**
+ * 获取商品评价
+ */
+export function getEvaluateList(params: Record) {
+ return request.get(`shop/goods/evaluate`, params)
+}
+
+/**
+ * 获取评价详情
+ */
+export function getEvaluateInfo(id: any) {
+ return request.get(`shop/goods/evaluate/${ id }`)
+}
+
+/**
+ * 提交评论
+ */
+export function setOrderEvaluate(params: Record) {
+ return request.post('shop/goods/evaluate', params, { showSuccessMessage: true })
+}
+
+/**
+ * 获取订单评价
+ */
+export function getOrderEvaluate(id: any) {
+ return request.get(`shop/order/evaluate/${ id }`)
+}
diff --git a/niucloud/addon/shop/uni-app/api/goods.ts b/niucloud/addon/shop/uni-app/api/goods.ts
new file mode 100644
index 000000000..bd04ff084
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/api/goods.ts
@@ -0,0 +1,114 @@
+import request from '@/utils/request'
+
+/**
+ * 获取商品分类模板配置
+ */
+export function getGoodsCategoryConfig() {
+ return request.get(`shop/goods/category/config`)
+}
+
+/**
+ * 获取商品分类树结构
+ */
+export function getGoodsCategoryTree() {
+ return request.get(`shop/goods/category/tree`)
+}
+
+/**
+ * 获取商品分类列表
+ */
+export function getGoodsCategoryList(params: Record) {
+ return request.get(`shop/goods/category/list`, params)
+}
+
+/**
+ * 获取商品列表
+ */
+export function getGoodsPages(params: Record) {
+ return request.get(`shop/goods/pages`, params)
+}
+
+/**
+ * 获取商品详情
+ */
+export function getGoodsDetail(params: Record) {
+ return request.get(`shop/goods/detail`, params)
+}
+
+/**
+ * 获取商品规格
+ */
+export function getGoodsSku(sku_id: any) {
+ return request.get(`shop/goods/sku/${ sku_id }`)
+}
+
+/**
+ * 收藏列表
+ */
+export function getCollectList(params: Record) {
+ return request.get(`shop/goods/collect`, params)
+}
+
+/**
+ * 取消收藏
+ */
+export function cancelCollect(params: Record) {
+ return request.put(`shop/goods/collect`, params, { showSuccessMessage: true })
+}
+
+/**
+ * 收藏
+ */
+export function collect(goods_id: any) {
+ return request.post(`shop/goods/collect/${ goods_id }`)
+}
+
+
+/**
+ * 获取评价
+ */
+export function getEvaluateList(goods_id: any) {
+ return request.get(`shop/goods/evaluate/list`, { goods_id })
+}
+
+/**
+ * 获取商品列表供组件调用
+ */
+export function getGoodsComponents(params: Record) {
+ return request.get(`shop/goods/components`, params)
+}
+
+/**
+ * 获取商品满减信息
+ */
+export function getManjian(params: Record) {
+ return request.get(`shop/manjian/info`, params)
+}
+
+/**
+ * 商品足迹添加
+ */
+export function browse(params: Record) {
+ return request.post(`shop/goods/browse`, params, { showSuccessMessage: false })
+}
+
+/**
+ * 商品足迹列表
+ */
+export function getBrowse(params: Record) {
+ return request.get(`shop/goods/browse`, params)
+}
+
+/**
+ * 商品足迹删除
+ */
+export function delBrowse(params: Record) {
+ return request.delete(`shop/goods/browse`, params)
+}
+
+/**
+ * 获取商品搜索配置
+ */
+export function getGoodsConfigSearch() {
+ return request.get(`shop/goods/config/search`)
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/uni-app/api/impulse_buy.ts b/niucloud/addon/shop/uni-app/api/impulse_buy.ts
new file mode 100644
index 000000000..2169c1a24
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/api/impulse_buy.ts
@@ -0,0 +1,22 @@
+import request from '@/utils/request'
+
+/**
+ * 获取顺手买配置
+ */
+export function getShopImpulseBuyConfig() {
+ return request.get(`shop_impulse_buy/config`)
+}
+
+/**
+ * 获取顺手买商品列表
+ */
+export function getShopImpulseBuyList(params: Record) {
+ return request.get(`shop_impulse_buy/list`, params)
+}
+
+/**
+ * 获取顺手买商品详情
+ */
+export function getShopImpulseBuyDetail(params: Record) {
+ return request.get(`shop_impulse_buy/detail/${params.impulse_buy_goods_id}`, params)
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/uni-app/api/invoice.ts b/niucloud/addon/shop/uni-app/api/invoice.ts
new file mode 100644
index 000000000..5100a79ca
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/api/invoice.ts
@@ -0,0 +1,31 @@
+import request from '@/utils/request'
+
+// 发票列表
+export function getInvoiceList(params: Record) {
+ return request.get(`shop/order/invoice/list`,params)
+}
+
+// 发票详情
+export function getInvoiceInfo(id: number) {
+ return request.get(`shop/order/invoice/${id}`)
+}
+
+// 计算发票金额
+export function calculateInvoice(params: Record) {
+ return request.post(`shop/order/invoice/calculate`,params)
+}
+
+// 添加发票
+export function addInvoice(params: Record) {
+ return request.post(`shop/order/invoice/apply`, params)
+}
+
+// 编辑发票
+export function editInvoice(id:number, params: Record) {
+ return request.post(`shop/order/invoice/edit/${id}`, params)
+}
+
+// 取消申请
+export function cancelInvoice(id: number) {
+ return request.delete(`shop/order/invoice/cancel/${id}`)
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/uni-app/api/newcomer.ts b/niucloud/addon/shop/uni-app/api/newcomer.ts
new file mode 100644
index 000000000..e8ba10f44
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/api/newcomer.ts
@@ -0,0 +1,14 @@
+import request from '@/utils/request'
+
+// 新人专区列表
+export function getNewcomerGoodsList(params: Record) {
+ return request.get(`shop/newcomer/goods`, params)
+}
+export function getNewcomersConfig() {
+ return request.get(`shop/newcomer/config`)
+}
+
+// 首页新人专享列表
+export function getNewcomersComponentsList(params: Record) {
+ return request.get(`shop/newcomer/goods/components`, params)
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/uni-app/api/order.ts b/niucloud/addon/shop/uni-app/api/order.ts
new file mode 100644
index 000000000..03183ac3c
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/api/order.ts
@@ -0,0 +1,93 @@
+import request from '@/utils/request'
+
+/***************************************************** 订单列表 ****************************************************/
+/**
+ * 获取订单设置
+ */
+export function getShopOrderConfig() {
+ return request.get(`shop/order/config`)
+}
+
+/**
+ * 获取订单状态列表
+ */
+export function getShopOrderStatus() {
+ return request.get(`shop/order/status`)
+}
+
+/**
+ * 获取订单列表
+ */
+export function getShopOrder(params: Record) {
+ return request.get(`shop/order`, params)
+}
+
+/**
+ * 获取订单角标数据
+ */
+export function getShopOrderNum() {
+ return request.get(`shop/order/num`)
+}
+
+/**
+ * 获取订单详情
+ */
+export function getShopOrderDetail(order_id: any) {
+ return request.get(`shop/order/${ order_id }`)
+}
+
+/**
+ * 关闭订单
+ */
+export function orderClose(order_id: number) {
+ return request.put(`shop/order/close/${ order_id }`)
+}
+
+/**
+ * 订单完成
+ */
+export function orderFinish(order_id: number) {
+ return request.put(`shop/order/finish/${ order_id }`)
+}
+
+/**
+ * 订单创建计算
+ */
+export function orderCreateCalculate(params: Record) {
+ return request.get('shop/order_create/calculate', params)
+}
+
+/**
+ * 订单创建
+ */
+export function orderCreate(params: Record) {
+ return request.post('shop/order_create/create', params)
+}
+
+/**
+ * 查询订单可用优惠券
+ */
+export function orderCoupon(params: Record) {
+ return request.get('shop/order_create/coupon', params)
+}
+
+/**
+ * 查询自提点
+ */
+export function getStoreList(params: Record) {
+ return request.get('shop/order_create/store', params)
+}
+
+/**
+ * 查询物流信息
+ */
+export function getMaterialflowList(params: Record) {
+ return request.get('shop/order/logistics', params)
+}
+
+/**
+ * 查询同城配送预约配置
+ */
+export function getLocal() {
+ return request.get('shop/order_create/local')
+}
diff --git a/niucloud/addon/shop/uni-app/api/point.ts b/niucloud/addon/shop/uni-app/api/point.ts
new file mode 100644
index 000000000..c94ebcbf6
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/api/point.ts
@@ -0,0 +1,46 @@
+import request from '@/utils/request'
+
+/**
+ * 获取个人积分信息
+ * @returns
+ */
+export function getExchangePoint() {
+ return request.get(`shop/exchange/point`);
+}
+
+/**
+ * 获取积分商城推荐列表
+ * @returns
+ */
+export function getExchangeComponentsList(params: Record) {
+ return request.get(`shop/exchange/components`, params)
+}
+
+/**
+ * 获取积分商城列表
+ * @returns
+ */
+export function getExchangeGoodsList(params: Record) {
+ return request.get(`shop/exchange`, params)
+}
+
+/**
+ * 获取积分商品详情
+ */
+export function getExchangeGoodsDetail(id: any) {
+ return request.get(`shop/exchange/goods/${ id }`)
+}
+
+/**
+ * 订单创建计算
+ */
+export function orderCreateCalculate(params: Record) {
+ return request.get('shop/exchange_order/calculate', params)
+}
+
+/**
+ * 订单创建
+ */
+export function orderCreate(params: Record) {
+ return request.post('shop/exchange_order/create', params)
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/uni-app/api/rank.ts b/niucloud/addon/shop/uni-app/api/rank.ts
new file mode 100644
index 000000000..faaac6bcd
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/api/rank.ts
@@ -0,0 +1,21 @@
+import request from '@/utils/request'
+
+// 榜单分类列表
+export function getRankList() {
+ return request.get(`shop/rank`)
+}
+
+// 榜单商品列表
+export function getRankGoodsList(params: Record) {
+ return request.get(`shop/rank/goods`, params)
+}
+
+// 获取排行榜配置
+export function getRankConfig() {
+ return request.get(`shop/rank/getRankConfig`)
+}
+
+// 榜单组件商品列表
+export function getRankComponentsGoodsList(params: Record) {
+ return request.get(`shop/rank/components`, params)
+}
diff --git a/niucloud/addon/shop/uni-app/api/refund.ts b/niucloud/addon/shop/uni-app/api/refund.ts
new file mode 100644
index 000000000..e31b3c68c
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/api/refund.ts
@@ -0,0 +1,71 @@
+import request from '@/utils/request'
+
+/**
+ * 申请退款
+ */
+export function applyRefund(params: Record) {
+ return request.post(`shop/refund/apply`, params, { showSuccessMessage: true })
+}
+
+/**
+ * 修改退款申请
+ */
+export function editRefund(params: Record) {
+ return request.put(`shop/refund/${ params.order_refund_no }`, params, { showSuccessMessage: true })
+}
+
+/**
+ * 申请退款退货
+ */
+export function refundDelivery(params: Record) {
+ return request.post(`shop/refund/delivery/${ params.order_refund_no }`, params, { showSuccessMessage: true })
+}
+
+/**
+ * 修改退款申请
+ */
+export function editRefundDelivery(params: Record) {
+ return request.put(`shop/refund/delivery/${ params.order_refund_no }`, params, { showSuccessMessage: true })
+}
+
+/**
+ * 获取退款原因
+ */
+export function getRefundReason() {
+ return request.get('shop/refund/reason')
+}
+
+/**
+ * 获取退款列表
+ */
+export function getRefundList() {
+ return request.get('shop/order/refund')
+}
+
+/**
+ * 获取退款详情
+ */
+export function getRefundDetail(orderRefundNo: string) {
+ return request.get(`shop/order/refund/${ orderRefundNo }`)
+}
+
+/**
+ * 获取退款金额
+ */
+export function getRefundMoney(params: Record) {
+ return request.get(`shop/refund/refund_data`, params)
+}
+
+/**
+ * 编辑退款金额
+ */
+export function getRefundMoneyAgain(params: Record) {
+ return request.get(`shop/refund/refund_data_by_no`, params)
+}
+
+/**
+ * 取消售后
+ */
+export function closeRefund(orderRefundNo: string) {
+ return request.put(`shop/refund/close/${ orderRefundNo }`, {}, { showSuccessMessage: true })
+}
diff --git a/niucloud/addon/shop/uni-app/api/shop.ts b/niucloud/addon/shop/uni-app/api/shop.ts
new file mode 100644
index 000000000..eb0ac14bc
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/api/shop.ts
@@ -0,0 +1,8 @@
+import request from '@/utils/request'
+
+/**
+ * 获取评论设置
+ */
+export function getEvaluateConfig() {
+ return request.get(`shop/goods/evaluate/config`)
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/uni-app/components/diy/goods-coupon/index.vue b/niucloud/addon/shop/uni-app/components/diy/goods-coupon/index.vue
new file mode 100644
index 000000000..86de32ae3
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/components/diy/goods-coupon/index.vue
@@ -0,0 +1,442 @@
+
+
+
+
+
+
+
+
+
+
+ ¥
+ {{ parseFloat(item.price) }}
+
+ {{ item.min_condition_money == '0.00' ? '无门槛' : ('满' + parseFloat(item.min_condition_money) + '元可用') }}
+ {{ item.type_name }}
+
+
+
+
+
+ ¥
+ {{ parseFloat(item.price) }}
+
+
+
+
+ {{ item.type_name }}
+ {{ item.title }}
+
+ {{ item.min_condition_money == '0.00' ? '无门槛' : ('消费满' + parseFloat(item.min_condition_money) + '元可用') }}
+
+
+
+
+
+
+
+ {{ diyComponent.couponTitle }}
+ {{ diyComponent.couponSubTitle }}
+
+
+ {{ diyComponent.btnText }}
+
+
+
+
+
+
+
+
+ ¥
+ {{ parseFloat(item.price) }}
+
+ {{ item.min_condition_money == '0.00' ? '无门槛' : ('满' + parseFloat(item.min_condition_money) + '元可用') }}
+ {{ item.type_name }}
+
+
+
+ {{ diyComponent.couponTitle }}
+ {{ diyComponent.couponSubTitle }}
+ {{ diyComponent.btnText }}
+
+
+
+
+
+ {{ diyComponent.couponTitle }}
+ {{ diyComponent.couponSubTitle }}
+
+ {{ diyComponent.btnText }}
+
+
+
+
+
+ {{ item.type_name }}
+
+ ¥
+ {{ parseFloat(item.price) }}
+
+
+ {{ item.min_condition_money == '0.00' ? '无门槛' : ('满' + parseFloat(item.min_condition_money) + '元可用') }}
+
+
+
+
+
+ ¥
+ {{ parseFloat(couponList[0].price) }}
+
+
+ {{ couponList[0].min_condition_money == '0.00' ? '无门槛' : ('满' + parseFloat(couponList[0].min_condition_money) + '元可用') }}
+
+ {{ couponList[0].type_name }}
+ 店铺优惠券
+
+
+
+
+
+
+
+ {{ diyComponent.couponTitle }}
+ {{ diyComponent.couponSubTitle }}
+
+
+
+
+ ¥
+ {{ parseFloat(item.price) }}
+
+
+ {{ item.type_name }}
+ {{ item.min_condition_money == '0.00' ? '无门槛' : ('满' + parseFloat(item.min_condition_money) + '元可用') }}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/uni-app/components/diy/goods-list/index.vue b/niucloud/addon/shop/uni-app/components/diy/goods-list/index.vue
new file mode 100644
index 000000000..fe75a114b
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/components/diy/goods-list/index.vue
@@ -0,0 +1,716 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ item.goods_brand.brand_name }}
+ {{ item.goods_name }}
+
+
+ {{ item.sub_title }}
+
+
+
+
+ {{ tagItem.label_name }}
+
+
+
+
+
+
+ ¥
+ {{ parseFloat(diyGoods.goodsPrice(item)).toFixed(2) }}
+
+
+
+
+
+
+ 已售{{ item.sale_num }}{{ item.unit || '件' }}
+
+
+
+
+
+
+ {{ diyComponent.btnStyle.text }}
+ {{ cartList['goods_' + item.goods_id].totalNum }}
+
+
+
+ {{ cartList['goods_' + item.goods_id].totalNum }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ item.goods_brand.brand_name }}
+ {{ item.goods_name }}
+
+
+ {{ item.sub_title }}
+
+
+
+
+ {{ tagItem.label_name }}
+
+
+
+
+
+
+ ¥
+ {{ parseFloat(diyGoods.goodsPrice(item)).toFixed(2).split('.')[0] }}
+ .{{ parseFloat(diyGoods.goodsPrice(item)).toFixed(2).split('.')[1] }}
+
+
+
+
+
+
+ 已售{{ item.sale_num }}{{ item.unit || '件' }}
+
+
+
+
+
+ {{ diyComponent.btnStyle.text }}
+ {{ cartList['goods_' + item.goods_id].totalNum }}
+
+
+
+ {{ cartList['goods_' + item.goods_id].totalNum }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ item.goods_brand.brand_name }}
+ {{ item.goods_name }}
+
+
+ {{ item.sub_title }}
+
+
+
+
+ {{ tagItem.label_name }}
+
+
+
+
+
+
+ ¥
+ {{ parseFloat(diyGoods.goodsPrice(item)).toFixed(2).split('.')[0] }}
+ .{{ parseFloat(diyGoods.goodsPrice(item)).toFixed(2).split('.')[1] }}
+
+
+
+
+
+
+ 已售{{ item.sale_num }}{{ item.unit || '件' }}
+
+
+
+
+
+ {{ diyComponent.btnStyle.text }}
+ {{ cartList['goods_' + item.goods_id].totalNum }}
+
+
+
+ {{ cartList['goods_' + item.goods_id].totalNum }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ item.goods_name }}
+
+ ¥
+ {{ parseFloat(diyGoods.goodsPrice(item)).toFixed(2) }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/uni-app/components/diy/many-goods-list/index.vue b/niucloud/addon/shop/uni-app/components/diy/many-goods-list/index.vue
new file mode 100644
index 000000000..15de56373
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/components/diy/many-goods-list/index.vue
@@ -0,0 +1,369 @@
+
+
+
+
+
+
+
+
+ {{ item.title }}
+
+
+
+
+
+ 全部
+
+
+
+
+ {{ item.category_name }}
+
+
+
+
+
+
+ {{ item.title }}
+ {{ item.desc }}
+
+
+ {{ item.title }}
+
+
+
+ {{ item.title }}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/uni-app/components/diy/shop-exchange-goods/index.vue b/niucloud/addon/shop/uni-app/components/diy/shop-exchange-goods/index.vue
new file mode 100644
index 000000000..02d774563
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/components/diy/shop-exchange-goods/index.vue
@@ -0,0 +1,271 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ item.goods_brand.brand_name }}
+ {{ item.names }}
+
+
+ {{ item.title }}
+
+
+
+
+
+ {{ tagItem.label_name }}
+
+
+
+ 已兑{{ item.total_exchange_num }}人
+
+
+
+ {{ item.point }}
+ 积分
+
+
+ +{{ parseFloat(item.price).toFixed(2) }}
+ 元
+
+
+ 去兑换
+
+
+
+
+
+
+ 暂无商品
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/uni-app/components/diy/shop-exchange-info/index.vue b/niucloud/addon/shop/uni-app/components/diy/shop-exchange-info/index.vue
new file mode 100644
index 000000000..4e5c89d70
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/components/diy/shop-exchange-info/index.vue
@@ -0,0 +1,119 @@
+
+
+
+
+
+
+
+ 我的积分
+ {{ memberPoint.point || 0 }}
+ 今日获得:{{ memberPoint.today_point || 0 }}
+
+
+ 积分当钱花
+ 做任务可领积分
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/uni-app/components/diy/shop-goods-detail-attr/index.vue b/niucloud/addon/shop/uni-app/components/diy/shop-goods-detail-attr/index.vue
new file mode 100644
index 000000000..da7789718
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/components/diy/shop-goods-detail-attr/index.vue
@@ -0,0 +1,122 @@
+
+
+
+ 商品属性
+
+
+
+ {{ item.attr_value_name }}
+ {{ Array.isArray(item.attr_child_value_name) ? item.attr_child_value_name.join(',') : item.attr_child_value_name }}
+
+
+
+ {{ !isAttrFormatShow ? '展开' : '收起' }}
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/uni-app/components/diy/shop-goods-detail-basic-info/index.vue b/niucloud/addon/shop/uni-app/components/diy/shop-goods-detail-basic-info/index.vue
new file mode 100644
index 000000000..a32071264
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/components/diy/shop-goods-detail-basic-info/index.vue
@@ -0,0 +1,692 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ item.name }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 视频
+
+ 图片
+ {{swiperCurrentIndex}}/{{diyComponent.goods.goods_image.length}}
+
+
+
+
+
+ 新人价
+ 折扣价
+ 会员价
+
+ ¥
+ {{ parseFloat(goodsPrice).toFixed(2).split('.')[0] }}
+ .{{ parseFloat(goodsPrice).toFixed(2).split('.')[1] }}
+
+
+
+ 售价
+
+
+ 售价
+
+ ¥{{ diyComponent.price }}
+
+
+
+
+
+ 距结束
+
+
+
+ {{ timeData.days }}
+ 天
+
+
+ {{ timeData.hours >= 10 ? timeData.hours : '0' + timeData.hours }}
+ 00
+ 时
+
+
+ {{ timeData.minutes >= 10 ? timeData.minutes : '0' + timeData.minutes }}
+ 分
+
+
+ {{ timeData.seconds < 10 ? '0' + timeData.seconds : timeData.seconds }}
+ 秒
+
+
+
+
+
+
+
+
+
+
+ ¥
+ {{ parseFloat(goodsPrice).toFixed(2).split('.')[0] }}
+ .{{ parseFloat(goodsPrice).toFixed(2).split('.')[1] }}
+
+
+
+ {{ diyComponent?.goods?.goods_brand?.brand_name }}
+ {{ diyComponent.goods.goods_name }}
+
+
+ {{diyComponent.goods.sub_title}}
+
+
+
+
+
+ {{ item.label_name }}
+
+
+
+
+ 划线价:
+ ¥{{ diyComponent.market_price }}
+
+
+ 库存:
+ {{ diyComponent.stock }}
+ {{ diyComponent.goods.unit }}
+
+
+ 销量:
+ {{ diyComponent.goods.sale_num }}
+ {{ diyComponent.goods.unit }}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/uni-app/components/diy/shop-goods-detail-bottom/index.vue b/niucloud/addon/shop/uni-app/components/diy/shop-goods-detail-bottom/index.vue
new file mode 100644
index 000000000..d0ce29081
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/components/diy/shop-goods-detail-bottom/index.vue
@@ -0,0 +1,309 @@
+
+
+
+
+
+
+
+ 首页
+
+
+
+ 客服
+
+
+
+ 购物车
+
+
+
+ 收藏
+
+
+
+ 分享
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/uni-app/components/diy/shop-goods-detail-desc/index.vue b/niucloud/addon/shop/uni-app/components/diy/shop-goods-detail-desc/index.vue
new file mode 100644
index 000000000..bafe83ad3
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/components/diy/shop-goods-detail-desc/index.vue
@@ -0,0 +1,89 @@
+
+
+
+ 商品详情
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/uni-app/components/diy/shop-goods-detail-evaluate/index.vue b/niucloud/addon/shop/uni-app/components/diy/shop-goods-detail-evaluate/index.vue
new file mode 100644
index 000000000..6075675db
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/components/diy/shop-goods-detail-evaluate/index.vue
@@ -0,0 +1,162 @@
+
+
+
+
+ 宝贝评价({{ evaluate.count }})
+
+ 查看全部
+
+
+ 暂无评价
+
+
+
+
+
+ {{ item.member_name }}
+
+
+ {{ item.content }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/uni-app/components/diy/shop-goods-detail-purchase-service/index.vue b/niucloud/addon/shop/uni-app/components/diy/shop-goods-detail-purchase-service/index.vue
new file mode 100644
index 000000000..c2b2f736d
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/components/diy/shop-goods-detail-purchase-service/index.vue
@@ -0,0 +1,323 @@
+
+
+
+
+
+ 服务
+ {{ diyComponent.service[0].service_name }}
+
+
+
+ 已选
+ {{ diyComponent.sku_spec_format }}
+
+
+
+ 配送
+ {{ diyComponent.goods.delivery_type_list[selectDeliveryType].name }}
+
+
+
+ 领券
+
+
+ {{ item.title }}
+
+
+
+
+
+ 优惠
+
+ 满减送
+ {{ item.manjian_name }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/uni-app/components/diy/shop-goods-detail-sow/index.vue b/niucloud/addon/shop/uni-app/components/diy/shop-goods-detail-sow/index.vue
new file mode 100644
index 000000000..bcbdc37c8
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/components/diy/shop-goods-detail-sow/index.vue
@@ -0,0 +1,125 @@
+
+
+
+
+
+ 种草秀
+
+ ({{ diyComponent.sow_show_list.count }})
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/uni-app/components/diy/shop-goods-ranking/index.vue b/niucloud/addon/shop/uni-app/components/diy/shop-goods-ranking/index.vue
new file mode 100644
index 000000000..57ef6166b
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/components/diy/shop-goods-ranking/index.vue
@@ -0,0 +1,197 @@
+
+
+
+
+
+
+
+
+
+ {{ item.text }}
+ {{ listGoodsNames[item.rankIds[0]] }}
+
+
+
+ {{ item.subTitle.text }}
+
+
+
+
+
+
+
+ {{ goods.rank_num }}
+
+
+
+
+
+
+
+
+
+ {{ goods.goods_name }}
+
+
+ ¥
+ {{ diyGoods.goodsPrice(goods).toFixed(2).split('.')[0] }}
+ .{{ diyGoods.goodsPrice(goods).toFixed(2).split('.')[1] }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/uni-app/components/diy/shop-goods-recommend/index.vue b/niucloud/addon/shop/uni-app/components/diy/shop-goods-recommend/index.vue
new file mode 100644
index 000000000..3efd926d6
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/components/diy/shop-goods-recommend/index.vue
@@ -0,0 +1,227 @@
+
+
+
+
+
+
+
+
+
+ {{ item.title.text }}
+ {{ item.moreTitle.text }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ¥
+ {{ parseFloat(diyGoods.goodsPrice(item.info)).toFixed(2) }}
+
+
+
+ {{ item.button.text }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/uni-app/components/diy/shop-member-info/index.vue b/niucloud/addon/shop/uni-app/components/diy/shop-member-info/index.vue
new file mode 100644
index 000000000..47f975028
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/components/diy/shop-member-info/index.vue
@@ -0,0 +1,263 @@
+
+
+
+
+
+
+
+
+
+
+
+ {{ info.nickname }}
+ {{ info.mobile.replace(info.mobile.substring(3, 7), "****") }}
+
+
+
+ {{ t('bindMobile') }}
+
+
+
+
+
+
+
+
+ UID:{{ info.member_no }}
+
+
+
+
+
+
+ {{ t('login') }}/{{ t('register') }}
+
+
+
+
+
+
+
+
+ {{ money }}
+
+
+ {{ t('balance') }}
+
+
+
+
+ {{ parseInt(info?.point) || 0 }}
+
+
+ {{ t('point') }}
+
+
+
+
+ {{ couponCount }}
+
+
+ {{ t('coupon') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/uni-app/components/diy/shop-newcomer/index.vue b/niucloud/addon/shop/uni-app/components/diy/shop-newcomer/index.vue
new file mode 100644
index 000000000..ab2221013
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/components/diy/shop-newcomer/index.vue
@@ -0,0 +1,521 @@
+
+
+
+
+
+
+ 活动未开始
+
+ 距结束还有
+
+
+
+ {{ dayTransitionHours() }}
+ 00
+ :
+
+
+ {{ timeData.minutes >= 10 ? timeData.minutes : '0' + timeData.minutes }}
+ 00
+ :
+
+
+ {{ timeData.seconds < 10 ? '0' + timeData.seconds : timeData.seconds }}
+ 00
+
+
+
+
+ 活动已结束
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ list[0].goods.goods_name }}
+
+
+ ¥
+ {{ goodsPrice(list[0]) }}
+
+ 抢
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ¥
+ {{ goodsPrice(item) }}
+
+
+
+
+
+
+
+
+
+
+ 活动未开始
+
+ 倒计时
+
+
+
+ {{ timeData.days }}
+ 0
+ 天
+
+
+ {{ timeData.hours >= 10 ? timeData.hours : '0' + timeData.hours }}
+ 00
+ 时
+
+
+ {{ timeData.minutes >= 10 ? timeData.minutes : '0' + timeData.minutes }}
+ 00
+ 分
+
+
+
+
+ 活动已结束
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ¥
+ {{ goodsPrice(item) }}
+
+
+
+
+
+
+
+
+
+ 活动未开始
+
+
+
+ {{ dayTransitionHours() }}
+ 00
+ :
+
+
+ {{ timeData.minutes >= 10 ? timeData.minutes : '0' + timeData.minutes }}
+ 00
+ :
+
+
+ {{ timeData.seconds < 10 ? '0' + timeData.seconds : timeData.seconds }}
+ 00
+
+
+
+ 活动已结束
+
+
+
+ {{ diyComponent.subTitle.text }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ¥
+ {{ goodsPrice(item) }}
+
+
+
+
+
+
+
+
+
+ 活动未开始
+
+ 本场仅剩
+
+
+
+ {{ dayTransitionHours() }}
+ 00
+ :
+
+
+ {{ timeData.minutes >= 10 ? timeData.minutes : '0' + timeData.minutes }}
+ 00
+ :
+
+
+ {{ timeData.seconds < 10 ? '0' + timeData.seconds : timeData.seconds }}
+ 00
+
+
+
+
+ 活动已结束
+
+
+
+
+
+
+
+
+
+
+
+ 新人价
+
+
+
+ ¥
+ {{ goodsPrice(item) }}
+
+ 抢
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/uni-app/components/diy/shop-order-info/index.vue b/niucloud/addon/shop/uni-app/components/diy/shop-order-info/index.vue
new file mode 100644
index 000000000..91cbfd203
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/components/diy/shop-order-info/index.vue
@@ -0,0 +1,124 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/uni-app/components/diy/shop-search/index.vue b/niucloud/addon/shop/uni-app/components/diy/shop-search/index.vue
new file mode 100644
index 000000000..9e4836768
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/components/diy/shop-search/index.vue
@@ -0,0 +1,102 @@
+
+
+
+
+
+
+ {{ diyComponent.text }}
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/uni-app/components/diy/single-recommend/index.vue b/niucloud/addon/shop/uni-app/components/diy/single-recommend/index.vue
new file mode 100644
index 000000000..bdedc8d3c
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/components/diy/single-recommend/index.vue
@@ -0,0 +1,260 @@
+
+
+
+
+
+
+
+ {{ diyComponent.subTitle.text }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ goodsList[0].goods_name }}
+
+
+
+ ¥
+ {{ parseFloat(diyGoods.goodsPrice(goodsList[0])).toFixed(2).split('.')[0] }}
+ .{{ parseFloat(diyGoods.goodsPrice(goodsList[0])).toFixed(2).split('.')[1] }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/uni-app/components/ns-goods-manjian/ns-goods-manjian.vue b/niucloud/addon/shop/uni-app/components/ns-goods-manjian/ns-goods-manjian.vue
new file mode 100644
index 000000000..32e785035
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/components/ns-goods-manjian/ns-goods-manjian.vue
@@ -0,0 +1,180 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/uni-app/components/ns-goods-recommend/ns-goods-recommend.vue b/niucloud/addon/shop/uni-app/components/ns-goods-recommend/ns-goods-recommend.vue
new file mode 100644
index 000000000..fb925f9a1
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/components/ns-goods-recommend/ns-goods-recommend.vue
@@ -0,0 +1,71 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/uni-app/components/ns-goods-sku/ns-goods-sku.vue b/niucloud/addon/shop/uni-app/components/ns-goods-sku/ns-goods-sku.vue
new file mode 100644
index 000000000..2faa9fafd
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/components/ns-goods-sku/ns-goods-sku.vue
@@ -0,0 +1,478 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/uni-app/components/ns-impulse-buy/ns-impulse-buy.vue b/niucloud/addon/shop/uni-app/components/ns-impulse-buy/ns-impulse-buy.vue
new file mode 100644
index 000000000..710b2d007
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/components/ns-impulse-buy/ns-impulse-buy.vue
@@ -0,0 +1,255 @@
+
+
+
+
+
+ {{ impulseBuyConfigInfo.title }}
+
+ {{ impulseBuyConfigInfo.sub_title }}
+
+
+
+ {{ t('changeIt') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ item.goods.goods_name }}
+ {{ item.sku.sku_name }}
+ {{ `${t('limitPlaceholderOne')}${item.limit_buy}${t('limitPlaceholderTwo')}¥${goodsPrice(item)}${t('limitPlaceholderThree')}` }}
+
+
+
+ ¥
+ {{ parseFloat(item.impulse_buy_price).toFixed(2).split('.')[0] }}
+ .{{ parseFloat(item.impulse_buy_price).toFixed(2).split('.')[1] }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/uni-app/components/ns-select-time/date.js b/niucloud/addon/shop/uni-app/components/ns-select-time/date.js
new file mode 100644
index 000000000..c9e5a907a
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/components/ns-select-time/date.js
@@ -0,0 +1,221 @@
+//字符串拼接
+function strFormat(str) {
+ return str < 10 ? `0${ str }` : str
+}
+
+// 获取当前时间
+export function currentTime() {
+ const myDate = new Date();
+ const y = myDate.getFullYear()
+ const m = myDate.getMonth() + 1;
+ const d = myDate.getDate();
+ const date = y + '-' + strFormat(m) + '-' + strFormat(d)//年月日
+ const mdTime = strFormat(m) + '-' + strFormat(d)
+ const md = strFormat(m) + '月' + strFormat(d) + '日'
+ const hour = myDate.getHours()
+ const min = myDate.getMinutes()
+ const secon = myDate.getSeconds()
+ const seconTime = Math.floor(Date.now() / 1000)
+ const time = strFormat(hour) + ':' + strFormat(min) + ':' + strFormat(secon);
+ return {
+ y,
+ md,
+ mdTime,
+ date,
+ time,
+ seconTime
+ }
+}
+
+//时间戳转日期
+export function timeStamp(time, isQuantum) {
+ const dates = new Date(time)
+ const year = dates.getFullYear()
+ const month = dates.getMonth() + 1
+ const date = dates.getDate()
+ const day = dates.getDay()
+ const hour = dates.getHours()
+ const min = dates.getMinutes()
+ const days = ['日', '一', '二', '三', '四', '五', '六']
+ const xinqi = [0, 1, 2, 3, 4, 5, 6]
+ return {
+ allDate: `${ year }/${ strFormat(month) }/${ strFormat(date) }`,
+ date: `${ strFormat(year) }-${ strFormat(month) }-${ strFormat(date) }`, //返回的日期 2000-07-01
+ md: `${ strFormat(month) }月${ strFormat(date) }日`,//返回的日期 07月01日
+ mdTime: `${ strFormat(month) }-${ strFormat(date) }`, //返回的日期 07-01
+ day: `周${ days[day] }`, //返回的礼拜天数 星期一
+ dayNum: `${ xinqi[day] }`, //返回的礼拜天数 用于判断左侧设置
+ hour: strFormat(hour) + ':' + strFormat(min) + (isQuantum ? "" : ':00') //返回的时钟 08:00
+ }
+}
+
+//获取最近7天的日期和礼拜天数
+export function initData() {
+ const time = []
+ const date = new Date()
+
+ const now = date.getTime() //获取当前日期的时间戳
+ let timeStr = 3600 * 24 * 1000 //一天的时间戳
+ let obj = {
+ 0: "今天",
+ 1: "明天",
+ 2: "后天"
+ }
+ for (let i = 0; i < 7; i++) {
+ time.push({
+ date: timeStamp(now + timeStr * i).date, //保存日期(年月日)
+ mdTime: timeStamp(now + timeStr * i).md,
+ md: obj[i] ? obj[i] : timeStamp(now + timeStr * i).md,
+ timeStamp: now + timeStr * i, //保存时间戳
+ week: timeStamp(now + timeStr * i).day,
+ dayNum: timeStamp(now + timeStr * i).dayNum,
+ disable: false
+ })
+ }
+ return time
+}
+// 预约
+export function initAppointmentData(advanceDay, mostDay) {
+ const time = [];
+ const date = new Date()
+ let timeStr = 3600 * 24 * 1000 //一天的时间戳
+
+ // 加上今天
+ const now = date.getTime() //获取当前日期的时间戳
+ // time.push({
+ // date: timeStamp(now).date, //保存日期(年月日)
+ // mdTime: timeStamp(now).md,
+ // md: '今天',
+ // timeStamp: now , //保存时间戳
+ // week: timeStamp(now).day,
+ // dayNum: timeStamp(now).dayNum,
+ // disable: false
+ // });
+
+ // 正常预约范围
+ for (let i = advanceDay; i <= mostDay; i++) {
+ time.push({
+ date: timeStamp(now + timeStr * i).date, //保存日期(年月日)
+ mdTime: timeStamp(now + timeStr * i).md,
+ md: i === 0 ? '今天' : i === 1 ? '明天' : i === 2 ? '后天' : timeStamp(now + timeStr * i).md,
+ timeStamp: now + timeStr * i, //保存时间戳
+ week: timeStamp(now + timeStr * i).day,
+ dayNum: timeStamp(now + timeStr * i).dayNum,
+ disable: false
+ });
+ }
+
+ return time;
+}
+/**
+ * 仅返回“今天”这一项,用于只展示今天场景
+ */
+export function initTodayData() {
+ const time = [];
+ const date = new Date()
+ let timeStr = 3600 * 24 * 1000 //一天的时间戳
+
+ // 加上今天
+ const now = date.getTime() //获取当前日期的时间戳
+ time.push({
+ date: timeStamp(now).date, //保存日期(年月日)
+ mdTime: timeStamp(now).md,
+ md: '今天',
+ timeStamp: now , //保存时间戳
+ week: timeStamp(now).day,
+ dayNum: timeStamp(now).dayNum,
+ disable: false
+ });
+
+ return time;
+}
+
+
+//时间数组
+export function initTime(trade_time_json, timeInterval = 0.5, isQuantum = true) {
+ const time = [];
+ const timeStr = 3600 * timeInterval; // 间隔时间转换成秒
+
+ trade_time_json.forEach(slot => {
+ let start = slot.start_time;
+ let end = slot.end_time;
+
+ for (let i = start; i < end; i += timeStr) {
+ let nextTime = i + timeStr > end ? end : i + timeStr;
+
+ if (isQuantum) {
+ time.push({
+ begin: timestampTransition(i),
+ end: timestampTransition(nextTime),
+ disable: false
+ });
+ } else {
+ time.push({
+ time: timestampTransition(i),
+ disable: false
+ });
+ }
+ }
+ });
+
+ return time;
+}
+
+// 带“立即送出”的时间数组,仅用于预约
+export function initTimeWithImmediate(trade_time_json, timeInterval = 0.5, isQuantum = true) {
+ const time = [];
+
+ // 先插入立即送出
+ time.push({
+ begin: '立即',
+ end: '送出',
+ value: 'immediate',
+ disable: false
+ });
+
+ const timeStr = 3600 * timeInterval; // 间隔时间转秒
+
+ trade_time_json.forEach(slot => {
+ let start = slot.start_time;
+ let end = slot.end_time;
+
+ for (let i = start; i < end; i += timeStr) {
+ let nextTime = i + timeStr > end ? end : i + timeStr;
+
+ if (isQuantum) {
+ time.push({
+ begin: timestampTransition(i),
+ end: timestampTransition(nextTime),
+ disable: false
+ });
+ } else {
+ time.push({
+ time: timestampTransition(i),
+ disable: false
+ });
+ }
+ }
+ });
+
+ return time;
+}
+
+
+// 时间戳转时间
+export function timestampTransition(timeStamp) {
+ let hour = Math.floor(timeStamp / (60 * 60))
+ let minute = Math.floor(timeStamp / 60) - (hour * 60)
+ let second = timeStamp % 60
+ hour = hour < 10 ? ('0' + hour) : hour
+ minute = minute < 10 ? ('0' + minute) : minute
+ // second = second < 10 ? ( '0' + second ) : second
+ return hour + ':' + minute
+}
+
+// 时间转时间戳
+export function timeTransition(time) {
+ const arr = time.split(':');
+ const hours = Number(arr[0]) * 60 * 60;
+ const minutes = Number(arr[1]) * 60;
+ return hours + minutes;
+}
diff --git a/niucloud/addon/shop/uni-app/components/ns-select-time/index.vue b/niucloud/addon/shop/uni-app/components/ns-select-time/index.vue
new file mode 100644
index 000000000..55af3e9e8
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/components/ns-select-time/index.vue
@@ -0,0 +1,277 @@
+
+
+
+
+ {{ rules.type=='subscribe' ? '请选择配送时间' : '请选择自提时间'}}
+
+
+
+
+
+
+ {{ item.md }}
+ ({{ item.week }})
+
+
+
+
+
+
+
+
+
+ {{ el.begin }}{{ el.end }}
+ {{ el.begin }}-{{ el.end }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/uni-app/hooks/useDiyGoodsDetail.ts b/niucloud/addon/shop/uni-app/hooks/useDiyGoodsDetail.ts
new file mode 100644
index 000000000..903bb887c
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/hooks/useDiyGoodsDetail.ts
@@ -0,0 +1,315 @@
+import { computed, reactive, ref, watch } from 'vue';
+import { onHide, onLoad, onPageScroll, onShow, onUnload } from '@dcloudio/uni-app';
+import { deepClone, goback, handleOnloadParams, img, getToken } from '@/utils/common';
+import useDiyStore from '@/app/stores/diy';
+import { getDiyInfo } from '@/app/api/diy';
+import { getGoodsDetail, browse } from '@/addon/shop/api/goods';
+import useGoodsDetailStore from '@/addon/shop/stores/goodsDetail'
+
+export function useDiyGoodsDetail(params: any = {}) {
+
+ const loading = ref(true);
+ const diyStore = useDiyStore();
+
+ const id = ref(0)
+ const name = ref(params.name || '')
+ const template = ref('')
+ const currRoute = ref('') //当前路由
+ const requestData: any = reactive({});
+
+ // 自定义页面 数据
+ const diyData = reactive({
+ pageMode: 'diy',
+ title: '',
+ global: {},
+ value: []
+ })
+
+ // 商品详情参数
+ const goodsDetailParameter: any = reactive({
+ goods_id: '',
+ sku_id: '',
+ type: '' // 来源营销活动类型,例如:discount:限时折扣,newcomer_discount:新人价
+ });
+
+ const getLoading = () => {
+ return loading.value;
+ }
+
+ const data: any = computed(() => {
+ if (diyStore.mode == 'decorate') {
+ return diyStore;
+ } else {
+ return diyData;
+ }
+ })
+
+ const isShowTopTabbar = ref(false);
+
+ const pageStyle = () => {
+ let style = '';
+ if (data.value.global.pageStartBgColor) {
+ if (data.value.global.pageStartBgColor && data.value.global.pageEndBgColor) style += `background:linear-gradient(${ data.value.global.pageGradientAngle },${ data.value.global.pageStartBgColor },${ data.value.global.pageEndBgColor });`;
+ else style += 'background-color:' + data.value.global.pageStartBgColor + ';';
+ }
+ if (data.value.global.bottomTabBar && data.value.global.bottomTabBar.isShow) {
+ style += 'min-height:calc(100vh - 50px);';
+ } else {
+ style += 'min-height:calc(100vh);';
+ }
+ if (data.value.global.bgUrl) {
+ style += `background-image:url('${ img(data.value.global.bgUrl) }');`;
+ }
+
+ if (data.value.global.bgHeightScale) {
+ style += `background-size: 100% ${ data.value.global.bgHeightScale }%;`;
+ }
+ return style;
+ };
+
+ // 监听页面加载
+ const onLoadLifeCycle = () => {
+ onLoad((option: any) => {
+ // #ifdef MP-WEIXIN
+ // 处理小程序场景值参数
+ option = handleOnloadParams(option);
+ // #endif
+
+ // #ifdef H5
+ // 装修模式
+ diyStore.mode = option.mode || '';
+ if (diyStore.mode == 'decorate') {
+ loading.value = false;
+ }
+ // #endif
+
+ goodsDetailParameter.goods_id = option.goods_id || '';
+ goodsDetailParameter.sku_id = option.sku_id || '';
+ goodsDetailParameter.type = option.type || '';
+
+ id.value = option.id || '';
+ if (name.value == '') name.value = option.name || '';
+ template.value = option.template || '';
+ });
+ }
+
+ // 监听页面显示
+ const onShowLifeCycle = (callback: any = null) => {
+ onShow(() => {
+ /******** 解决跳转自定义页面空白问题-第二步-start **********/
+ let curPage: any = getCurrentPages();
+ currRoute.value = curPage[curPage.length - 1] ? curPage[curPage.length - 1].route : ''; //获取当前页面的路由
+ let urlArr = []
+ if (uni.getStorageSync('diyPageBlank')) {
+ urlArr = uni.getStorageSync('diyPageBlank');
+ }
+ if (!urlArr.length || urlArr.length && urlArr.indexOf(currRoute.value) == -1) {
+ diyStore.topFixedStatus = 'home'
+ } else if (urlArr.length && urlArr.indexOf(currRoute.value) != -1) {
+ diyStore.topFixedStatus = 'diy'
+ }
+ /******** 解决跳转自定义页面空白问题-第二步-end **********/
+ // 装修模式
+ if (diyStore.mode == 'decorate') {
+ diyStore.init();
+ } else if(id.value){
+ // 用于商品详情页预览
+ getDiyInfo({
+ id: id.value,
+ name: name.value
+ }).then((res: any) => {
+ Object.assign(requestData, res.data);
+ handleComponentDataFn()
+ diyStore.mode = 'decorate';
+ diyStore.value = diyData.value;
+ diyStore.global = diyData.global;
+
+ loading.value = false;
+ if (callback) callback(requestData)
+ })
+
+ } else {
+ getGoodsDetail({
+ goods_id: goodsDetailParameter.goods_id || '',
+ sku_id: goodsDetailParameter.sku_id || '',
+ type: goodsDetailParameter.type || '' // 来源营销活动类型,例如:discount:限时折扣,newcomer_discount:新人价
+ }).then((res: any) => {
+ if (!res.data.goods || JSON.stringify(res.data) === '[]') {
+ let goBackParameter = {
+ url: '/addon/shop/pages/index',
+ title: '找不到该商品',
+ mode: 'reLaunch'
+ };
+ goback(goBackParameter)
+ return false
+ }
+
+ Object.assign(requestData, res.data.diy_detail_info);
+ handleComponentDataFn()
+ // 商品详情数据处理
+ diyData.global.goodsParameter = {}
+ diyData.global.goodsParameter.goods_id = goodsDetailParameter.goods_id
+ diyData.global.goodsParameter.sku_id = goodsDetailParameter.sku_id
+ diyData.global.goodsParameter.type = goodsDetailParameter.type
+ // 组装商品组件数据
+ assembleGoodsDetailData(diyData, res.data)
+
+ // 商品分享
+ requestData.share = {
+ title: res.data.goods.goods_name,
+ desc: res.data.goods.sub_title,
+ url: res.data.goods.goods_cover_thumb_mid
+ }
+
+ loading.value = false;
+ if (callback) callback(requestData)
+
+ });
+ }
+ })
+ }
+
+ // 处理组件数据
+ const handleComponentDataFn = () => {
+ if (requestData.value) {
+ diyData.pageMode = requestData.mode;
+ diyData.title = requestData.title;
+
+ let sources = JSON.parse(requestData.value); // todo diy的结构应该后台处理好,前端就不需要再转换了
+
+ diyData.global = sources.global;
+ // 用于区分微页面之间弹窗的id
+ if (diyData.global.popWindow && diyData.global.popWindow.show) {
+ diyData.global.popWindow.id = requestData.id;
+ }
+
+ diyData.value = sources.value;
+ diyData.value.forEach((item: any, index) => {
+
+ const detailComponent = ['ShopGoodsDetailBottom','ShopGoodsDetailDesc','ShopGoodsDetailAttr','ShopGoodsDetailEvaluate','ShopGoodsDetailSow','ShopGoodsDetailPurchaseService','ShopGoodsDetailBasicInfo']
+ if(detailComponent.indexOf(item.componentName) > -1){
+ item.componentIsShow = false // 是否显示
+ }else{
+ item.componentIsShow = true // 是否显示
+ }
+
+ item.pageStyle = '';
+ if (item.pageStartBgColor) {
+ if (item.pageStartBgColor && item.pageEndBgColor) item.pageStyle += `background:linear-gradient(${ item.pageGradientAngle },${ item.pageStartBgColor },${ item.pageEndBgColor });`;
+ else item.pageStyle += 'background-color:' + item.pageStartBgColor + ';';
+ }
+
+ if (item.margin) {
+ if (item.margin.top > 0) {
+ item.pageStyle += 'padding-top:' + item.margin.top * 2 + 'rpx' + ';';
+ }
+ item.pageStyle += 'padding-bottom:' + item.margin.bottom * 2 + 'rpx' + ';';
+ item.pageStyle += 'padding-right:' + item.margin.both * 2 + 'rpx' + ';';
+ item.pageStyle += 'padding-left:' + item.margin.both * 2 + 'rpx' + ';';
+ }
+ });
+
+ // 控制自定义头部是否出现 | 微信小程序
+ isShowTopTabbar.value = diyData.value.some((item: any) => {
+ return item && item.position && item.position == 'top_fixed'
+ });
+
+ uni.setNavigationBarTitle({
+ title: diyData.title
+ });
+
+ }
+ }
+
+ // 监听页面隐藏
+ const onHideLifeCycle = (callback: any = null) => {
+ onHide(() => {
+ /******** 解决跳转自定义页面空白问题-第一步 -start **********/
+ let url = [];
+ if (uni.getStorageSync('diyPageBlank')) {
+ url = uni.getStorageSync('diyPageBlank');
+ }
+
+ // 清空重复、与当前页面路径一致的url
+ if (url.length) {
+ url = Array.from(new Set(url))
+ url.forEach((item, index, arr) => {
+ if (item == currRoute.value) {
+ arr.splice(index, 1);
+ }
+ })
+ }
+
+ // 当diyStore.topFixedStatus == "diy"时,存储到diyPageBlank缓存中
+ if (diyStore.topFixedStatus == "diy") {
+ url.push(currRoute.value);
+ }
+ uni.setStorageSync('diyPageBlank', url);
+ /******** 解决跳转自定义页面空白问题-第一步 -end **********/
+
+ if (callback) callback()
+ })
+ }
+
+ // 监听页面卸载
+ const onUnloadLifeCycle = () => {
+ onUnload(() => {
+ useGoodsDetailStore().removeGoodsDetail()
+ })
+ }
+
+ // 监听滚动事件
+ const onPageScrollLifeCycle = () => {
+ onPageScroll((e) => {
+ if (e.scrollTop > 0) {
+ diyStore.scrollTop = e.scrollTop;
+ }
+ })
+ }
+
+ const assembleGoodsDetailData = (componentData: any, res: any) => {
+ let data = deepClone(res)
+ data.goods.goods_image = data.goods.goods_image.split(',');
+ data.goods.goods_image.forEach((item: any, index: any) => {
+ data.goods.goods_image[index] = img(item);
+ })
+ data.goods.delivery_type_list = data.goods.delivery_type_list ? Object.values(data.goods.delivery_type_list) : []
+
+ if (getToken()) {
+ // 我的足迹
+ myBrowseFn(data.goods.goods_id);
+ }
+
+ uni.setNavigationBarTitle({
+ title: data.goods.goods_name
+ })
+
+ // 弹窗开启
+ data.isOpenSkuBuy = false
+ data.skuBuyType = ''
+
+ // 打开分享弹窗
+ data.isOpenSharePoster = false
+ useGoodsDetailStore().setGoodsDetail(data,true)
+ }
+
+ // 我的足迹
+ const myBrowseFn = (goods_id: any) => {
+ browse({
+ goods_id
+ }).then((res: any) => {
+ })
+ }
+
+ return {
+ getLoading,
+ data: data.value,
+ isShowTopTabbar,
+ pageStyle,
+ onLoad: onLoadLifeCycle,
+ onShow: onShowLifeCycle,
+ onHide: onHideLifeCycle,
+ onUnload: onUnloadLifeCycle,
+ onPageScroll: onPageScrollLifeCycle,
+ }
+}
diff --git a/niucloud/addon/shop/uni-app/hooks/useGoods.ts b/niucloud/addon/shop/uni-app/hooks/useGoods.ts
new file mode 100644
index 000000000..ecd6ffb29
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/hooks/useGoods.ts
@@ -0,0 +1,39 @@
+export function useGoods(params: any = {}) {
+
+ const baseTagStyle = (data: any) => {
+ let style = "";
+ if (data.color_json && data.color_json.text_color) {
+ style += `color:${ data.color_json.text_color };`;
+ }
+ if (data.color_json && data.color_json.border_color) {
+ style += `border-color: ${ data.color_json.border_color };`;
+ }
+ if (data.color_json && data.color_json.bg_color) {
+ style += `background-color: ${ data.color_json.bg_color };`;
+ }
+ return style;
+ }
+
+ // 价格类型
+ const priceType = (data: any) => {
+ return data.goodsSku.show_type
+ }
+
+ // 商品价格
+ const goodsPrice = (data: any) => {
+ let price = data.goodsSku.show_price
+ return parseFloat(price);
+ }
+
+ // 错误图片展示
+ const errorImgFn = (data: any, type: any) => {
+ data[type] = '';
+ }
+
+ return {
+ baseTagStyle: baseTagStyle,
+ goodsPrice: goodsPrice,
+ priceType: priceType,
+ error: errorImgFn
+ }
+}
diff --git a/niucloud/addon/shop/uni-app/locale/en.json b/niucloud/addon/shop/uni-app/locale/en.json
new file mode 100644
index 000000000..9e26dfeeb
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/locale/en.json
@@ -0,0 +1 @@
+{}
\ No newline at end of file
diff --git a/niucloud/addon/shop/uni-app/locale/zh-Hans.json b/niucloud/addon/shop/uni-app/locale/zh-Hans.json
new file mode 100644
index 000000000..70b4722d3
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/locale/zh-Hans.json
@@ -0,0 +1,39 @@
+{
+ "pages.goods.search": "搜索",
+ "pages.goods.cart": "购物车",
+ "pages.goods.collect": "商品收藏",
+ "pages.goods.browse": "我的足迹",
+ "pages.goods.category": "商品分类",
+ "pages.goods.detail": "商品详情",
+ "pages.goods.list": "商品列表",
+ "pages.goods.rank": "排行榜",
+ "pages.member.index": "个人中心",
+ "pages.member.my_coupon": "我的优惠券",
+ "pages.order.list": "订单列表",
+ "pages.order.detail": "订单详情",
+ "pages.order.payment": "待付款订单",
+ "pages.evaluate.order_evaluate": "商品评价",
+ "pages.evaluate.order_evaluate_view": "商品评价",
+ "pages.evaluate.list": "评价列表",
+ "pages.coupon.list": "优惠券列表",
+ "pages.coupon.detail": "优惠券详情",
+ "pages.discount.list": "限时折扣",
+ "pages.refund.list": "退款列表",
+ "pages.refund.detail": "退款详情",
+ "pages.refund.apply": "申请退款",
+ "pages.refund.edit_apply": "编辑退款信息",
+ "pages.refund.log": "协商记录",
+ "pages.point.index": "积分商城",
+ "pages.point.list": "积分商品列表",
+ "pages.point.detail": "积分商品详情",
+ "pages.point.payment": "待付款订单",
+ "pages.point.order_list": "积分兑换记录",
+ "pages.newcomer.list": "新人专享",
+ "pages.invoice.list": "发票管理",
+ "pages.invoice.detail": "发票详情",
+ "pages.invoice.invoice": "申请发票",
+ "pages.invoice.invoice_edit": "编辑发票信息",
+ "pages.invoice.invoice_order": "发票订单",
+ "pages.pay.index": "待支付",
+ "pages.pay.result": ""
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/uni-app/locale/zh-Hans/common.json b/niucloud/addon/shop/uni-app/locale/zh-Hans/common.json
new file mode 100644
index 000000000..0a041dd1c
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/locale/zh-Hans/common.json
@@ -0,0 +1,10 @@
+{
+ "orderNo": "订单号",
+ "actualPayment": "实付款",
+ "orderClose": "关闭订单",
+ "orderFinish": "确认收货",
+ "coupon":"优惠劵",
+ "emptyAddress": "暂无收货地址,请先创建地址",
+ "addAddress": "新增收货地址",
+ "selectAddress": "选择地址"
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/uni-app/locale/zh-Hans/pages.goods.cart.json b/niucloud/addon/shop/uni-app/locale/zh-Hans/pages.goods.cart.json
new file mode 100644
index 000000000..2c63c0851
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/locale/zh-Hans/pages.goods.cart.json
@@ -0,0 +1,2 @@
+{
+}
diff --git a/niucloud/addon/shop/uni-app/locale/zh-Hans/pages.goods.category.json b/niucloud/addon/shop/uni-app/locale/zh-Hans/pages.goods.category.json
new file mode 100644
index 000000000..2c63c0851
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/locale/zh-Hans/pages.goods.category.json
@@ -0,0 +1,2 @@
+{
+}
diff --git a/niucloud/addon/shop/uni-app/locale/zh-Hans/pages.goods.detail.json b/niucloud/addon/shop/uni-app/locale/zh-Hans/pages.goods.detail.json
new file mode 100644
index 000000000..2c63c0851
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/locale/zh-Hans/pages.goods.detail.json
@@ -0,0 +1,2 @@
+{
+}
diff --git a/niucloud/addon/shop/uni-app/locale/zh-Hans/pages.goods.list.json b/niucloud/addon/shop/uni-app/locale/zh-Hans/pages.goods.list.json
new file mode 100644
index 000000000..358a66be7
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/locale/zh-Hans/pages.goods.list.json
@@ -0,0 +1,4 @@
+{
+ "all": "全部",
+ "price": "价格"
+}
diff --git a/niucloud/addon/shop/uni-app/locale/zh-Hans/pages.goods.rank.json b/niucloud/addon/shop/uni-app/locale/zh-Hans/pages.goods.rank.json
new file mode 100644
index 000000000..b6f022fc5
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/locale/zh-Hans/pages.goods.rank.json
@@ -0,0 +1,3 @@
+{
+ "rankingRules":"榜单规则"
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/uni-app/locale/zh-Hans/pages.index.json b/niucloud/addon/shop/uni-app/locale/zh-Hans/pages.index.json
new file mode 100644
index 000000000..2c63c0851
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/locale/zh-Hans/pages.index.json
@@ -0,0 +1,2 @@
+{
+}
diff --git a/niucloud/addon/shop/uni-app/locale/zh-Hans/pages.member.index.json b/niucloud/addon/shop/uni-app/locale/zh-Hans/pages.member.index.json
new file mode 100644
index 000000000..c8b96b1cd
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/locale/zh-Hans/pages.member.index.json
@@ -0,0 +1,3 @@
+{
+ "coupon": "优惠券"
+}
diff --git a/niucloud/addon/shop/uni-app/locale/zh-Hans/pages.order.detail.json b/niucloud/addon/shop/uni-app/locale/zh-Hans/pages.order.detail.json
new file mode 100644
index 000000000..8b439cbc5
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/locale/zh-Hans/pages.order.detail.json
@@ -0,0 +1,25 @@
+{
+ "orderNo": "订单号",
+ "actualPayment": "实付款",
+ "orderClose": "关闭订单",
+ "orderFinish": "确认收货",
+ "topay": "去支付",
+ "orderDetail": "详情",
+ "orderTradeNo": "支付流水号",
+ "createTime": "创建时间",
+ "deliveryType": "配送方式",
+ "payTypeName": "支付方式",
+ "payTime": "支付时间",
+ "goodsMoney": "商品金额",
+ "deliveryMoney": "配送费用",
+ "orderMoney": "实付金额",
+ "evaluate": "评价",
+ "selectedEvaluate": "查看评价",
+ "index": "首页",
+ "discountMoney": "优惠金额",
+ "logisticsTracking":"查看物流",
+ "copy":"复制",
+ "detailedInformation":"详细信息",
+ "helpPay":"的帮付",
+ "memberRemark":"用户备注"
+}
diff --git a/niucloud/addon/shop/uni-app/locale/zh-Hans/pages.order.list.json b/niucloud/addon/shop/uni-app/locale/zh-Hans/pages.order.list.json
new file mode 100644
index 000000000..937a509b7
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/locale/zh-Hans/pages.order.list.json
@@ -0,0 +1,16 @@
+{
+ "emptyAddress":"暂无收货地址,请先创建地址",
+ "addAddress":"新增收货地址",
+ "selectAddress":"选择地址",
+ "evaluate": "评价",
+ "money":"元",
+ "pendingPayment":"待支付",
+ "pendingPaymentTips":"剩余时间",
+ "service":"含物流运输服务",
+ "selectedEvaluate": "查看评价",
+ "orderClose": "关闭订单",
+ "orderFinish": "确认收货",
+ "topay": "支付",
+ "deliveryType":"配送方式",
+ "createTime":"下单时间"
+}
diff --git a/niucloud/addon/shop/uni-app/locale/zh-Hans/pages.order.payment.json b/niucloud/addon/shop/uni-app/locale/zh-Hans/pages.order.payment.json
new file mode 100644
index 000000000..769e24d46
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/locale/zh-Hans/pages.order.payment.json
@@ -0,0 +1,23 @@
+{
+ "orderNo": "订单号",
+ "actualPayment": "实付款",
+ "orderClose": "关闭订单",
+ "orderFinish": "确认收货",
+ "topay": "支付",
+ "orderDetail": "详情",
+ "evaluate": "评价",
+ "orderListempty":"暂无订单",
+ "emptyAddress":"暂无收货地址,请先创建地址",
+ "changeIt":"换一换",
+ "activityInstructions":"活动说明",
+ "goodsLimitThree":"该商品起购",
+ "piece":"件",
+ "goodsLimitTwo":"该商品每人限购",
+ "goodsLimitOne":"该商品单次限购",
+ "stockNotEnough":"商品库存不足",
+ "limitPlaceholderTwo":"件,超过按",
+ "limitPlaceholderThree":"购买",
+ "limitPlaceholderOne":"限购",
+ "buyWithOneClick":"一键购买",
+ "know":"我知道了"
+}
diff --git a/niucloud/addon/shop/uni-app/locale/zh-Hans/pages.point.detail.json b/niucloud/addon/shop/uni-app/locale/zh-Hans/pages.point.detail.json
new file mode 100644
index 000000000..e30ee6193
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/locale/zh-Hans/pages.point.detail.json
@@ -0,0 +1,5 @@
+{
+ "point":"积分",
+ "priceUnit":"元",
+ "redeemed":"已兑"
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/uni-app/locale/zh-Hans/pages.point.order_list.json b/niucloud/addon/shop/uni-app/locale/zh-Hans/pages.point.order_list.json
new file mode 100644
index 000000000..31342def5
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/locale/zh-Hans/pages.point.order_list.json
@@ -0,0 +1,14 @@
+{
+ "orderNo": "订单号",
+ "actualPayment": "订单金额",
+ "orderClose": "关闭订单",
+ "orderFinish": "确认收货",
+ "topay": "支付",
+ "orderDetail": "详情",
+ "evaluate": "评价",
+ "selectedEvaluate": "查看评价",
+ "orderListempty": "暂无订单",
+ "deliveryType":"配送方式",
+ "money":"元",
+ "point": "积分"
+}
diff --git a/niucloud/addon/shop/uni-app/locale/zh-Hans/pages.refund.detail.json b/niucloud/addon/shop/uni-app/locale/zh-Hans/pages.refund.detail.json
new file mode 100644
index 000000000..4fd1125b9
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/locale/zh-Hans/pages.refund.detail.json
@@ -0,0 +1,17 @@
+{
+ "refundDetail": "退货详情",
+ "fastRefundSuccessful": "极速退款成功",
+ "refundInfo": "由于你的信誉良好,已享受极速退款服务,退款即刻到账",
+ "refundType": "退款方式",
+ "refundMoney": "退款金额",
+ "refundCause": "退款原因",
+ "reasonRefusal": "拒绝原因",
+ "refundNo": "退款编号",
+ "createTime": "申请时间",
+ "createExplain": "退款说明",
+ "record": "协商记录",
+ "check": "查看",
+ "refundApply": "取消退款",
+ "cancelRefundContent": "撤销之后本次申请将会关闭,如后续仍有问题可再次发起申请。",
+ "index": "首页"
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/uni-app/locale/zh-Hans/pages.refund.list.json b/niucloud/addon/shop/uni-app/locale/zh-Hans/pages.refund.list.json
new file mode 100644
index 000000000..7d6830ade
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/locale/zh-Hans/pages.refund.list.json
@@ -0,0 +1,7 @@
+{
+ "refundNo": "退款编号",
+ "refundMoney": "退款金额",
+ "refundApply": "取消退款",
+ "refund": "退款进度",
+ "cancelRefundContent": "撤销之后本次申请将会关闭,如后续仍有问题可再次发起申请。"
+}
\ No newline at end of file
diff --git a/niucloud/addon/shop/uni-app/pages/coupon/detail.vue b/niucloud/addon/shop/uni-app/pages/coupon/detail.vue
new file mode 100644
index 000000000..a0ffdba68
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/pages/coupon/detail.vue
@@ -0,0 +1,177 @@
+
+
+
+
+
+
+
+ 限领{{ detail.limit_count }}张
+
+ {{ detail.coupon_price || 0.00 }}
+ 元
+
+
+ 无门槛
+ 满{{ detail.coupon_min_price }}元可用
+
+
+
+ 领取之日起
+ {{ detail.length }}
+ 天内有效
+
+
+ 有效期至
+ {{ detail.valid_end_time ? detail.valid_end_time.slice(0, 10) : '' }}
+
+
+
+ 已领完
+ 领取
+ 去使用
+
+
+
+
+ 注:扫描二维码或点击右上角进行分享
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/uni-app/pages/coupon/list.vue b/niucloud/addon/shop/uni-app/pages/coupon/list.vue
new file mode 100644
index 000000000..aafc902bb
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/pages/coupon/list.vue
@@ -0,0 +1,362 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/uni-app/pages/discount/list.vue b/niucloud/addon/shop/uni-app/pages/discount/list.vue
new file mode 100644
index 000000000..fc6723b74
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/pages/discount/list.vue
@@ -0,0 +1,304 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ item.remark }}
+
+ {{ item.status == 'not_active' ? '预告' : item.status_name }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/uni-app/pages/evaluate/components/upload-img.vue b/niucloud/addon/shop/uni-app/pages/evaluate/components/upload-img.vue
new file mode 100644
index 000000000..013d3990f
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/pages/evaluate/components/upload-img.vue
@@ -0,0 +1,96 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ value.length }}/{{ maxCount }}
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/uni-app/pages/evaluate/list.vue b/niucloud/addon/shop/uni-app/pages/evaluate/list.vue
new file mode 100644
index 000000000..a5b1cdaea
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/pages/evaluate/list.vue
@@ -0,0 +1,235 @@
+
+
+
+
+
+ {{ item.name }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/uni-app/pages/evaluate/order_evaluate.vue b/niucloud/addon/shop/uni-app/pages/evaluate/order_evaluate.vue
new file mode 100644
index 000000000..b63cd40f7
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/pages/evaluate/order_evaluate.vue
@@ -0,0 +1,156 @@
+
+
+
+
+
+
+
+ 匿名
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/uni-app/pages/evaluate/order_evaluate_view.vue b/niucloud/addon/shop/uni-app/pages/evaluate/order_evaluate_view.vue
new file mode 100644
index 000000000..50e2d570e
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/pages/evaluate/order_evaluate_view.vue
@@ -0,0 +1,186 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/uni-app/pages/goods/browse.vue b/niucloud/addon/shop/uni-app/pages/goods/browse.vue
new file mode 100644
index 000000000..492fa74f0
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/pages/goods/browse.vue
@@ -0,0 +1,292 @@
+
+
+
+
+
+ 共
+ {{ browseTotal }}
+ 条
+
+
+
+ 日期
+
+
+
+ {{ isEdit ? '完成' : '管理' }}
+
+
+
+
+
+
+
+
+
+
+ 已选
+ {{ checkedNum }}
+ 件宝贝
+
+ 一键清空宝贝足迹
+
+
+
+
+ 全选
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/uni-app/pages/goods/cart.vue b/niucloud/addon/shop/uni-app/pages/goods/cart.vue
new file mode 100644
index 000000000..903db3a6e
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/pages/goods/cart.vue
@@ -0,0 +1,795 @@
+
+
+
+
+
+
+
+
+
+ 暂未登录
+
+
+
+
+
+
+
+ 赶紧去逛逛, 购买心仪的商品吧
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 全选
+
+
+
+
+
+ 合计:
+ ¥{{ parseFloat(total.order_money).toFixed(2) }}
+
+
+ 优惠明细
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 全选
+
+
+
+
+
+ 合计:
+ ¥{{ parseFloat(total.order_money).toFixed(2) }}
+
+
+ 优惠明细
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/uni-app/pages/goods/category.vue b/niucloud/addon/shop/uni-app/pages/goods/category.vue
new file mode 100644
index 000000000..53c9855ee
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/pages/goods/category.vue
@@ -0,0 +1,146 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/uni-app/pages/goods/collect.vue b/niucloud/addon/shop/uni-app/pages/goods/collect.vue
new file mode 100644
index 000000000..a8516f8a4
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/pages/goods/collect.vue
@@ -0,0 +1,195 @@
+
+
+
+
+
+
+
+
+
+
+ 全选
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/uni-app/pages/goods/components/add-cart-popup.vue b/niucloud/addon/shop/uni-app/pages/goods/components/add-cart-popup.vue
new file mode 100644
index 000000000..f035b3f15
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/pages/goods/components/add-cart-popup.vue
@@ -0,0 +1,379 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ¥
+ {{ parseFloat(goodsPrice(detail)).toFixed(2).split('.')[0] }}
+ .{{ parseFloat(goodsPrice(detail)).toFixed(2).split('.')[1] }}
+
+
+
+
+ 库存{{ detail.stock }}{{ goodsDetail.goods.unit }}
+
+
+ 已选规格:{{ detail.sku_spec_format }}
+
+
+
+
+
+ {{ item.spec_name }}
+
+ {{ subItem.name }}
+
+
+
+ 购买数量
+ ({{ minBuyShow }}{{ goodsDetail.goods.unit }}起售,限购{{ maxBuyShow }}{{ goodsDetail.goods.unit }})
+ (限购{{ maxBuyShow }}{{ goodsDetail.goods.unit }})
+ ({{ minBuyShow }}{{ goodsDetail.goods.unit }}起售)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/uni-app/pages/goods/components/category-template-one-one.vue b/niucloud/addon/shop/uni-app/pages/goods/components/category-template-one-one.vue
new file mode 100644
index 000000000..411627da4
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/pages/goods/components/category-template-one-one.vue
@@ -0,0 +1,793 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ item.category_name }}
+
+
+
+
+
+
+
+
+
+
+
+ {{ item.category_name }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ item.goods_name }}
+
+
+ ¥
+ {{ parseFloat(goodsPrice(item)).toFixed(2).split('.')[0] }}
+ .{{ parseFloat(goodsPrice(item)).toFixed(2).split('.')[1] }}
+
+
+
+
+
+
+
+
+
+ {{ cartList['goods_' + item.goods_id]['sku_' + item.goodsSku.sku_id].num }}
+
+
+
+
+
+
+ {{ config.cart.text }}
+ {{ cartList['goods_' + item.goods_id].totalNum }}
+
+
+
+ {{ cartList['goods_' + item.goods_id].totalNum }}
+
+
+
+ {{ cartList['goods_' + item.goods_id].totalNum }}
+
+
+
+
+
+ {{ cartList['goods_' + item.goods_id].totalNum }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ totalNum > 99 ? "99+" : totalNum }}
+
+
+ 总计:
+
+ ¥
+ {{ parseFloat(totalMoney) }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ totalNum > 99 ? "99+" : totalNum }}
+
+
+ 总计:
+
+ ¥
+ {{ parseFloat(totalMoney) }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/uni-app/pages/goods/components/category-template-two-one.vue b/niucloud/addon/shop/uni-app/pages/goods/components/category-template-two-one.vue
new file mode 100644
index 000000000..fbfdceab6
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/pages/goods/components/category-template-two-one.vue
@@ -0,0 +1,334 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ item.category_name }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{item.category_name }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/uni-app/pages/goods/components/category-template-two-two.vue b/niucloud/addon/shop/uni-app/pages/goods/components/category-template-two-two.vue
new file mode 100644
index 000000000..746f0980a
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/pages/goods/components/category-template-two-two.vue
@@ -0,0 +1,939 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ item.category_name }}
+
+
+
+
+
+
+
+
+
+
+
+ {{ item.category_name }}
+
+
+
+
+
+
+
+
+
+
+ {{ item.category_name }}
+
+
+
+
+
+ 全部分类
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ item.goods_name }}
+
+
+ ¥
+ {{ parseFloat(goodsPrice(item)).toFixed(2).split('.')[0] }}
+ .{{ parseFloat(goodsPrice(item)).toFixed(2).split('.')[1] }}
+
+
+
+
+
+
+
+
+
+ {{ cartList['goods_' + item.goods_id]['sku_' + item.goodsSku.sku_id].num }}
+
+
+
+
+
+
+
+ {{ config.cart.text }}
+
+
+ {{ cartList['goods_' + item.goods_id].totalNum }}
+
+
+
+
+ {{ cartList['goods_' + item.goods_id].totalNum }}
+
+
+
+ {{ cartList['goods_' + item.goods_id].totalNum }}
+
+
+
+
+
+ {{ cartList['goods_' + item.goods_id].totalNum }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ totalNum > 99 ? "99+" : totalNum }}
+
+
+ 总计:
+
+ ¥
+ {{ parseFloat(totalMoney) }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ totalNum > 99 ? "99+" : totalNum }}
+
+
+ 总计:
+
+ ¥
+ {{ parseFloat(totalMoney) }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/uni-app/pages/goods/detail.vue b/niucloud/addon/shop/uni-app/pages/goods/detail.vue
new file mode 100644
index 000000000..d409ab5a4
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/pages/goods/detail.vue
@@ -0,0 +1,130 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/uni-app/pages/goods/list.vue b/niucloud/addon/shop/uni-app/pages/goods/list.vue
new file mode 100644
index 000000000..9fad48edc
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/pages/goods/list.vue
@@ -0,0 +1,402 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 综合排序
+
+ 销量
+
+
+
+
+ 价格
+
+
+
+
+ 筛选
+
+
+
+
+
+
+
+
+ {{item.category_name}}
+
+
+ 全部
+
+
+ {{ subItem.category_name }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ item.goods_brand.brand_name }}
+ {{ item.goods_name }}
+
+
+ {{ item.sub_title }}
+
+
+
+
+
+ {{ tagItem.label_name }}
+
+
+
+
+
+
+ ¥
+ {{ diyGoods.goodsPrice(item).toFixed(2).split('.')[0] }}
+ .{{ diyGoods.goodsPrice(item).toFixed(2).split('.')[1] }}
+
+
+
+
+
+
+ 已售{{ item.sale_num }}{{ item.unit }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ item.goods_brand.brand_name }}
+ {{ item.goods_name }}
+
+
+ {{ item.sub_title }}
+
+
+
+
+ {{ tagItem.label_name }}
+
+
+
+
+
+ ¥
+ {{ diyGoods.goodsPrice(item).toFixed(2).split('.')[0] }}
+ .{{ diyGoods.goodsPrice(item).toFixed(2).split('.')[1] }}
+
+
+
+
+
+ 已售{{ item.sale_num }}{{ item.unit }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ item.goods_brand.brand_name }}
+
+ {{ item.goods_name }}
+
+
+ {{ item.sub_title }}
+
+
+
+
+
+ {{ tagItem.label_name }}
+
+
+
+
+
+
+ ¥
+ {{ diyGoods.goodsPrice(item).toFixed(2).split('.')[0] }}
+ .{{ diyGoods.goodsPrice(item).toFixed(2).split('.')[1] }}
+
+
+
+
+
+ 已售{{ item.sale_num }}{{ item.unit }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/uni-app/pages/goods/rank.vue b/niucloud/addon/shop/uni-app/pages/goods/rank.vue
new file mode 100644
index 000000000..87c6750f3
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/pages/goods/rank.vue
@@ -0,0 +1,343 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ item.name }}
+
+
+
+
+
+
+
+
+ {{ t('rankingRules') }}
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ index + 1 }}
+
+
+
+
+
+
+
+
+
+ {{ item.goods_brand.brand_name }}
+
+ {{ item.goods_name }}
+
+
+
+
+ {{ tagItem.label_name }}
+
+
+
+
+ ¥
+ {{ diyGoods.goodsPrice(item).toFixed(2).split('.')[0] }}
+ .{{ diyGoods.goodsPrice(item).toFixed(2).split('.')[1] }}
+
+
+
+
+ 去购买
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/uni-app/pages/goods/search.vue b/niucloud/addon/shop/uni-app/pages/goods/search.vue
new file mode 100644
index 000000000..864798f1e
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/pages/goods/search.vue
@@ -0,0 +1,274 @@
+
+
+
+
+
+
+
+
+ 搜索
+
+
+
+
+
+
+
+ 历史搜索
+
+
+
+
+
+ {{ item }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 热门搜索
+
+
+
+
+ {{ item }}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/uni-app/pages/index.vue b/niucloud/addon/shop/uni-app/pages/index.vue
new file mode 100644
index 000000000..6eff83bcd
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/pages/index.vue
@@ -0,0 +1,83 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/uni-app/pages/invoice/detail.vue b/niucloud/addon/shop/uni-app/pages/invoice/detail.vue
new file mode 100644
index 000000000..5c639a4f6
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/pages/invoice/detail.vue
@@ -0,0 +1,185 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/uni-app/pages/invoice/invoice.vue b/niucloud/addon/shop/uni-app/pages/invoice/invoice.vue
new file mode 100644
index 000000000..d3498d879
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/pages/invoice/invoice.vue
@@ -0,0 +1,275 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/uni-app/pages/invoice/invoice_edit.vue b/niucloud/addon/shop/uni-app/pages/invoice/invoice_edit.vue
new file mode 100644
index 000000000..a8dc15322
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/pages/invoice/invoice_edit.vue
@@ -0,0 +1,275 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/uni-app/pages/invoice/invoice_order.vue b/niucloud/addon/shop/uni-app/pages/invoice/invoice_order.vue
new file mode 100644
index 000000000..6f020b763
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/pages/invoice/invoice_order.vue
@@ -0,0 +1,89 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/niucloud/addon/shop/uni-app/pages/invoice/list.vue b/niucloud/addon/shop/uni-app/pages/invoice/list.vue
new file mode 100644
index 000000000..8beeecc92
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/pages/invoice/list.vue
@@ -0,0 +1,200 @@
+
+
+
+
+
+ {{ item.name }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/uni-app/pages/member/index.vue b/niucloud/addon/shop/uni-app/pages/member/index.vue
new file mode 100644
index 000000000..24cae019d
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/pages/member/index.vue
@@ -0,0 +1,88 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/uni-app/pages/member/my_coupon.vue b/niucloud/addon/shop/uni-app/pages/member/my_coupon.vue
new file mode 100644
index 000000000..d923ea767
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/pages/member/my_coupon.vue
@@ -0,0 +1,242 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/uni-app/pages/newcomer/list.vue b/niucloud/addon/shop/uni-app/pages/newcomer/list.vue
new file mode 100644
index 000000000..f2d31eb93
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/pages/newcomer/list.vue
@@ -0,0 +1,283 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ 活动规则
+
+
+
+
+
+
+
+
+ 活动规则
+
+
+
+ 距结束还有:
+
+
+
+ {{ timeData.days }}
+ 天
+
+
+ {{ timeData.hours >= 10 ? timeData.hours : '0' + timeData.hours }}
+ 00
+ 时
+
+
+ {{ timeData.minutes >= 10 ? timeData.minutes : '0' + timeData.minutes }}
+ 00
+ 分
+
+
+ {{ timeData.seconds < 10 ? '0' + timeData.seconds : timeData.seconds }}
+ 00
+ 秒
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ item.goods_name }}
+
+
+
+
+
+ 新人价
+ ¥
+ {{ parseFloat(item.goodsSku.newcomer_price).toFixed(2) }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/uni-app/pages/order/components/address-list/address-list.vue b/niucloud/addon/shop/uni-app/pages/order/components/address-list/address-list.vue
new file mode 100644
index 000000000..f5bb816dc
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/pages/order/components/address-list/address-list.vue
@@ -0,0 +1,121 @@
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/uni-app/pages/order/components/goods-detail/goods-detail.vue b/niucloud/addon/shop/uni-app/pages/order/components/goods-detail/goods-detail.vue
new file mode 100644
index 000000000..b97e9cbc4
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/pages/order/components/goods-detail/goods-detail.vue
@@ -0,0 +1,132 @@
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/uni-app/pages/order/components/invoice/invoice.vue b/niucloud/addon/shop/uni-app/pages/order/components/invoice/invoice.vue
new file mode 100644
index 000000000..4cb090e39
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/pages/order/components/invoice/invoice.vue
@@ -0,0 +1,210 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/uni-app/pages/order/components/logistics-tracking/logistics-tracking.vue b/niucloud/addon/shop/uni-app/pages/order/components/logistics-tracking/logistics-tracking.vue
new file mode 100644
index 000000000..f61bfc869
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/pages/order/components/logistics-tracking/logistics-tracking.vue
@@ -0,0 +1,121 @@
+
+
+
+
+ {{ t('detailedInformation') }}
+
+
+
+ {{ item.name }}
+
+
+
+
+
+
+ 无需物流
+
+
+ {{ showList.company.company_name }}
+
+ {{ showList.express_number }}
+ {{ t('copy') }}
+
+
+
+
+
+
+
+ 暂无物流信息~~
+
+
+
+
+
+
+
+
+
+
+
+
+ 无需物流~~
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/uni-app/pages/order/components/message-open/message-open.vue b/niucloud/addon/shop/uni-app/pages/order/components/message-open/message-open.vue
new file mode 100644
index 000000000..1fed3db51
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/pages/order/components/message-open/message-open.vue
@@ -0,0 +1,83 @@
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/uni-app/pages/order/components/select-coupon/select-coupon.vue b/niucloud/addon/shop/uni-app/pages/order/components/select-coupon/select-coupon.vue
new file mode 100644
index 000000000..d515c3752
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/pages/order/components/select-coupon/select-coupon.vue
@@ -0,0 +1,138 @@
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/uni-app/pages/order/components/select-store/select-store.vue b/niucloud/addon/shop/uni-app/pages/order/components/select-store/select-store.vue
new file mode 100644
index 000000000..a98b912f8
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/pages/order/components/select-store/select-store.vue
@@ -0,0 +1,145 @@
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/uni-app/pages/order/detail.vue b/niucloud/addon/shop/uni-app/pages/order/detail.vue
new file mode 100644
index 000000000..be2830532
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/pages/order/detail.vue
@@ -0,0 +1,853 @@
+
+
+
+
+
+
+
+
+
+
+
+ {{ detail.status_name.name }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('index') }}
+
+
+
+
+
+ 客服
+
+
+
+
+ {{ t('logisticsTracking') }}
+ {{ t('orderClose') }}
+ {{ t('topay') }}
+ {{ t('orderFinish') }}
+
+ {{ detail.is_evaluate == 1 ? t('selectedEvaluate') : t('evaluate') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/uni-app/pages/order/list.vue b/niucloud/addon/shop/uni-app/pages/order/list.vue
new file mode 100644
index 000000000..2aaaee90f
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/pages/order/list.vue
@@ -0,0 +1,508 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ item.name }}
+
+
+
+
+
+ 开发票
+
+
+
+
+
+
+
+
+
+
+ 已选
+ {{ checkedNum }}
+ 个订单
+
+
+
+
+
+ 全选
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/uni-app/pages/order/payment.vue b/niucloud/addon/shop/uni-app/pages/order/payment.vue
new file mode 100644
index 000000000..3a3f8dac8
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/pages/order/payment.vue
@@ -0,0 +1,858 @@
+
+
+
+
+
+
+
+
+
+
+ 合计:
+
+ ¥
+ {{ parseFloat(orderData.basic.order_money).toFixed(2).split('.')[0] }}
+ .{{ parseFloat(orderData.basic.order_money).toFixed(2).split('.')[1] }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/uni-app/pages/point/components/goods-sku.vue b/niucloud/addon/shop/uni-app/pages/point/components/goods-sku.vue
new file mode 100644
index 000000000..20c90761f
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/pages/point/components/goods-sku.vue
@@ -0,0 +1,324 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/uni-app/pages/point/detail.vue b/niucloud/addon/shop/uni-app/pages/point/detail.vue
new file mode 100644
index 000000000..faa59ab4b
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/pages/point/detail.vue
@@ -0,0 +1,682 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 视频
+
+ 图片
+ {{swiperCurrentIndex}}/{{goodsDetail?.goods?.goods_image?.length}}
+
+
+
+
+
+
+
+ {{ goodsDetail.point }}
+ {{ t('point') }}
+
+ +
+
+ {{ parseFloat(goodsDetail.price).toFixed(2) }}
+ {{ t('priceUnit') }}
+
+
+
+
+
+
+
+
+ {{ goodsDetail.goods.goods_brand.brand_name }}
+ {{ goodsDetail.goods.goods_name }}
+
+
+ {{goodsDetail.goods.sub_title}}
+
+
+
+
+
+ {{ item.label_name }}
+
+
+
+
+
+ 划线价:
+ ¥{{ goodsDetail.market_price }}
+
+
+ 库存:
+ {{ goodsDetail.stock }}
+ {{ goodsDetail.goods.unit }}
+
+
+ 销量:
+ {{ goodsDetail.goods.sale_num }}
+ {{ goodsDetail.goods.unit }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 首页
+
+
+
+
+ 分享
+
+
+
+
+
+
+
+ 客服
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/uni-app/pages/point/index.vue b/niucloud/addon/shop/uni-app/pages/point/index.vue
new file mode 100644
index 000000000..141be0949
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/pages/point/index.vue
@@ -0,0 +1,80 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/uni-app/pages/point/list.vue b/niucloud/addon/shop/uni-app/pages/point/list.vue
new file mode 100644
index 000000000..874f5b4a0
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/pages/point/list.vue
@@ -0,0 +1,236 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 综合排序
+
+ 销量
+
+
+
+
+ 价格
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/uni-app/pages/point/order_list.vue b/niucloud/addon/shop/uni-app/pages/point/order_list.vue
new file mode 100644
index 000000000..983d58e89
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/pages/point/order_list.vue
@@ -0,0 +1,291 @@
+
+
+
+
+
+ {{ item.name }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/uni-app/pages/point/payment.vue b/niucloud/addon/shop/uni-app/pages/point/payment.vue
new file mode 100644
index 000000000..a46b36fd4
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/pages/point/payment.vue
@@ -0,0 +1,661 @@
+
+
+
+
+
+
+
+
+
+
+ 合计:
+
+ {{ orderData.basic.point_sum }}
+ 积分
+
+
+ +
+
+ {{ parseFloat(orderData.basic.order_money).toFixed(2) }}
+ 元
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/uni-app/pages/refund/apply.vue b/niucloud/addon/shop/uni-app/pages/refund/apply.vue
new file mode 100644
index 000000000..442c36042
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/pages/refund/apply.vue
@@ -0,0 +1,295 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/uni-app/pages/refund/detail.vue b/niucloud/addon/shop/uni-app/pages/refund/detail.vue
new file mode 100644
index 000000000..f0d324dc1
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/pages/refund/detail.vue
@@ -0,0 +1,416 @@
+
+
+
+
+
+
+
+
+
+ {{ detail.status_name }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('index') }}
+
+
+
+
+
+ 客服
+
+
+
+
+ {{ t('refundApply') }}
+ 编辑退款信息
+ 填写发货物流
+ 编辑发货物流
+
+
+
+
+
+
+
+
+
+ {{ detail.status_name }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/uni-app/pages/refund/edit_apply.vue b/niucloud/addon/shop/uni-app/pages/refund/edit_apply.vue
new file mode 100644
index 000000000..0ca8a9fa0
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/pages/refund/edit_apply.vue
@@ -0,0 +1,284 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/uni-app/pages/refund/list.vue b/niucloud/addon/shop/uni-app/pages/refund/list.vue
new file mode 100644
index 000000000..45577a34c
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/pages/refund/list.vue
@@ -0,0 +1,178 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/uni-app/pages/refund/log.vue b/niucloud/addon/shop/uni-app/pages/refund/log.vue
new file mode 100644
index 000000000..07f0a6d7b
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/pages/refund/log.vue
@@ -0,0 +1,64 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/niucloud/addon/shop/uni-app/stores/cart.ts b/niucloud/addon/shop/uni-app/stores/cart.ts
new file mode 100644
index 000000000..330d3b20f
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/stores/cart.ts
@@ -0,0 +1,211 @@
+import { defineStore } from 'pinia'
+import { t } from '@/locale'
+import { redirect, getToken } from '@/utils/common'
+import { addCart, editCart, deleteCart, getCartList } from '@/addon/shop/api/cart';
+
+interface Cart {
+ cartList: AnyObject
+ totalNum: number
+ totalMoney: number
+ isRepeat: boolean
+ isAddCartRecommend: boolean // 是否添加购物车推荐
+}
+
+const useCartStore = defineStore('cart', {
+ state: (): Cart => {
+ return {
+ cartList: {}, // 购物车列表
+ totalNum: 0, // 购物车商品总数量
+ totalMoney: 0, // 购物车商品总价格
+ isRepeat: false,
+ isAddCartRecommend: false
+ }
+ },
+ actions: {
+ // 查询购物车列表
+ getList(callback: any = null) {
+ if (!getToken()) {
+ // 每次查询清空
+ for (let k in this.cartList) {
+ delete this.cartList[k];
+ }
+ this.totalNum = 0;
+ this.totalMoney = 0;
+ return;
+ }
+ getCartList({}).then((res: any) => {
+ let data = res.data;
+
+ // 每次查询清空
+ for (let k in this.cartList) {
+ delete this.cartList[k];
+ }
+ if (data) {
+ data.forEach((item: any) => {
+ if (item.goods.status == 1 && item.goods.delete_time == 0 && item.goodsSku) {
+ let cart: any = {
+ id: item.id,
+ goods_id: item.goods_id,
+ sku_id: item.sku_id,
+ stock: item.goodsSku.stock,
+ num: item.num,
+ sale_price: item.goodsSku.show_price
+ };
+
+ // if (item.goods.member_discount && getToken() && item.goodsSku.member_price != item.goodsSku.price) {
+ // cart.sale_price = item.goodsSku.member_price ? item.goodsSku.member_price : item.goodsSku.price // 会员价
+ // }
+
+ // todo sale_price 改成 price
+
+ if (!this.cartList['goods_' + cart.goods_id]) {
+ this.cartList['goods_' + cart.goods_id] = {};
+ }
+ this.cartList['goods_' + cart.goods_id]['sku_' + cart.sku_id] = cart;
+ }
+ })
+ }
+ this.calculateNum();
+ if (callback && typeof callback == 'function') callback();
+ })
+ },
+ /**
+ * 购物车数量增加
+ * data:数据源
+ * step:记步数量,默认为:1,每次加一个,设置为:0时,按照 num 修改
+ */
+ increase(data: any, step = 1, callback: any = null) {
+ if (!data || (data && Object.keys(data).length == 0) || !data.goods_id || !data.sku_id) return;
+ if (!getToken()) return;
+
+ let num = data.num || 0; // 当前数量
+ let updateNum = num + step; // 变更数量
+
+ let api = data.id ? editCart : addCart;
+
+ if (updateNum > parseInt(data.stock)) {
+ uni.showToast({ title: '商品库存不足', icon: 'none' })
+ return;
+ }
+
+ if (this.isRepeat) return;
+ this.isRepeat = true;
+
+ // 更新存储数据
+ if (data.id) {
+ this.cartList['goods_' + data.goods_id]['sku_' + data.sku_id].num = updateNum;
+ } else {
+
+ // 如果商品第一次添加,则初始化数据
+ if (!this.cartList['goods_' + data.goods_id]) {
+ this.cartList['goods_' + data.goods_id] = {};
+ }
+ this.cartList['goods_' + data.goods_id]['sku_' + data.sku_id] = {
+ id: data.id,
+ goods_id: data.goods_id,
+ sku_id: data.sku_id,
+ stock: data.stock,
+ num: updateNum,
+ sale_price: data.sale_price
+ };
+ }
+
+ this.calculateNum();
+
+ api({
+ id: data.id,
+ goods_id: data.goods_id,
+ sku_id: data.sku_id,
+ num: updateNum
+ }).then(res => {
+ this.getList(callback)
+ this.isRepeat = false;
+ }).catch(res => {
+ this.isRepeat = false;
+ })
+
+ },
+ /**
+ * 购物车数量减少
+ * data:数据源
+ * step:记步数量,默认为:1,每次减一个,设置为:0时,按照 num 修改
+ */
+ reduce(data: any, step = 1, callback: any = null) {
+ if (!data || (data && Object.keys(data).length == 0) || !data.goods_id || !data.sku_id) return;
+ if (!getToken()) return;
+
+ let num = data.num || 0; // 当前数量
+ let updateNum = num - step; // 变更数量
+
+ let api = updateNum > 0 ? editCart : deleteCart;
+
+ if (this.isRepeat) return;
+ this.isRepeat = true;
+
+ // 更新存储数据
+ if (updateNum > 0) {
+ this.cartList['goods_' + data.goods_id]['sku_' + data.sku_id].num = updateNum;
+ } else {
+ delete this.cartList['goods_' + data.goods_id]['sku_' + data.sku_id];
+ if (Object.keys(this.cartList['goods_' + data.goods_id]).length == 0) delete this.cartList['goods_' + data.goods_id];
+ }
+
+ this.calculateNum();
+
+ api({
+ ids: data.id, // 删除接口用
+ id: data.id,
+ goods_id: data.goods_id,
+ sku_id: data.sku_id,
+ num: updateNum
+ }).then(res => {
+ this.getList(callback);
+ this.isRepeat = false;
+ }).catch(res => {
+ this.isRepeat = false;
+ })
+ },
+ // 购物车删除
+ delete(ids: any, callback: any = null) {
+ if (!ids) return;
+
+ deleteCart({
+ ids
+ }).then(res => {
+ this.getList();
+ this.isRepeat = false;
+ if (callback) callback();
+ }).catch(res => {
+ this.isRepeat = false;
+ })
+ },
+
+ // 计算购物车商品的总数量、总价格
+ calculateNum() {
+ this.totalNum = 0;
+ this.totalMoney = 0;
+
+ if (Object.keys(this.cartList).length) {
+ for (let goods in this.cartList) {
+ let totalNum = 0;
+ let totalMoney = 0;
+ for (let sku in this.cartList[goods]) {
+ if (typeof this.cartList[goods][sku] == 'object') {
+ totalNum += this.cartList[goods][sku].num;
+ totalMoney += this.cartList[goods][sku].num * this.cartList[goods][sku].sale_price;
+ }
+ }
+ this.cartList[goods].totalNum = totalNum;
+ this.cartList[goods].totalMoney = totalMoney.toFixed(2);
+
+ this.totalNum += totalNum;
+ this.totalMoney += totalMoney;
+
+ }
+ }
+ this.totalMoney = this.totalMoney.toFixed(2);
+ }
+ }
+})
+
+export default useCartStore
diff --git a/niucloud/addon/shop/uni-app/stores/goodsDetail.ts b/niucloud/addon/shop/uni-app/stores/goodsDetail.ts
new file mode 100644
index 000000000..64aa22017
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/stores/goodsDetail.ts
@@ -0,0 +1,29 @@
+import { defineStore } from 'pinia'
+import { t } from '@/locale'
+import { redirect, getToken } from '@/utils/common'
+
+interface GoodsDetail {
+ goodsDetail: AnyObject
+}
+
+const useGoodsDetailStore = defineStore('goodsDetail', {
+ state: (): GoodsDetail => {
+ return {
+ goodsDetail: {}
+ }
+ },
+ actions: {
+ setGoodsDetail(data: any, isAllUpdate:Boolean = false) { // 商品详情
+ if(isAllUpdate){
+ this.goodsDetail = data;
+ }else{
+ Object.assign(this.goodsDetail, data);
+ }
+ },
+ removeGoodsDetail(){ // 商品详情
+ this.goodsDetail = {}
+ }
+ }
+})
+
+export default useGoodsDetailStore
diff --git a/niucloud/addon/shop/uni-app/styles/common.scss b/niucloud/addon/shop/uni-app/styles/common.scss
new file mode 100644
index 000000000..cc2af0ec1
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/styles/common.scss
@@ -0,0 +1,74 @@
+.remove-border {
+ &::after {
+ border: none;
+ }
+}
+
+/******************** 商品列表 state **********************/
+.brand-tag {
+ position: relative;
+ top: -2rpx;
+ display: inline;
+ line-height: 38rpx;
+ padding: 4rpx 8rpx;
+ border-radius: 4rpx;
+ margin-right: 8rpx;
+ background: red;
+ vertical-align: middle;
+ font-size: 18rpx;
+ color: #fff;
+ border: 2rpx solid transparent;
+
+ &.middle {
+ padding: 4rpx 8rpx;
+ border-radius: 8rpx;
+ font-size: 20rpx;
+ margin-right: 6rpx;
+ }
+}
+
+.base-tag {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ height: 34rpx;
+ font-size: 18rpx;
+ padding: 0 8rpx;
+ color: #333;
+ border-radius: 4rpx;
+ background-color: #fff;
+ margin-right: 8rpx;
+ box-sizing: border-box;
+ margin-top: 8rpx;
+ border: 2rpx solid transparent;
+
+ &.middle {
+ height: 40rpx;
+ padding: 0 12rpx;
+ border-radius: 8rpx;
+ font-size: 20rpx;
+ margin-right: 16rpx;
+ }
+}
+
+.img-tag {
+ display: block;
+ height: 34rpx;
+ width: auto;
+ border-radius: 4rpx;
+ margin-right: 14rpx;
+ box-sizing: border-box;
+ margin-top: 8rpx;
+
+ &.middle {
+ height: 38rpx;
+ border-radius: 8rpx;
+ margin-right: 16rpx;
+ }
+}
+
+/******************** 商品列表 end **********************/
+// 购物车按钮背景颜色
+.cart-btn-bg{
+ background: linear-gradient(127deg, var(--primary-help-color1) 0%, var(--primary-help-color5) 100%);
+}
diff --git a/niucloud/addon/shop/uni-app/utils/map/openMap.js b/niucloud/addon/shop/uni-app/utils/map/openMap.js
new file mode 100644
index 000000000..4d3c80610
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/utils/map/openMap.js
@@ -0,0 +1,111 @@
+import TransformCoordinate from './transformCoordinate.js'
+import useConfigStore from "@/stores/config";
+import useSystemStore from "../../../../stores/system";
+
+function openMapByDefault(latitude, longitude, name) {
+ uni.openLocation({
+ latitude: latitude,
+ longitude: longitude,
+ name: name,
+ fail: (e) => {
+ uni.showModal({
+ content: '打开地图失败,请稍后重试',
+ confirmColor: useConfigStore().themeColor['--primary-color'],
+ })
+ },
+ })
+}
+
+function openMapByAndroid(latitude, longitude, name) {
+ let url = ''; // 回调地址
+ let identity = ''; // 程序名称
+ if (plus.runtime.isApplicationExist({
+ pname: 'com.baidu.BaiduMap'
+ })) { // baidumap
+ url = `baidumap://map/marker?location=${latitude},${longitude}&title=${name}&coord_type=gcj02&src=andr.baidu.openAPIdemo`
+ identity = 'com.baidu.BaiduMap'
+ openURL(url, identity)
+ } else if (plus.runtime.isApplicationExist({
+ pname: 'com.autonavi.minimap'
+ })) { // 高德
+ url = `androidamap://viewMap?sourceApplication=appname&poiname=${name}&lat=${latitude}&lon=${longitude}&dev=0`
+ identity = 'com.autonavi.minimap'
+ openURL(url, identity)
+ } else {
+ openMapByDefault(latitude, longitude, name)
+ }
+}
+
+function openMapByIos(latitude, longitude, name) {
+ let url = ''; // 回调地址
+ let errorCB = ''; // url失败的回调地址
+ let identity = ''; // 程序名称
+
+ if (plus.runtime.isApplicationExist({
+ action: 'baidumap://'
+ })) { // baidumap
+ url =
+ `baidumap://map/marker?location=${latitude},${longitude}&title=${name}&content=${name}&src=ios.baidu.openAPIdemo&coord_type=gcj02`;
+ openURL(url, identity)
+ } else if (plus.runtime.isApplicationExist({
+ action: 'iosamap://'
+ })) { // 高德
+ url = `iosamap://viewMap?sourceApplication=applicationName&poiname=${name}&lat=${latitude}&lon=${longitude}&dev=0`
+ openURL(url, identity)
+ } else {
+ openMapByDefault(latitude, longitude, name)
+ }
+}
+
+function openURL(url, identity) {
+ let newurl = encodeURI(url);
+ plus.runtime.openURL(newurl, function(res) {
+ uni.showModal({
+ content: res.message,
+ confirmColor: useConfigStore().themeColor['--primary-color'],
+ })
+ }, identity);
+}
+
+function getCoordByType(longitude, latitude, coord_type) {
+ switch (coord_type) {
+ case 'gcj02':
+ return [longitude, latitude]
+ break;
+ case 'bd09':
+ return TransformCoordinate.bd09togcj02(longitude, latitude)
+ break;
+ case 'wgs84':
+ return TransformCoordinate.wgs84togcj02(longitude, latitude)
+ break;
+ default:
+ return [longitude, latitude]
+ break;
+ }
+}
+export default {
+ /* 打开地图 */
+ openMap(latitude, longitude, name, coord_type = 'gcj02') {
+ let arr = getCoordByType(longitude, latitude, coord_type)
+ // #ifdef APP-PLUS
+ const systemStore = useSystemStore()
+ switch (systemStore.systemInfo.platform) {
+ case 'android':
+ // console.log('运行Android上')
+ openMapByAndroid(arr[1], arr[0], name)
+ break;
+ case 'ios':
+ // console.log('运行iOS上')
+ openMapByIos(arr[1], arr[0], name)
+ break;
+ default:
+ openMapByDefault(arr[1], arr[0], name)
+ // console.log('运行在开发者工具上')
+ break;
+ }
+ // #endif
+ // #ifndef APP-PLUS
+ openMapByDefault(arr[1], arr[0], name)
+ // #endif
+ }
+}
diff --git a/niucloud/addon/shop/uni-app/utils/map/transformCoordinate.js b/niucloud/addon/shop/uni-app/utils/map/transformCoordinate.js
new file mode 100644
index 000000000..c844ca1fd
--- /dev/null
+++ b/niucloud/addon/shop/uni-app/utils/map/transformCoordinate.js
@@ -0,0 +1,122 @@
+/**
+ * Created by Wandergis on 2015/7/8.
+ * 提供了百度坐标(BD09)、国测局坐标(火星坐标,GCJ02)、和WGS84坐标系之间的转换
+ */
+const x_PI = 3.14159265358979324 * 3000.0 / 180.0;
+const PI = 3.1415926535897932384626;
+const a = 6378245.0;
+const ee = 0.00669342162296594323;
+
+/**
+ * 百度坐标系 (BD-09) 与 火星坐标系 (GCJ-02)的转换
+ * 即 百度 转 谷歌、高德
+ * @param bd_lon
+ * @param bd_lat
+ * @returns {*[]}
+ */
+function bd09togcj02(bd_lon, bd_lat) {
+ const x_pi = 3.14159265358979324 * 3000.0 / 180.0;
+ const x = bd_lon - 0.0065;
+ const y = bd_lat - 0.006;
+ const z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * x_pi);
+ const theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * x_pi);
+ const gg_lng = z * Math.cos(theta);
+ const gg_lat = z * Math.sin(theta);
+ return [gg_lng, gg_lat]
+}
+
+/**
+ * 火星坐标系 (GCJ-02) 与百度坐标系 (BD-09) 的转换
+ * 即谷歌、高德 转 百度
+ * @param lng
+ * @param lat
+ * @returns {*[]}
+ */
+function gcj02tobd09(lng, lat) {
+ const z = Math.sqrt(lng * lng + lat * lat) + 0.00002 * Math.sin(lat * x_PI);
+ const theta = Math.atan2(lat, lng) + 0.000003 * Math.cos(lng * x_PI);
+ const bd_lng = z * Math.cos(theta) + 0.0065;
+ const bd_lat = z * Math.sin(theta) + 0.006;
+ return [bd_lng, bd_lat]
+}
+
+/**
+ * WGS84转GCj02
+ * @param lng
+ * @param lat
+ * @returns {*[]}
+ */
+function wgs84togcj02(lng, lat) {
+ if (out_of_china(lng, lat)) {
+ return [lng, lat]
+ } else {
+ let dlat = transformlat(lng - 105.0, lat - 35.0);
+ let dlng = transformlng(lng - 105.0, lat - 35.0);
+ const radlat = lat / 180.0 * PI;
+ let magic = Math.sin(radlat);
+ magic = 1 - ee * magic * magic;
+ const sqrtmagic = Math.sqrt(magic);
+ dlat = (dlat * 180.0) / ((a * (1 - ee)) / (magic * sqrtmagic) * PI);
+ dlng = (dlng * 180.0) / (a / sqrtmagic * Math.cos(radlat) * PI);
+ const mglat = lat + dlat;
+ const mglng = lng + dlng;
+ return [mglng, mglat]
+ }
+}
+
+/**
+ * GCJ02 转换为 WGS84
+ * @param lng
+ * @param lat
+ * @returns {*[]}
+ */
+function gcj02towgs84(lng, lat) {
+ if (out_of_china(lng, lat)) {
+ return [lng, lat]
+ } else {
+ let dlat = transformlat(lng - 105.0, lat - 35.0);
+ let dlng = transformlng(lng - 105.0, lat - 35.0);
+ const radlat = lat / 180.0 * PI;
+ let magic = Math.sin(radlat);
+ magic = 1 - ee * magic * magic;
+ const sqrtmagic = Math.sqrt(magic);
+ dlat = (dlat * 180.0) / ((a * (1 - ee)) / (magic * sqrtmagic) * PI);
+ dlng = (dlng * 180.0) / (a / sqrtmagic * Math.cos(radlat) * PI);
+ const mglat = lat + dlat;
+ const mglng = lng + dlng;
+ return [lng * 2 - mglng, lat * 2 - mglat]
+ }
+}
+
+function transformlat(lng, lat) {
+ let ret = -100.0 + 2.0 * lng + 3.0 * lat + 0.2 * lat * lat + 0.1 * lng * lat + 0.2 * Math.sqrt(Math.abs(lng));
+ ret += (20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) * 2.0 / 3.0;
+ ret += (20.0 * Math.sin(lat * PI) + 40.0 * Math.sin(lat / 3.0 * PI)) * 2.0 / 3.0;
+ ret += (160.0 * Math.sin(lat / 12.0 * PI) + 320 * Math.sin(lat * PI / 30.0)) * 2.0 / 3.0;
+ return ret
+}
+
+function transformlng(lng, lat) {
+ let ret = 300.0 + lng + 2.0 * lat + 0.1 * lng * lng + 0.1 * lng * lat + 0.1 * Math.sqrt(Math.abs(lng));
+ ret += (20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) * 2.0 / 3.0;
+ ret += (20.0 * Math.sin(lng * PI) + 40.0 * Math.sin(lng / 3.0 * PI)) * 2.0 / 3.0;
+ ret += (150.0 * Math.sin(lng / 12.0 * PI) + 300.0 * Math.sin(lng / 30.0 * PI)) * 2.0 / 3.0;
+ return ret
+}
+
+/**
+ * 判断是否在国内,不在国内则不做偏移
+ * @param lng
+ * @param lat
+ * @returns {boolean}
+ */
+function out_of_china(lng, lat) {
+ return (lng < 72.004 || lng > 137.8347) || ((lat < 0.8293 || lat > 55.8271) || false);
+}
+
+export default {
+ bd09togcj02: bd09togcj02, // 百度坐标系 (BD-09) 与 火星坐标系 (GCJ-02)的转换
+ gcj02tobd09: gcj02tobd09, // 火星坐标系 (GCJ-02) 与百度坐标系 (BD-09) 的转换
+ wgs84togcj02: wgs84togcj02, //
+ gcj02towgs84: gcj02towgs84,
+}