Parcourir la source

Merge branch 'v5.1.0dev' of https://gitee.com/ZhongBangKeJi/CRMEB into v5.1.0dev

liaofei il y a 2 ans
Parent
commit
edb3797171
65 fichiers modifiés avec 5343 ajouts et 3833 suppressions
  1. 1 1
      crmeb/app/adminapi/controller/v1/order/StoreOrder.php
  2. 2 1
      crmeb/app/adminapi/controller/v1/product/StoreProductReply.php
  3. 6 2
      crmeb/app/adminapi/controller/v1/setting/SystemStorage.php
  4. 1 1
      crmeb/app/dao/product/product/StoreProductDao.php
  5. 10 0
      crmeb/app/model/user/UserRecharge.php
  6. 6 6
      crmeb/app/services/activity/combination/StorePinkServices.php
  7. 7 1
      crmeb/app/services/activity/coupon/StoreCouponIssueServices.php
  8. 1 1
      crmeb/app/services/activity/lottery/LuckLotteryRecordServices.php
  9. 13 9
      crmeb/app/services/order/StoreOrderRefundServices.php
  10. 2 1
      crmeb/app/services/other/UploadService.php
  11. 5 5
      crmeb/app/services/product/product/StoreCategoryServices.php
  12. 4 2
      crmeb/app/services/product/product/StoreProductReplyServices.php
  13. 10 1
      crmeb/app/services/product/product/StoreProductServices.php
  14. 1 1
      crmeb/app/services/shipping/ExpressServices.php
  15. 1 1
      crmeb/app/services/statistic/TradeStatisticServices.php
  16. 73 6
      crmeb/app/services/system/config/SystemStorageServices.php
  17. 10 2
      crmeb/app/services/user/UserBrokerageServices.php
  18. 1 0
      crmeb/crmeb/services/upload/Upload.php
  19. 125 13
      crmeb/crmeb/services/upload/extend/obs/Client.php
  20. 6 36
      crmeb/crmeb/services/upload/storage/Jdoss.php
  21. 317 0
      crmeb/crmeb/services/upload/storage/Obs.php
  22. 445 0
      crmeb/crmeb/services/upload/storage/Tyoss.php
  23. 1089 1089
      crmeb/public/install/crmeb.sql
  24. 13 0
      template/admin/src/api/product.js
  25. 38 19
      template/admin/src/components/linkaddress/index.vue
  26. 97 1
      template/admin/src/pages/order/orderList/handle/orderDetails.vue
  27. 236 0
      template/admin/src/pages/product/components/addReply.vue
  28. 10 7
      template/admin/src/pages/product/productAdd/index.vue
  29. 186 1
      template/admin/src/pages/product/productReply/index.vue
  30. 1 1
      template/admin/src/pages/setting/devise/diyIndex.vue
  31. 17 2
      template/admin/src/pages/setting/storage/index.vue
  32. 4 18
      template/uni-app/components/guide/index.vue
  33. 1 1
      template/uni-app/components/orderGoods/index.vue
  34. 3 3
      template/uni-app/components/recommend/index.vue
  35. 366 383
      template/uni-app/pages/activity/goods_combination/index.vue
  36. 25 4
      template/uni-app/pages/activity/goods_combination_status/index.vue
  37. 1 1
      template/uni-app/pages/activity/goods_seckill/index.vue
  38. 495 463
      template/uni-app/pages/activity/presell/index.vue
  39. 178 193
      template/uni-app/pages/columnGoods/HotNewGoods/index.vue
  40. 1 1
      template/uni-app/pages/goods/goods_list/index.vue
  41. 60 1
      template/uni-app/pages/goods/order_confirm/index.vue
  42. 39 15
      template/uni-app/pages/goods/order_details/index.vue
  43. 29 19
      template/uni-app/pages/goods/order_list/index.vue
  44. 11 0
      template/uni-app/pages/goods_cate/goods_cate1.vue
  45. 1 10
      template/uni-app/pages/index/diy/components/activeParty.vue
  46. 240 252
      template/uni-app/pages/index/diy/components/menus.vue
  47. 133 137
      template/uni-app/pages/index/diy/components/news.vue
  48. 310 330
      template/uni-app/pages/index/diy/components/pictureCube.vue
  49. 1 21
      template/uni-app/pages/index/diy/components/swiperBg.vue
  50. 74 66
      template/uni-app/pages/index/diy/components/titles.vue
  51. 1 1
      template/uni-app/pages/index/index.vue
  52. 1 18
      template/uni-app/pages/index/visualization/components/activity.vue
  53. 1 19
      template/uni-app/pages/index/visualization/components/mBanner.vue
  54. 1 20
      template/uni-app/pages/index/visualization/components/menus.vue
  55. 1 3
      template/uni-app/pages/index/visualization/components/newGoods.vue
  56. 174 190
      template/uni-app/pages/index/visualization/components/news.vue
  57. 4 6
      template/uni-app/pages/index/visualization/components/popular.vue
  58. 1 3
      template/uni-app/pages/index/visualization/components/promotion.vue
  59. 1 27
      template/uni-app/pages/index/visualization/components/swiperBg.vue
  60. 1 1
      template/uni-app/pages/order_addcart/order_addcart.vue
  61. 395 410
      template/uni-app/pages/points_mall/index.vue
  62. 3 0
      template/uni-app/pages/users/user_spread_money/index.vue
  63. 1 1
      template/uni-app/pages/users/wechat_login/index.vue
  64. 1 1
      template/uni-app/static/css/style.scss
  65. 51 5
      template/uni-app/utils/util.js

+ 1 - 1
crmeb/app/adminapi/controller/v1/order/StoreOrder.php

@@ -465,7 +465,7 @@ class StoreOrder extends AuthController
      */
     public function order_info($id)
     {
-        if (!$id || !($orderInfo = $this->services->get($id, [], ['refund']))) {
+        if (!$id || !($orderInfo = $this->services->get($id, [], ['refund','invoice']))) {
             return app('json')->fail(400118);
         }
         /** @var UserServices $services */

+ 2 - 1
crmeb/app/adminapi/controller/v1/product/StoreProductReply.php

@@ -100,7 +100,8 @@ class StoreProductReply extends AuthController
             ['product_score', 0],
             ['service_score', 0],
             ['product_id', 0],
-            ['add_time', 0]
+            ['add_time', 0],
+            ['suk', ''],
         ]);
         if (!$data['product_id']) {
             $data['product_id'] = $data['image']['product_id'] ?? '';

+ 6 - 2
crmeb/app/adminapi/controller/v1/setting/SystemStorage.php

@@ -166,7 +166,10 @@ class SystemStorage extends AuthController
         //设置跨域规则
         try {
             $upload = UploadService::init($info->type);
-            $upload->setBucketCors($info->name, $info->region);
+            $res = $upload->setBucketCors($info->name, $info->region);
+            if (false === $res) {
+                return app('json')->fail($upload->getError());
+            }
         } catch (\Throwable $e) {
         }
 
@@ -199,6 +202,7 @@ class SystemStorage extends AuthController
     public function updateDomain($id)
     {
         $domain = $this->request->post('domain', '');
+        $cdn = $this->request->post('cdn', '');
         $data = $this->request->postMore([
             ['pri', ''],
             ['ca', '']
@@ -214,7 +218,7 @@ class SystemStorage extends AuthController
 //            return app('json')->fail('域名为HTTPS访问时,必须填写证书');
 //        }
 
-        $this->services->updateDomain($id, $domain);
+        $this->services->updateDomain($id, $domain, ['cdn' => $cdn]);
 
         return app('json')->success(100001);
     }

+ 1 - 1
crmeb/app/dao/product/product/StoreProductDao.php

@@ -122,7 +122,7 @@ class StoreProductDao extends BaseDao
         })->when(isset($where['cid']) && $where['cid'], function ($query) use ($where) {
             $query->whereIn('id', function ($query) use ($where) {
                 $query->name('store_product_cate')->whereIn('cate_id', function ($query) use ($where) {
-                    $query->name('store_category')->where('pid', $where['cid'])->field('id')->select();
+                    $query->name('store_category')->where('pid', $where['cid'])->whereOr('id', $where['cid'])->field('id')->select();
                 })->field('product_id')->select();
             });
         })->when(isset($where['coupon_category_id']) && $where['coupon_category_id'] != '', function ($query) use ($where) {

+ 10 - 0
crmeb/app/model/user/UserRecharge.php

@@ -87,6 +87,16 @@ class UserRecharge extends BaseModel
         $query->where('recharge_type', $value);
     }
 
+    /**
+     * 不等于充值类型
+     * @param Model $query
+     * @param $value
+     */
+    public function searchNoRechargeTypeAttr($query, $value)
+    {
+        $query->where('recharge_type', '<>', $value);
+    }
+
     /**退款金额
      * @param $query
      * @param $value

+ 6 - 6
crmeb/app/services/activity/combination/StorePinkServices.php

@@ -97,7 +97,7 @@ class StorePinkServices extends BaseServices
      */
     public function getPinkMember(int $id)
     {
-        return $this->dao->getList(['k_id' => $id, 'is_refund' => 0]);
+        return $this->dao->getList(['k_id' => $id]);
     }
 
     /**
@@ -130,15 +130,15 @@ class StorePinkServices extends BaseServices
                 $res11 = $this->dao->update($id, ['k_id' => $kCount['id']], 'k_id');
                 $res12 = $this->dao->update($kCount['id'], ['stop_time' => $count['add_time'] + 86400, 'k_id' => 0]);
                 $res1 = $res11 && $res12;
-                $res2 = $this->dao->update($id, ['stop_time' => time() - 1, 'k_id' => 0, 'is_refund' => $kCount['id'], 'status' => 3]);
+                $res2 = $this->dao->update($id, ['stop_time' => time() - 1, 'k_id' => $kCount['id'], 'is_refund' => $kCount['id'], 'status' => 3]);
             } else {
                 $res1 = true;
-                $res2 = $this->dao->update($id, ['stop_time' => time() - 1, 'k_id' => 0, 'is_refund' => $id, 'status' => 3]);
+                $res2 = $this->dao->update($id, ['stop_time' => time() - 1, 'is_refund' => $id, 'status' => 3]);
             }
             //修改结束时间为前一秒  团长ID为0
             $res = $res1 && $res2;
         } else if ($countY) {//团员
-            $res = $this->dao->update($countY['id'], ['stop_time' => time() - 1, 'k_id' => 0, 'is_refund' => $id, 'status' => 3]);
+            $res = $this->dao->update($countY['id'], ['stop_time' => time() - 1, 'is_refund' => $id, 'status' => 3]);
         }
         return $res;
     }
@@ -221,10 +221,10 @@ class StorePinkServices extends BaseServices
     {
         //查找拼团团员和团长
         if ($pink['k_id']) {
-            $pinkAll = $this->dao->getPinkUserList(['k_id' => $pink['k_id'], 'is_refund' => 0]);
+            $pinkAll = $this->dao->getPinkUserList(['k_id' => $pink['k_id']]);
             $pinkT = $this->dao->getPinkUserOne($pink['k_id']);
         } else {
-            $pinkAll = $this->dao->getPinkUserList(['k_id' => $pink['id'], 'is_refund' => 0]);
+            $pinkAll = $this->dao->getPinkUserList(['k_id' => $pink['id']]);
             $pinkT = $pink;
         }
         $count = count($pinkAll) + 1;

+ 7 - 1
crmeb/app/services/activity/coupon/StoreCouponIssueServices.php

@@ -23,6 +23,7 @@ use app\services\user\UserServices;
 use crmeb\exceptions\AdminException;
 use crmeb\exceptions\ApiException;
 use crmeb\services\FormBuilder;
+use think\facade\Db;
 
 /**
  *
@@ -64,6 +65,7 @@ class StoreCouponIssueServices extends BaseServices
         foreach ($list as &$item) {
             $item['use_time'] = date('Y-m-d', $item['start_use_time']) . ' ~ ' . date('Y-m-d', $item['end_use_time']);
         }
+        unset($where['type'], $where['receive_type']);
         $count = $this->dao->count($where);
         return compact('list', 'count');
     }
@@ -372,9 +374,13 @@ class StoreCouponIssueServices extends BaseServices
         $issueUserService = app()->make(StoreCouponIssueUserServices::class);
         /** @var StoreCouponUserServices $couponUserService */
         $couponUserService = app()->make(StoreCouponUserServices::class);
-        $this->transaction(function () use ($issueUserService, $uid, $id, $couponUserService, $issueCouponInfo) {
+        $this->transaction(function () use ($issueUserService, $uid, $id, $couponUserService, $issueCouponInfo, $is_receive) {
             $issueUserService->save(['uid' => $uid, 'issue_coupon_id' => $id, 'add_time' => time()]);
             $couponUserService->addUserCoupon($uid, $issueCouponInfo, "send");
+            if ($issueCouponInfo['total_count'] > 0 && $is_receive) {
+                $issueCouponInfo['remain_count'] -= 1;
+                $issueCouponInfo->save();
+            }
         });
     }
 

+ 1 - 1
crmeb/app/services/activity/lottery/LuckLotteryRecordServices.php

@@ -212,7 +212,7 @@ class LuckLotteryRecordServices extends BaseServices
                     /** @var StoreCouponIssueServices $couponIssueService */
                     $couponIssueService = app()->make(StoreCouponIssueServices::class);
                     try {
-                        $couponIssueService->issueUserCoupon($prize['coupon_id'], $userInfo, true);
+                        $couponIssueService->issueUserCoupon($prize['coupon_id'], $userInfo);
                     } catch (\Throwable $e) {
                         Log::error('抽奖领取优惠券失败,原因:' . $e->getMessage());
                     }

+ 13 - 9
crmeb/app/services/order/StoreOrderRefundServices.php

@@ -434,18 +434,22 @@ class StoreOrderRefundServices extends BaseServices
         /** @var StoreOrderStatusServices $statusService */
         $statusService = app()->make(StoreOrderStatusServices::class);
         $res = true;
-        //取消的订单退回优惠券
-        if ($type == 'cancel' && $order['coupon_id'] && $order['coupon_price']) {
+        //取消或者退款的订单退回优惠券
+        if ($order['coupon_id'] && $order['coupon_price']) {
             /** @var StoreCouponUserServices $couponUserServices */
             $couponUserServices = app()->make(StoreCouponUserServices::class);
-            $res = $couponUserServices->recoverCoupon((int)$order['coupon_id']);
-            $statusService->save([
-                'oid' => $order['id'],
-                'change_type' => 'coupon_back',
-                'change_message' => '商品退优惠券',
-                'change_time' => time()
-            ]);
+            //未支付取消订单,或者退优惠券开关打开之后的主订单以及最后一个子订单退还优惠券
+            if ($type == 'cancel' || (sys_config('coupon_return_open', 1) && ($order['pid'] == 0 || $this->storeOrderServices->count(['pid' => $order['pid'], 'refund_status' => 0]) == 1))) {
+                $res = $couponUserServices->recoverCoupon((int)$order['coupon_id']);
+                $statusService->save([
+                    'oid' => $order['id'],
+                    'change_type' => 'coupon_back',
+                    'change_message' => '商品退优惠券',
+                    'change_time' => time()
+                ]);
+            }
         }
+
         //回退积分
         $order = $this->regressionIntegral($order);
         $statusService->save([

+ 2 - 1
crmeb/app/services/other/UploadService.php

@@ -95,6 +95,7 @@ class UploadService
             $config['uploadUrl'] = $res['domain'];
             $config['storageName'] = $res['name'];
             $config['storageRegion'] = $res['region'];
+            $config['cdn'] = $res['cdn'];
         }
 
         $thumb = SystemConfigService::more(['thumb_big_height', 'thumb_big_width', 'thumb_mid_height', 'thumb_mid_width', 'thumb_small_height', 'thumb_small_width',]);
@@ -134,7 +135,7 @@ class UploadService
         /** @var SystemStorageServices $storageServices */
         $storageServices = app()->make(SystemStorageServices::class);
         $storageArr = $storageServices->cacheDriver()->remember('storage_list', function () use ($storageServices) {
-            return $storageServices->selectList([], 'domain')->toArray();
+            return $storageServices->selectList([], 'domain,type')->toArray();
         });
         foreach ($storageArr as $item) {
             if ($fileHost == $item['domain']) {

+ 5 - 5
crmeb/app/services/product/product/StoreCategoryServices.php

@@ -97,11 +97,11 @@ class StoreCategoryServices extends BaseServices
         if ($show !== '') $where['is_show'] = $show;
         if (!$type) $where['pid'] = 0;
         $data = get_tree_children($this->dao->getTierList($where, ['id', 'id as value', 'cate_name as label', 'cate_name as title', 'pid']), 'children', 'id');
-        foreach ($data as &$item) {
-            if (!isset($item['children'])) {
-                $item['disabled'] = true;
-            }
-        }
+//        foreach ($data as &$item) {
+//            if (!isset($item['children'])) {
+//                $item['disabled'] = true;
+//            }
+//        }
         return $data;
     }
 

+ 4 - 2
crmeb/app/services/product/product/StoreProductReplyServices.php

@@ -131,10 +131,12 @@ class StoreProductReplyServices extends BaseServices
     public function getRecProductReply(int $productId)
     {
         $res = $this->dao->getProductReply($productId);
+
         if ($res) {
             $res = $res->toArray();
-//            $res['cart_info'] = isset($res['cart_info']) ? json_decode($res['cart_info'], true) : [];
-            $res['suk'] = isset($res['cart_info']['productInfo']['attrInfo']) ? $res['cart_info']['productInfo']['attrInfo']['suk'] : '';
+            if ($res['suk'] == '') {
+                $res['suk'] = isset($res['cart_info']['productInfo']['attrInfo']) ? $res['cart_info']['productInfo']['attrInfo']['suk'] : '';
+            }
             $res['nickname'] = anonymity($res['nickname']);
             $res['merchant_reply_time'] = date('Y-m-d H:i', $res['merchant_reply_time']);
             $res['add_time'] = time_tran($res['add_time']);

+ 10 - 1
crmeb/app/services/product/product/StoreProductServices.php

@@ -620,7 +620,7 @@ class StoreProductServices extends BaseServices
                 $cateGory = $storeCategoryServices->getColumn([['id', 'IN', $cate_id]], 'id,pid', 'id');
                 foreach ($cate_id as $cid) {
                     if ($cid && isset($cateGory[$cid]['pid'])) {
-                        $cateData[] = ['product_id' => $id, 'cate_id' => $cid, 'cate_pid' => $cateGory[$cid]['pid'], 'status' => $data['is_show'], 'add_time' => $time];
+                        $cateData[] = ['product_id' => $id, 'cate_id' => $cid, 'cate_pid' => $cateGory[$cid]['pid'] ?: $cid, 'status' => $data['is_show'], 'add_time' => $time];
                     }
                 }
                 $storeProductCateServices->change($id, $cateData);
@@ -865,6 +865,15 @@ class StoreProductServices extends BaseServices
             $item['cost'] = floatval($item['cost']);
             $item['is_product_type'] = 1;
             $item['logistics'] = explode(',', $item['logistics']);
+            $attrs = $this->getProductRules($item['id'], 0)['attrs'];
+            foreach ($attrs as $items) {
+                $item['attrs'][] = [
+                    'image' => $items['pic'],
+                    'price' => $items['price'],
+                    'ot_price' => $items['ot_price'],
+                    'suk' => implode(',', $items['detail'])
+                ];
+            }
         }
         return $data;
     }

+ 1 - 1
crmeb/app/services/shipping/ExpressServices.php

@@ -260,7 +260,7 @@ class ExpressServices extends BaseServices
                 $data['partner_name'] = $express['partner_name'] ?? '';
                 $data['is_code'] = $express['is_code'] ?? '';
                 $data['net'] = $express['net'] ?? '';
-                $data['is_show'] = 1;
+                $data['is_show'] = 0;
                 $data['status'] = 0;
                 if ($express['partner_id'] == 0 && $express['partner_key'] == 0 && $express['net'] == 0 && $express['check_man'] == 0 && $express['partner_name'] == 0 && $express['is_code'] == 0) {
                     $data['status'] = 1;

+ 1 - 1
crmeb/app/services/statistic/TradeStatisticServices.php

@@ -663,12 +663,12 @@ class TradeStatisticServices extends BaseServices
      */
     public function getRechargeTotalMoney(array $where, string $selectType, string $group = "", bool $isNum = false)
     {
-        /** 用户充值金额 */
         /** @var UserRechargeServices $userRechageService */
         $userRechageService = app()->make(UserRechargeServices::class);
         $rechargeSumField = "price";
         $whereInRecharge['paid'] = 1;
         $whereInRecharge['refund_price'] = '0.00';
+        $whereInRecharge['no_recharge_type'] = 'system';
         $whereInRecharge['timeKey'] = $this->TimeConvert($where['time'], $isNum);
         $whereInRecharge['store_id'] = 0;
         $totalMoney = $userRechageService->getRechargeMoneyByWhere($whereInRecharge, $rechargeSumField, $selectType, $group);

+ 73 - 6
crmeb/app/services/system/config/SystemStorageServices.php

@@ -189,7 +189,10 @@ class SystemStorageServices extends BaseServices
 
         try {
             $upload = UploadService::init($storageInfo->type);
-            $upload->deleteBucket($storageInfo->name, $storageInfo->region);
+            $res = $upload->deleteBucket($storageInfo->name, $storageInfo->region);
+            if (false === $res) {
+                throw new AdminException($upload->getError());
+            }
         } catch (\Throwable $e) {
             throw new AdminException($e->getMessage());
         }
@@ -368,6 +371,56 @@ class SystemStorageServices extends BaseServices
                     }
                 }
                 break;
+            case 5:// cos 京东云
+                $upload = UploadService::init($type);
+                $res = $upload->listbuckets();
+                $list = $res['Buckets'];
+                $location = explode('.', $res['@metadata']['effectiveUri'])[1] ?? 'cn-north-1';
+                $config = $this->getStorageConfig($type);
+                foreach ($list as $item) {
+                    if (!$this->dao->count(['name' => $item['Name'], 'access_key' => $config['accessKey']])) {
+                        $data[] = [
+                            'type' => $type,
+                            'access_key' => $config['accessKey'],
+                            'name' => $item['Name'],
+                            'region' => $location,
+                            'acl' => 'public-read',
+                            'status' => 0,
+                            'domain' => $this->getDomain($type, $item['Name'], $location),
+                            'is_delete' => 0,
+                            'add_time' => time(),
+                            'update_time' => time()
+                        ];
+                    }
+                }
+                break;
+            case 6:// cos 华为云
+            case 7:// cos 天翼云
+                $upload = UploadService::init($type);
+                $list = $upload->listbuckets();
+                if (!empty($list['Name'])) {
+                    $newList = $list;
+                    $list = [];
+                    $list[] = $newList;
+                }
+                $config = $this->getStorageConfig($type);
+                foreach ($list as $item) {
+                    if (!$this->dao->count(['name' => $item['Name'], 'access_key' => $config['accessKey']])) {
+                        $data[] = [
+                            'type' => $type,
+                            'access_key' => $config['accessKey'],
+                            'name' => $item['Name'],
+                            'region' => $item['Location'],
+                            'acl' => 'public-read',
+                            'status' => 0,
+                            'domain' => $this->getDomain($type, $item['Name'], $item['Location']),
+                            'is_delete' => 0,
+                            'add_time' => strtotime($item['CreationDate']),
+                            'update_time' => time()
+                        ];
+                    }
+                }
+                break;
         }
         if ($data) {
             $this->dao->saveAll($data);
@@ -413,6 +466,15 @@ class SystemStorageServices extends BaseServices
             case 4:// cos 腾讯云
                 $domainName = 'https://' . $name . ($appid ? '-' . $appid : '') . '.cos.' . $reagion . '.myqcloud.com';
                 break;
+            case 5:// cos 京东云
+                $domainName = 'https://' . $name . '.s3.' . $reagion . '.jdcloud-oss.com';
+                break;
+            case 6:// cos 华为云
+                $domainName = 'https://' . $name . '.obs.' . $reagion . '.myhuaweicloud.com';
+                break;
+            case 7:// cos 天翼云
+                $domainName = 'https://' . $name . '.obs.' . $reagion . '.ctyun.cn';
+                break;
         }
         return $domainName;
     }
@@ -425,11 +487,11 @@ class SystemStorageServices extends BaseServices
      */
     public function getConfig(int $type)
     {
-        $res = ['name' => '', 'region' => '', 'domain' => ''];
+        $res = ['name' => '', 'region' => '', 'domain' => '', 'cdn' => ''];
         try {
             $config = $this->dao->get(['type' => $type, 'status' => 1, 'is_delete' => 0]);
             if ($config) {
-                return ['name' => $config->name, 'region' => $config->region, 'domain' => $config->domain];
+                return ['name' => $config->name, 'region' => $config->region, 'domain' => $config->domain, 'cdn' => $config->cdn];
             }
         } catch (\Throwable $e) {
         }
@@ -445,9 +507,10 @@ class SystemStorageServices extends BaseServices
      */
     public function getUpdateDomainForm(int $id)
     {
-        $domain = $this->dao->value(['id' => $id], 'domain');
+        $storage = $this->dao->get(['id' => $id], ['domain', 'cdn']);
         $rule = [
-            FormBuilder::input('domain', '空间域名', $domain),
+            FormBuilder::input('domain', '空间域名', $storage['domain']),
+            FormBuilder::input('cdn', 'cdn域名', $storage['cdn']),
         ];
         return create_form('修改空间域名', $rule, '/system/config/storage/domain/' . $id);
     }
@@ -488,7 +551,11 @@ class SystemStorageServices extends BaseServices
                 $resDomain = $upload->getDomianInfo($domain);
                 $info->cname = $resDomain['cname'] ?? '';
             }
-            return $info->save();
+            $info->save();
+        }
+        if ($info->cdn != $data['cdn']) {
+            $info->cdn = $data['cdn'];
+            $info->save();
         }
 
         $this->cacheDriver()->clear();

+ 10 - 2
crmeb/app/services/user/UserBrokerageServices.php

@@ -396,7 +396,7 @@ class UserBrokerageServices extends BaseServices
         }
         /** @var UserExtractServices $userExtractService */
         $userExtractService = app()->make(UserExtractServices::class);
-        $userExtract = $userExtractService->getColumn(['uid' => $uid], 'fail_msg', 'id');
+        $userExtract = $userExtractService->getColumn(['uid' => $uid], 'fail_msg,extract_type', 'id');
         $list = $this->dao->getList($where, '*', $page, $limit);
         $count = $this->dao->count($where);
         $times = [];
@@ -404,7 +404,15 @@ class UserBrokerageServices extends BaseServices
             foreach ($list as &$item) {
                 $item['time'] = $item['time_key'] = $item['add_time'] ? date('Y-m', (int)$item['add_time']) : '';
                 $item['add_time'] = $item['add_time'] ? date('Y-m-d H:i', (int)$item['add_time']) : '';
-                $item['fail_msg'] = $item['type'] == 'extract_fail' ? $userExtract[$item['link_id']] : '';
+                $item['fail_msg'] = $item['type'] == 'extract_fail' ? $userExtract[$item['link_id']]['fail_msg'] : '';
+                $extract_type = $userExtract[$item['link_id']]['extract_type'];
+                if ($extract_type == 'alipay') {
+                    $item['extract_type'] = '支付宝';
+                } elseif ($extract_type == 'weixin') {
+                    $item['extract_type'] = '微信';
+                } else {
+                    $item['extract_type'] = '银行卡';
+                }
             }
             $times = array_merge(array_unique(array_column($list, 'time_key')));
         }

+ 1 - 0
crmeb/crmeb/services/upload/Upload.php

@@ -21,6 +21,7 @@ use think\facade\Config;
  * @mixin \crmeb\services\upload\storage\COS
  * @mixin \crmeb\services\upload\storage\Qiniu
  * @mixin \crmeb\services\upload\storage\Jdoss
+ * @mixin \crmeb\services\upload\storage\Tyoss
  */
 class Upload extends BaseManager
 {

+ 125 - 13
crmeb/crmeb/services/upload/extend/obs/Client.php

@@ -124,6 +124,8 @@ class Client extends BaseClient
      */
     protected $baseUrl = 'obs.cn-north-1.myhuaweicloud.com';
 
+    protected $type = 'hw';
+
     /**
      * Client constructor.
      * @param array $config
@@ -135,6 +137,7 @@ class Client extends BaseClient
         $this->bucketName = $config['bucket'] ?? '';
         $this->region = $config['region'] ?? 'ap-chengdu';
         $this->uploadUrl = $config['uploadUrl'] ?? '';
+        $this->type = $config['type'] ?? 'hw';
     }
 
     /**
@@ -172,10 +175,8 @@ class Client extends BaseClient
      */
     public function putObject(string $key, $body, string $contentType = 'image/jpeg')
     {
-        $url = $this->uploadUrl ?: $this->getRequestUrl($this->bucketName, $this->region);
-
         $header = [
-            'Host' => $url,
+            'Host' => $this->getRequestUrl($this->bucketName, $this->region),
             'Content-Type' => $contentType,
             'Content-Length' => strlen($body),
         ];
@@ -218,7 +219,43 @@ class Client extends BaseClient
      */
     public function listBuckets()
     {
-        $res = $this->request('https://' . $this->baseUrl . '/', 'GET', [], []);
+        $header = [
+            'Host' => $this->getRequestUrl('', $this->region),
+        ];
+        $res = $this->request('https://' . $header['Host'] . '/', 'GET', [], []);
+        return $this->response($res);
+    }
+
+    public function headBucket(string $bucket, string $region)
+    {
+        $header = [
+            'Host' => $this->getRequestUrl($bucket, $region),
+        ];
+        $res = $this->request('https://' . $header['Host'] . '/', 'HEAD', [], []);
+        return $this->response($res);
+    }
+
+    /**
+     * 设置桶的策略
+     * @param string $bucket
+     * @param string $region
+     * @param array $data
+     * @return mixed
+     *
+     * @date 2023/06/08
+     * @author yyw
+     */
+    public function putPolicy(string $bucket, string $region, array $data)
+    {
+        $header = [
+            'Host' => $this->getRequestUrl($bucket, $region),
+            "Content-Type" => "application/json"
+        ];
+        $res = $this->request('https://' . $header['Host'] . '/?policy', 'PUT', [
+            'bucket' => $bucket,
+            'json' => $data
+        ], $header);
+
         return $this->response($res);
     }
 
@@ -237,10 +274,12 @@ class Client extends BaseClient
         $header = [
             'x-obs-acl' => $acl,
             'Host' => $this->getRequestUrl($bucket, $region),
+            "Content-Type" => "application/xml"
         ];
-
+        $xml = "<CreateBucketConfiguration><Location>{$region}</Location></CreateBucketConfiguration>";
         $res = $this->request('https://' . $header['Host'] . '/', 'PUT', [
-            'bucket' => $bucket
+            'bucket' => $bucket,
+            'body' => $xml
         ], $header);
 
         return $this->response($res);
@@ -316,9 +355,42 @@ class Client extends BaseClient
      * @email 136327134@qq.com
      * @date 2023/5/18
      */
-    public function putBucketCors()
+    public function putBucketCors(string $bucket, string $region, array $data = [])
+    {
+        $xml = $this->xmlBuild($data, 'CORSConfiguration', 'CORSRule');
+        $header = [
+            'Host' => $this->getRequestUrl($bucket, $region),
+            'Content-Type' => 'application/xml',
+            'Content-Length' => strlen($xml),
+            'Content-MD5' => base64_encode(md5($xml, true))
+        ];
+        $res = $this->request('https://' . $header['Host'] . '/?cors', 'PUT', [
+            'bucket' => $bucket,
+            'body' => $xml
+        ], $header);
+
+        return $this->response($res);
+    }
+
+    /**
+     * 删除跨域
+     * @param string $bucket
+     * @param string $region
+     * @return mixed
+     *
+     * @date 2023/06/08
+     * @author yyw
+     */
+    public function deleteBucketCors(string $bucket, string $region)
     {
-        return true;
+        $header = [
+            'Host' => $this->getRequestUrl($bucket, $region),
+        ];
+        $res = $this->request('https://' . $header['Host'] . '/?cors', 'DELETE', [
+            'bucket' => $bucket,
+        ], $header);
+
+        return $this->response($res);
     }
 
     /**
@@ -341,13 +413,22 @@ class Client extends BaseClient
      * @param string $bucket
      * @param string $region
      * @return string
-     * @author 等风来
-     * @email 136327134@qq.com
-     * @date 2023/5/18
+     *
+     * @date 2023/06/08
+     * @author yyw
      */
-    protected function getRequestUrl(string $bucket, string $region)
+    protected function getRequestUrl(string $bucket = '', string $region = '')
     {
-        return $bucket . '.obs.' . $region . '.myhuaweicloud.com';
+        if ($this->type == 'hw') {
+            $url = '.myhuaweicloud.com';  // 华为
+        } else {
+            $url = '.ctyun.cn';  // 天翼
+        }
+        if ($bucket) {
+            return $bucket . '.obs.' . $region . $url;
+        } else {
+            return 'obs.' . $region . $url;
+        }
     }
 
     /**
@@ -602,4 +683,35 @@ class Client extends BaseClient
         return $this->requestClient($url, $method, $data, $result['headers'], $timeout);
     }
 
+
+    /**
+     * 组合成xml
+     * @param array $data
+     * @param string $root
+     * @param string $itemKey
+     * @return string
+     * @author 等风来
+     * @email 136327134@qq.com
+     * @date 2022/10/17
+     */
+    protected function xmlBuild(array $xmlAttr, string $root = 'xml', string $itemKey = 'item')
+    {
+        $xml = '<' . $root . '>';
+        $xml .= '<' . $itemKey . '>';
+
+        foreach ($xmlAttr as $kk => $vv) {
+            if (is_array($vv)) {
+                foreach ($vv as $v) {
+                    $xml .= '<' . $kk . '>' . $v . '</' . $kk . '>';
+                }
+            } else {
+                $xml .= '<' . $kk . '>' . $vv . '</' . $kk . '>';
+            }
+        }
+        $xml .= '</' . $itemKey . '>';
+        $xml .= '</' . $root . '>';
+
+        return $xml;
+    }
+
 }

+ 6 - 36
crmeb/crmeb/services/upload/storage/Jdoss.php

@@ -147,7 +147,7 @@ class Jdoss extends BaseUpload
                 'Key' => $key,
                 'SourceFile' => $fileHandle->getRealPath()
             ]);
-            if (!isset($uploadInfo['info']['url'])) {
+            if (!isset($uploadInfo['ObjectURL'])) {
                 return $this->setError('Upload failure');
             }
             $this->fileInfo->uploadInfo = $uploadInfo;
@@ -157,7 +157,7 @@ class Jdoss extends BaseUpload
             $this->fileInfo->filePathWater = $this->water($this->fileInfo->filePath);
             $this->authThumb && $this->thumb($this->fileInfo->filePath);
             return $this->fileInfo;
-        } catch (UploadException $e) {
+        } catch (\Throwable $e) {
             return $this->setError($e->getMessage());
         }
     }
@@ -185,7 +185,7 @@ class Jdoss extends BaseUpload
             $this->fileInfo->filePathWater = $this->water($this->fileInfo->filePath);
             $this->thumb($this->fileInfo->filePath);
             return $this->fileInfo;
-        } catch (UploadException $e) {
+        } catch (\Throwable $e) {
             return $this->setError($e->getMessage());
         }
     }
@@ -207,7 +207,7 @@ class Jdoss extends BaseUpload
     {
         try {
             $res = $this->app()->listBuckets();
-            return $res['Buckets']['Bucket'] ?? [];
+            return $res ?? [];
         } catch (\Throwable $e) {
             return [];
         }
@@ -277,8 +277,7 @@ class Jdoss extends BaseUpload
         try {
             $this->storageRegion = $region;
             $this->app()->deleteBucket([
-                'bucketName' => $name, // REQUIRED
-                'forceDelete' => false
+                'Bucket' => $name, // REQUIRED
             ]);
             return true;
         } catch (AcmException $e) {
@@ -290,7 +289,7 @@ class Jdoss extends BaseUpload
     {
         try {
             $this->storageRegion = $region;
-            $res = $this->app()->getBucketWebsite([
+            $res = $this->app()->getBucketPolicy([
                 'Bucket' => $name
             ]);
             return $res['DomainName'] ?? [];
@@ -429,33 +428,4 @@ class Jdoss extends BaseUpload
         }
         return $waterPath;
     }
-
-    public function setError(?string $error = null)
-    {
-        $this->error = $error ?: '未知错误';
-        if (env('APP_DEBUG')) {
-            throw new UploadException($this->xmlToArr($this->error));
-        } else {
-            return false;
-        }
-    }
-
-    function xmlToArr($errorXml)
-    {
-
-        $pattern = '/<statusCode>(\d+)<\/statusCode><Code>(.*?)<\/Code><Message>(.*?)<\/Message><Resource>(.*?)<\/Resource><RequestId>(.*?)<\/RequestId>/';
-
-        preg_match($pattern, $errorXml, $matches);
-
-        $error = [
-            'statusCode' => $matches[1],
-            'Code' => $matches[2],
-            'Message' => $matches[3],
-            'Resource' => $matches[4],
-            'RequestId' => $matches[5]
-        ];
-
-        return $error;
-
-    }
 }

+ 317 - 0
crmeb/crmeb/services/upload/storage/Obs.php

@@ -0,0 +1,317 @@
+<?php
+
+namespace crmeb\services\upload\storage;
+
+use crmeb\exceptions\AdminException;
+use crmeb\exceptions\UploadException;
+use crmeb\services\upload\extend\obs\Client as TyClient;
+use crmeb\services\upload\BaseUpload;
+use GuzzleHttp\Psr7\Utils;
+
+class Obs extends BaseUpload
+{
+    /**
+     * accessKey
+     * @var mixed
+     */
+    protected $accessKey;
+
+    /**
+     * secretKey
+     * @var mixed
+     */
+    protected $secretKey;
+
+    /**
+     * 句柄
+     * @var TyClient
+     */
+    protected $handle;
+
+    /**
+     * 空间域名 Domain
+     * @var mixed
+     */
+    protected $uploadUrl;
+
+    /**
+     * 存储空间名称  公开空间
+     * @var mixed
+     */
+    protected $storageName;
+
+    /**
+     * COS使用  所属地域
+     * @var mixed|null
+     */
+    protected $storageRegion;
+
+    /**
+     * @var string
+     */
+    protected $cdn;
+
+    public function move(string $file = 'file', bool $isStream = false, string $fileContent = null)
+    {
+        if (!$isStream) {
+            $fileHandle = app()->request->file($file);
+            if (!$fileHandle) {
+                return $this->setError('上传的文件不存在');
+            }
+            if ($this->validate) {
+                if (!in_array(pathinfo($fileHandle->getOriginalName(), PATHINFO_EXTENSION), $this->validate['fileExt'])) {
+                    return $this->setError('不合法的文件后缀');
+                }
+                if (filesize($fileHandle) > $this->validate['filesize']) {
+                    return $this->setError('文件过大');
+                }
+                if (!in_array($fileHandle->getOriginalMime(), $this->validate['fileMime'])) {
+                    return $this->setError('不合法的文件类型');
+                }
+            }
+            $key = $this->saveFileName($fileHandle->getRealPath(), $fileHandle->getOriginalExtension());
+
+            $body = fopen($fileHandle->getRealPath(), 'rb');
+            $body = (string)Utils::streamFor($body);
+        } else {
+            $key = $file;
+            $body = $fileContent;
+        }
+        $key = $this->getUploadPath($key);
+
+        try {
+            $uploadInfo = $this->app()->putObject($key, $body, 'application/octet-stream');
+            $this->fileInfo->uploadInfo = $uploadInfo;
+            $this->fileInfo->realName = $fileHandle->getOriginalName();
+            $this->fileInfo->filePath = ($this->cdn ?: $this->uploadUrl) . '/' . $key;
+            $this->fileInfo->fileName = $key;
+            $this->fileInfo->filePathWater = $this->water($this->fileInfo->filePath);
+            $this->authThumb && $this->thumb($this->fileInfo->filePath);
+            return $this->fileInfo;
+        } catch (\Throwable $e) {
+            return $this->setError($e->getMessage());
+        }
+    }
+
+    public function stream($fileContent, string $key = null)
+    {
+        if (!$key) {
+            $key = $this->saveFileName();
+        }
+        return $this->move($key, true, $fileContent);
+    }
+
+    public function delete(string $filePath)
+    {
+        try {
+            return $this->app()->deleteObject($filePath);
+        } catch (\Exception $e) {
+            return $this->setError($e->getMessage());
+        }
+    }
+
+    /**
+     * 初始化
+     * @param array $config
+     * @return mixed|void
+     */
+    public function initialize(array $config)
+    {
+        parent::initialize($config);
+        $this->accessKey = $config['accessKey'] ?? null;
+        $this->secretKey = $config['secretKey'] ?? null;
+        $this->uploadUrl = $this->checkUploadUrl($config['uploadUrl'] ?? '');
+        $this->storageName = $config['storageName'] ?? null;
+        $this->storageRegion = $config['storageRegion'] ?? null;
+        $this->cdn = $config['cdn'] ?? null;
+        $this->waterConfig['watermark_text_font'] = 'simfang仿宋.ttf';
+    }
+
+    /**
+     * 实例化cos
+     * @return TyClient
+     */
+    protected function app()
+    {
+        $this->handle = new TyClient([
+            'accessKey' => $this->accessKey,
+            'secretKey' => $this->secretKey,
+            'region' => $this->storageRegion ?: 'cn-north-1',
+            'bucket' => $this->storageName,
+            'uploadUrl' => $this->uploadUrl
+        ]);
+        return $this->handle;
+    }
+
+    public function listbuckets(string $region = null, bool $line = false, bool $shared = false)
+    {
+        try {
+            $res = $this->app()->listBuckets();
+            return $res['Buckets']['Bucket'] ?? [];
+        } catch (\Throwable $e) {
+            return [];
+        }
+    }
+
+    public function createBucket(string $name, string $region, string $acl = TyClient::DEFAULT_OBS_ACL)
+    {
+        $regionData = $this->getRegion();
+        $regionData = array_column($regionData, 'value');
+        if (!in_array($region, $regionData)) {
+            return $this->setError('COS:无效的区域!');
+        }
+        $this->storageRegion = $region;
+        $app = $this->app();
+        //创建桶
+        try {
+            $app->createBucket($name, $region, $acl);
+            $data = [
+                'Statement' => [
+                    'Sid' => '公共读' . $name,
+                    'Effect' => 'Allow',
+                    'Principal' => [
+                        'ID' => ['*']
+                    ],
+                    'Action' => ['HeadBucket', 'GetBucketLocation', 'ListBucketVersions', 'GetObject', 'RestoreObject', 'GetObjectVersion'],
+                    'Resource' => [$name, $name . '/*']
+                ]
+            ];
+
+            $app->putPolicy($name, $region, $data);
+        } catch (\Throwable $e) {
+            return $this->setError('COS:' . $e->getMessage());
+        }
+        return true;
+    }
+
+    public function getRegion()
+    {
+        return $this->app()->getRegion();
+    }
+
+    public function deleteBucket(string $name, string $region = '')
+    {
+        try {
+            $this->app()->deleteBucket($name, $region);
+            return true;
+        } catch (\Throwable $e) {
+            return $this->setError($e->getMessage());
+        }
+    }
+
+    public function getDomian($name, $region)
+    {
+        try {
+            $res = $this->app()->GetBucketDomain($name, $region);
+            if ($res) {
+                $domainRules = $res->toArray()['ListBucketCustomDomainsResult'];
+                return array_column($domainRules, 'DomainName');
+            } else {
+                return [];
+            }
+
+        } catch (\Throwable $e) {
+        }
+        return [];
+    }
+
+    public function bindDomian(string $name, string $domain, string $region = null)
+    {
+        $parseDomin = parse_url($domain);
+        try {
+            $this->app()->putBucketDomain($name, $region, [
+                'domainname' => $parseDomin['host'],
+            ]);
+            return true;
+        } catch (\Throwable $e) {
+            return $this->setError($e->getMessage());
+        }
+    }
+
+    public function setBucketCors(string $name, string $region)
+    {
+        try {
+            $this->app()->PutBucketCors($name, $region, [
+                'AllowedHeader' => ['*'],
+                'AllowedMethod' => ['PUT', 'GET', 'POST', 'DELETE', 'HEAD'],
+                'AllowedOrigin' => ['*'],
+                'ExposeHeader' => ['ETag', 'Content-Length', 'x-cos-request-id'],
+                'MaxAgeSeconds' => 100
+            ]);
+            return true;
+        } catch (\Throwable $e) {
+            return $this->setError($e->getMessage());
+        }
+    }
+
+    public function getTempKeys()
+    {
+        // TODO: Implement getTempKeys() method.
+    }
+
+    /**
+     * 缩略图
+     * @param string $filePath
+     * @param string $fileName
+     * @param string $type
+     * @return array|mixed
+     */
+    public function thumb(string $filePath = '', string $fileName = '', string $type = 'all')
+    {
+        $filePath = $this->getFilePath($filePath);
+        $data = ['big' => $filePath, 'mid' => $filePath, 'small' => $filePath];
+        $this->fileInfo->filePathBig = $this->fileInfo->filePathMid = $this->fileInfo->filePathSmall = $this->fileInfo->filePathWater = $filePath;
+        if ($filePath) {
+            $config = $this->thumbConfig;
+            foreach ($this->thumb as $v) {
+                if ($type == 'all' || $type == $v) {
+                    $height = 'thumb_' . $v . '_height';
+                    $width = 'thumb_' . $v . '_width';
+                    $key = 'filePath' . ucfirst($v);
+                    if (sys_config('image_thumbnail_status', 1) && isset($config[$height]) && isset($config[$width]) && $config[$height] && $config[$width]) {
+                        $this->fileInfo->$key = $filePath . '?x-oss-process=image/resize,h_' . $config[$height] . ',w_' . $config[$width];
+                        $this->fileInfo->$key = $this->water($this->fileInfo->$key);
+                        $data[$v] = $this->fileInfo->$key;
+                    } else {
+                        $this->fileInfo->$key = $this->water($this->fileInfo->$key);
+                        $data[$v] = $this->fileInfo->$key;
+                    }
+                }
+            }
+        }
+        return $data;
+    }
+
+    /**
+     * 水印
+     * @param string $filePath
+     * @return mixed|string
+     */
+    public function water(string $filePath = '')
+    {
+        $filePath = $this->getFilePath($filePath);
+        $waterConfig = $this->waterConfig;
+        $waterPath = $filePath;
+        if ($waterConfig['image_watermark_status'] && $filePath) {
+            if (strpos($filePath, '?x-oss-process') === false) {
+                $filePath .= '?x-oss-process=image';
+            }
+            switch ($waterConfig['watermark_type']) {
+                case 1://图片
+                    if (!$waterConfig['watermark_image']) {
+                        throw new AdminException(400722);
+                    }
+                    $waterPath = $filePath .= '/watermark,image_' . base64_encode($waterConfig['watermark_image']) . ',t_' . $waterConfig['watermark_opacity'] . ',g_' . ($this->position[$waterConfig['watermark_position']] ?? 'nw') . ',x_' . $waterConfig['watermark_x'] . ',y_' . $waterConfig['watermark_y'];
+                    break;
+                case 2://文字
+                    if (!$waterConfig['watermark_text']) {
+                        throw new AdminException(400723);
+                    }
+                    $waterConfig['watermark_text_color'] = str_replace('#', '', $waterConfig['watermark_text_color']);
+                    $waterPath = $filePath .= '/watermark,text_' . base64_encode($waterConfig['watermark_text']) . ',color_' . $waterConfig['watermark_text_color'] . ',size_' . $waterConfig['watermark_text_size'] . ',g_' . ($this->position[$waterConfig['watermark_position']] ?? 'nw') . ',x_' . $waterConfig['watermark_x'] . ',y_' . $waterConfig['watermark_y'];
+                    break;
+            }
+        }
+        return $waterPath;
+    }
+}

+ 445 - 0
crmeb/crmeb/services/upload/storage/Tyoss.php

@@ -0,0 +1,445 @@
+<?php
+
+namespace crmeb\services\upload\storage;
+
+use crmeb\exceptions\AdminException;
+use crmeb\services\upload\extend\obs\Client as TyClient;
+use crmeb\services\upload\BaseUpload;
+use GuzzleHttp\Psr7\Utils;
+
+class Tyoss extends BaseUpload
+{
+    /**
+     * accessKey
+     * @var mixed
+     */
+    protected $accessKey;
+
+    /**
+     * secretKey
+     * @var mixed
+     */
+    protected $secretKey;
+
+    /**
+     * 句柄
+     * @var TyClient
+     */
+    protected $handle;
+
+    /**
+     * 空间域名 Domain
+     * @var mixed
+     */
+    protected $uploadUrl;
+
+    /**
+     * 存储空间名称  公开空间
+     * @var mixed
+     */
+    protected $storageName;
+
+    /**
+     * COS使用  所属地域
+     * @var mixed|null
+     */
+    protected $storageRegion;
+
+    /**
+     * @var string
+     */
+    protected $cdn;
+
+    public function move(string $file = 'file', bool $isStream = false, string $fileContent = null)
+    {
+        if (!$isStream) {
+            $fileHandle = app()->request->file($file);
+            if (!$fileHandle) {
+                return $this->setError('上传的文件不存在');
+            }
+            if ($this->validate) {
+                if (!in_array(pathinfo($fileHandle->getOriginalName(), PATHINFO_EXTENSION), $this->validate['fileExt'])) {
+                    return $this->setError('不合法的文件后缀');
+                }
+                if (filesize($fileHandle) > $this->validate['filesize']) {
+                    return $this->setError('文件过大');
+                }
+                if (!in_array($fileHandle->getOriginalMime(), $this->validate['fileMime'])) {
+                    return $this->setError('不合法的文件类型');
+                }
+            }
+            $key = $this->saveFileName($fileHandle->getRealPath(), $fileHandle->getOriginalExtension());
+
+            $body = fopen($fileHandle->getRealPath(), 'rb');
+            $body = (string)Utils::streamFor($body);
+        } else {
+            $key = $file;
+            $body = $fileContent;
+        }
+        $key = $this->getUploadPath($key);
+
+        try {
+            $uploadInfo = $this->app()->putObject($key, $body, 'application/octet-stream');
+            $this->fileInfo->uploadInfo = $uploadInfo;
+            $this->fileInfo->realName = $fileHandle->getOriginalName();
+            $this->fileInfo->filePath = ($this->cdn ?: $this->uploadUrl) . '/' . $key;
+            $this->fileInfo->fileName = $key;
+            $this->fileInfo->filePathWater = $this->water($this->fileInfo->filePath);
+            $this->authThumb && $this->thumb($this->fileInfo->filePath);
+            return $this->fileInfo;
+        } catch (\Throwable $e) {
+            return $this->setError($e->getMessage());
+        }
+    }
+
+    public function stream($fileContent, string $key = null)
+    {
+        if (!$key) {
+            $key = $this->saveFileName();
+        }
+        return $this->move($key, true, $fileContent);
+    }
+
+    public function delete(string $filePath)
+    {
+        try {
+            return $this->app()->deleteObject($filePath);
+        } catch (\Exception $e) {
+            return $this->setError($e->getMessage());
+        }
+    }
+
+    /**
+     * 初始化
+     * @param array $config
+     * @return mixed|void
+     */
+    public function initialize(array $config)
+    {
+        parent::initialize($config);
+        $this->accessKey = $config['accessKey'] ?? null;
+        $this->secretKey = $config['secretKey'] ?? null;
+        $this->uploadUrl = $this->checkUploadUrl($config['uploadUrl'] ?? '');
+        $this->storageName = $config['storageName'] ?? null;
+        $this->storageRegion = $config['storageRegion'] ?? null;
+        $this->cdn = $config['cdn'] ?? null;
+        $this->waterConfig['watermark_text_font'] = 'simfang仿宋.ttf';
+    }
+
+    /**
+     * 实例化cos
+     * @return TyClient
+     */
+    protected function app()
+    {
+        $this->handle = new TyClient([
+            'accessKey' => $this->accessKey,
+            'secretKey' => $this->secretKey,
+            'region' => $this->storageRegion ?: 'cn-qhxn1',
+            'bucket' => $this->storageName,
+            'uploadUrl' => $this->uploadUrl,
+            'type' => 'ty'
+        ]);
+        return $this->handle;
+    }
+
+    public function listbuckets(string $region = null, bool $line = false, bool $shared = false)
+    {
+        try {
+            $res = $this->app()->listBuckets();
+            return $res['Buckets']['Bucket'] ?? [];
+        } catch (\Throwable $e) {
+            return [];
+        }
+    }
+
+    public function createBucket(string $name, string $region, string $acl = TyClient::DEFAULT_OBS_ACL)
+    {
+        $regionData = $this->getRegion();
+        $regionData = array_column($regionData, 'value');
+        if (!in_array($region, $regionData)) {
+            return $this->setError('COS:无效的区域!');
+        }
+        $this->storageRegion = $region;
+        $app = $this->app();
+        //创建桶
+        try {
+            $app->createBucket($name, $region, $acl);
+            $data = [
+                'Statement' => [
+                    'Sid' => '公共读' . $name,
+                    'Effect' => 'Allow',
+                    'Principal' => [
+                        'ID' => ['*']
+                    ],
+                    'Action' => ['HeadBucket', 'GetBucketLocation', 'ListBucketVersions', 'GetObject', 'RestoreObject', 'GetObjectVersion'],
+                    'Resource' => [$name, $name . '/*']
+                ]
+            ];
+
+            $app->putPolicy($name, $region, $data);
+        } catch (\Throwable $e) {
+            return $this->setError('COS:' . $e->getMessage());
+        }
+        return true;
+    }
+
+    public function getRegion()
+    {
+        return [
+            [
+                'value' => 'cn-gz1',
+                'label' => '贵州'
+            ],
+            [
+                'value' => 'cn-fz1',
+                'label' => '福州'
+            ],
+            [
+                'value' => 'cn-hz1',
+                'label' => '杭州'
+            ],
+            [
+                'value' => 'cn-sz1',
+                'label' => '深圳'
+            ],
+            [
+                'value' => 'cn-gdgz1',
+                'label' => '广州'
+            ],
+            [
+                'value' => 'cn-jssz1',
+                'label' => '苏州'
+            ],
+            [
+                'value' => 'cn-sh1',
+                'label' => '上海'
+            ],
+            [
+                'value' => 'cn-ahwh1',
+                'label' => '芜湖'
+            ],
+            [
+                'value' => 'cn-bj1',
+                'label' => '北京'
+            ],
+            [
+                'value' => 'cn-sccd1',
+                'label' => '成都'
+            ],
+            [
+                'value' => 'cn-hazz1',
+                'label' => '郑州'
+            ],
+            [
+                'value' => 'cn-hncs1',
+                'label' => '长沙'
+            ],
+            [
+                'value' => 'cn-gxnn1',
+                'label' => '南宁'
+            ],
+            [
+                'value' => 'cn-jxnc1',
+                'label' => '南昌'
+            ],
+            [
+                'value' => 'cn-sdqd1',
+                'label' => '青岛'
+            ],
+            [
+                'value' => 'cn-snxy1',
+                'label' => '咸阳'
+            ],
+            [
+                'value' => 'cn-xjcj1',
+                'label' => '新疆'
+            ],
+            [
+                'value' => 'cn-ynkm1',
+                'label' => '昆明'
+            ],
+            [
+                'value' => 'cn-hihk1',
+                'label' => '海口'
+            ],
+            [
+                'value' => 'cn-hbwh1',
+                'label' => '武汉'
+            ],
+            [
+                'value' => 'cn-cq1',
+                'label' => '重庆'
+            ],
+            [
+                'value' => 'cn-qhxn1',
+                'label' => '西宁'
+            ],
+            [
+                'value' => 'cn-gslz1',
+                'label' => '兰州'
+            ],
+            [
+                'value' => 'cn-nxyc1',
+                'label' => '银川'
+            ],
+            [
+                'value' => 'cn-sxty1',
+                'label' => '太原'
+            ],
+            [
+                'value' => 'cn-hesjz1',
+                'label' => '石家庄'
+            ],
+            [
+                'value' => 'cn-tj1',
+                'label' => '天津'
+            ],
+            [
+                'value' => 'cn-jlcc1',
+                'label' => '长春'
+            ],
+            [
+                'value' => 'cn-hlhrb1',
+                'label' => '哈尔滨'
+            ],
+            [
+                'value' => 'cn-nmhh1',
+                'label' => '内蒙古'
+            ],
+            [
+                'value' => 'cn-lnsy1',
+                'label' => '沈阳'
+            ],
+            [
+                'value' => 'cn-north1',
+                'label' => '华北'
+            ]
+        ];
+    }
+
+    public function deleteBucket(string $name, string $region = '')
+    {
+        try {
+            $this->app()->deleteBucket($name, $region);
+            return true;
+        } catch (\Throwable $e) {
+            return $this->setError($e->getMessage());
+        }
+    }
+
+    public function getDomian($name, $region)
+    {
+        try {
+            $res = $this->app()->GetBucketDomain($name, $region);
+            if ($res) {
+                $domainRules = $res->toArray()['ListBucketCustomDomainsResult'];
+                return array_column($domainRules, 'DomainName');
+            } else {
+                return [];
+            }
+
+        } catch (\Throwable $e) {
+        }
+        return [];
+    }
+
+    public function bindDomian(string $name, string $domain, string $region = null)
+    {
+        $parseDomin = parse_url($domain);
+        try {
+            $this->app()->putBucketDomain($name, $region, [
+                'domainname' => $parseDomin['host'],
+            ]);
+            return true;
+        } catch (\Throwable $e) {
+            return $this->setError($e->getMessage());
+        }
+    }
+
+    public function setBucketCors(string $name, string $region)
+    {
+        try {
+            $this->app()->PutBucketCors($name, $region, [
+                'AllowedHeader' => ['*'],
+                'AllowedMethod' => ['PUT', 'GET', 'POST', 'DELETE', 'HEAD'],
+                'AllowedOrigin' => ['*'],
+                'ExposeHeader' => ['ETag', 'Content-Length', 'x-cos-request-id'],
+                'MaxAgeSeconds' => 100
+            ]);
+            return true;
+        } catch (\Throwable $e) {
+            return $this->setError($e->getMessage());
+        }
+    }
+    public function getTempKeys()
+    {
+        // TODO: Implement getTempKeys() method.
+    }
+
+    /**
+     * 缩略图
+     * @param string $filePath
+     * @param string $fileName
+     * @param string $type
+     * @return array|mixed
+     */
+    public function thumb(string $filePath = '', string $fileName = '', string $type = 'all')
+    {
+        $filePath = $this->getFilePath($filePath);
+        $data = ['big' => $filePath, 'mid' => $filePath, 'small' => $filePath];
+        $this->fileInfo->filePathBig = $this->fileInfo->filePathMid = $this->fileInfo->filePathSmall = $this->fileInfo->filePathWater = $filePath;
+        if ($filePath) {
+            $config = $this->thumbConfig;
+            foreach ($this->thumb as $v) {
+                if ($type == 'all' || $type == $v) {
+                    $height = 'thumb_' . $v . '_height';
+                    $width = 'thumb_' . $v . '_width';
+                    $key = 'filePath' . ucfirst($v);
+                    if (sys_config('image_thumbnail_status', 1) && isset($config[$height]) && isset($config[$width]) && $config[$height] && $config[$width]) {
+                        $this->fileInfo->$key = $filePath . '?x-oss-process=image/resize,h_' . $config[$height] . ',w_' . $config[$width];
+                        $this->fileInfo->$key = $this->water($this->fileInfo->$key);
+                        $data[$v] = $this->fileInfo->$key;
+                    } else {
+                        $this->fileInfo->$key = $this->water($this->fileInfo->$key);
+                        $data[$v] = $this->fileInfo->$key;
+                    }
+                }
+            }
+        }
+        return $data;
+    }
+
+    /**
+     * 水印
+     * @param string $filePath
+     * @return mixed|string
+     */
+    public function water(string $filePath = '')
+    {
+        $filePath = $this->getFilePath($filePath);
+        $waterConfig = $this->waterConfig;
+        $waterPath = $filePath;
+        if ($waterConfig['image_watermark_status'] && $filePath) {
+            if (strpos($filePath, '?x-oss-process') === false) {
+                $filePath .= '?x-oss-process=image';
+            }
+            switch ($waterConfig['watermark_type']) {
+                case 1://图片
+                    if (!$waterConfig['watermark_image']) {
+                        throw new AdminException(400722);
+                    }
+                    $waterPath = $filePath .= '/watermark,image_' . base64_encode($waterConfig['watermark_image']) . ',t_' . $waterConfig['watermark_opacity'] . ',g_' . ($this->position[$waterConfig['watermark_position']] ?? 'nw') . ',x_' . $waterConfig['watermark_x'] . ',y_' . $waterConfig['watermark_y'];
+                    break;
+                case 2://文字
+                    if (!$waterConfig['watermark_text']) {
+                        throw new AdminException(400723);
+                    }
+                    $waterConfig['watermark_text_color'] = str_replace('#', '', $waterConfig['watermark_text_color']);
+                    $waterPath = $filePath .= '/watermark,text_' . base64_encode($waterConfig['watermark_text']) . ',color_' . $waterConfig['watermark_text_color'] . ',size_' . $waterConfig['watermark_text_size'] . ',g_' . ($this->position[$waterConfig['watermark_position']] ?? 'nw') . ',x_' . $waterConfig['watermark_x'] . ',y_' . $waterConfig['watermark_y'];
+                    break;
+            }
+        }
+        return $waterPath;
+    }
+}

Fichier diff supprimé car celui-ci est trop grand
+ 1089 - 1089
crmeb/public/install/crmeb.sql


+ 13 - 0
template/admin/src/api/product.js

@@ -84,6 +84,19 @@ export function productShowApi(data) {
   });
 }
 
+/**
+ * 添加虚拟评论
+ * @param {*} data
+ * @returns
+ */
+export function saveFictitiousReply(data) {
+  return request({
+    url: 'product/reply/save_fictitious_reply',
+    method: 'post',
+    data,
+  });
+}
+
 /**
  * @description 商品属性 -- 批量下架
  * @param {Object} param data {Object} 传值对象

+ 38 - 19
template/admin/src/components/linkaddress/index.vue

@@ -250,31 +250,38 @@
           <!--<div v-if="!tableList.length || customNum==2">-->
           <!--<Button type="primary" @click="customList" v-if="tableList.length">自定义列表</Button>-->
           <div style="width: 340px; margin: 150px 100px 0 120px">
-            <Form ref="customdate" :model="customdate" :rules="ruleValidate" :label-width="88">
+            <Form ref="customdate" :model="customdate" :rules="ruleValidate" :label-width="100">
               <!--<FormItem label="链接名称:" prop="name">-->
               <!--<Input v-model="customdate.name" placeholder="会员中心"></Input>-->
               <!--</FormItem>-->
-              <FormItem label="跳转路径:" prop="url">
+              <!-- <FormItem label="跳转路径:" prop="url">
                 <Input v-model="customdate.url" placeholder="请输入跳转路径"></Input>
+              </FormItem> -->
+              <div class="mb30 radioGroup">
+                <RadioGroup v-model="customdate.status" @on-change="radioTap('customdate')">
+                  <Radio :label="1">
+                    <Icon></Icon>
+                    <span>普通链接</span>
+                  </Radio>
+                  <Radio :label="2">
+                    <Icon></Icon>
+                    <span>跳转其他小程序</span>
+                  </Radio>
+                </RadioGroup>
+              </div>
+              <FormItem label="跳转路径:" prop="url" v-if="customdate.status == 1">
+                <Input v-model="customdate.url" placeholder="请输入正确跳转路径"></Input>
+              </FormItem>
+              <FormItem label="APPID:" prop="appid" v-if="customdate.status == 2">
+                <Input v-model="customdate.appid" placeholder="请输入正确APPID"></Input>
+              </FormItem>
+              <FormItem label="小程序路径:" prop="mpUrl" v-if="customdate.status == 2">
+                <Input v-model="customdate.mpUrl" placeholder="请输入正确小程序路径"></Input>
               </FormItem>
             </Form>
           </div>
-          <!--</div>-->
-          <!--<div v-else>-->
-          <!--<Button type="primary" @click="customLink">自定义链接</Button>-->
-          <!--<div class="Box">-->
-          <!--<div v-for="(item,index) in tableList" :key="index" class="item">-->
-          <!--<div class="cont_box" :class="currenId==item.id?'on':''" @click="getUrl(item)">{{item.name}}</div>-->
-          <!--<span class="iconfont iconcha" @click="delLink(item, '删除链接', index)"></span>-->
-          <!--</div>-->
-          <!--</div>-->
-          <!--</div>-->
         </div>
       </div>
-      <!--<div slot="footer" v-if="categoryId==9&&customNum==2">-->
-      <!--<Button @click="handleReset('customdate')">重置</Button>-->
-      <!--<Button type="primary" @click="handleSubmit('customdate')">确定</Button>-->
-      <!--</div>-->
       <div slot="footer">
         <Button @click="cancel">取消</Button>
         <Button type="primary" @click="handleSubmit('customdate')" v-if="currenType == 'custom'">确定</Button>
@@ -403,8 +410,10 @@ export default {
       categoryId: '', //左侧分类id
       treeSelect: [],
       customdate: {
-        // name:'',
         url: '',
+        appid: '',
+        mpUrl: '',
+        status: 1,
       },
       customNum: 1,
       ruleValidate: {
@@ -493,7 +502,13 @@ export default {
     handleSubmit(name) {
       this.$refs[name].validate((valid) => {
         if (valid) {
-          this.$emit('linkUrl', this.customdate.url);
+          let url = this.customdate.url;
+          if (this.customdate.status == 1) {
+            url = this.customdate.url;
+          } else {
+            url = this.customdate.mpUrl + '@APPID=' + this.customdate.appid;
+          }
+          this.$emit('linkUrl', url);
           this.modals = false;
           this.reset();
           // saveLink(this.customdate,this.categoryId).then(res=>{
@@ -838,7 +853,11 @@ export default {
     min-width: 121px;
   }
 }
-
+.radioGroup{
+  /deep/.ivu-radio-wrapper{
+    margin-right 30px;
+  }
+}
 .table_box {
   margin-top: 14px;
   display: flex;

+ 97 - 1
template/admin/src/pages/order/orderList/handle/orderDetails.vue

@@ -11,6 +11,7 @@
           <Col span="12">联系电话:{{ orderDatalist.orderInfo.user_phone || '' }}</Col>
           <Col span="12">收货地址:{{ orderDatalist.orderInfo.user_address || '' }}</Col>
         </Row>
+
         <Divider style="margin: 20px 0 !important" />
         <div class="ivu-description-list-title">订单信息</div>
         <Row class="mb10">
@@ -57,7 +58,10 @@
           <Col span="12" class="fontColor3 mb10" v-if="parseFloat(orderDatalist.orderInfo.back_integral)"
             >退回积分:{{ parseFloat(orderDatalist.orderInfo.back_integral) }}</Col
           >
-          <Col span="12" class="fontColor3 mb10" v-if="parseFloat(orderDatalist.orderInfo.gain_integral) && orderDatalist.orderInfo.paid == 1"
+          <Col
+            span="12"
+            class="fontColor3 mb10"
+            v-if="parseFloat(orderDatalist.orderInfo.gain_integral) && orderDatalist.orderInfo.paid == 1"
             >赠送积分:{{ parseFloat(orderDatalist.orderInfo.gain_integral) }}</Col
           >
           <Col span="12" class="mb10">创建时间:{{ orderDatalist.orderInfo._add_time }}</Col>
@@ -93,6 +97,98 @@
             >虚拟发货备注:{{ orderDatalist.orderInfo.fictitious_content }}</Col
           >
         </Row>
+
+        <div v-if="orderDatalist.orderInfo.invoice">
+          <Divider style="margin: 20px 0 !important" />
+          <div class="ivu-description-list-title">发票信息</div>
+          <Row class="mb10">
+            <Col span="12">发票抬头:{{ orderDatalist.orderInfo.invoice.name }}</Col>
+            <Col
+              span="12"
+              v-if="orderDatalist.orderInfo.invoice.header_type === 2 && orderDatalist.orderInfo.invoice.type === 1"
+              >企业税号:{{ orderDatalist.orderInfo.invoice.duty_number }}</Col
+            >
+          </Row>
+          <Row
+            class="mb10"
+            v-if="orderDatalist.orderInfo.invoice.header_type === 2 && orderDatalist.orderInfo.invoice.type === 1"
+          >
+            <Col span="12">发票类型: 电子普通发票</Col>
+            <Col span="12">发票抬头类型: 企业</Col>
+          </Row>
+          <Row
+            class="mb10"
+            v-if="orderDatalist.orderInfo.invoice.header_type === 1 && orderDatalist.orderInfo.invoice.type === 1"
+          >
+            <Col span="12">发票类型: 电子普通发票</Col>
+            <Col span="12">发票抬头类型: 个人</Col>
+          </Row>
+          <div class="ivu-description-list-title">联系信息</div>
+          <Row
+            class="mb10"
+            v-if="orderDatalist.orderInfo.invoice.header_type === 1 && orderDatalist.orderInfo.invoice.type === 1"
+          >
+            <Col span="12">真实姓名:{{ orderDatalist.orderInfo.invoice.name || '' }}</Col>
+            <Col span="12">联系电话:{{ orderDatalist.orderInfo.invoice.drawer_phone || '' }}</Col>
+          </Row>
+          <Row
+            class="mb10"
+            v-if="orderDatalist.orderInfo.invoice.header_type === 1 && orderDatalist.orderInfo.invoice.type === 1"
+          >
+            <Col span="12">联系邮箱:{{ orderDatalist.orderInfo.invoice.email || '' }}</Col>
+          </Row>
+          <Row
+            class="mb10"
+            v-if="orderDatalist.orderInfo.invoice.header_type === 2 && orderDatalist.orderInfo.invoice.type === 1"
+          >
+            <Col span="12">真实姓名:{{ orderDatalist.orderInfo.invoice.real_name || '' }}</Col>
+            <Col span="12">联系电话:{{ orderDatalist.orderInfo.invoice.user_phone || '' }}</Col>
+          </Row>
+          <Row
+            class="mb10"
+            v-if="orderDatalist.orderInfo.invoice.header_type === 2 && orderDatalist.orderInfo.invoice.type === 1"
+          >
+            <Col span="12">联系邮箱:{{ orderDatalist.orderInfo.invoice.email || '' }}</Col>
+            <Col span="12">联系电话:{{ orderDatalist.orderInfo.invoice.user_phone || '' }}</Col>
+          </Row>
+
+          <div v-if="orderDatalist.orderInfo.invoice.header_type === 2 && orderDatalist.orderInfo.invoice.type === 2">
+            <Row class="mb10">
+              <Col span="12"
+                >发票抬头: <span class="info">{{ orderDatalist.orderInfo.invoice.name }}</span></Col
+              >
+              <Col span="12"
+                >企业税号: <span class="info">{{ orderDatalist.orderInfo.invoice.duty_number }}</span></Col
+              >
+            </Row>
+            <Row class="mb10">
+              <Col span="12">发票类型: 纸质专用发票</Col>
+              <Col span="12">发票抬头类型: 企业</Col>
+            </Row>
+            <Row class="mb10">
+              <Col span="12"
+                >开户银行: <span class="info">{{ orderDatalist.orderInfo.invoice.bank }}</span></Col
+              >
+              <Col span="12"
+                >银行账号: <span class="info">{{ orderDatalist.orderInfo.invoice.card_number }}</span></Col
+              >
+            </Row>
+            <Row class="mb10">
+              <Col span="12">企业地址: {{ orderDatalist.orderInfo.invoice.address }}</Col>
+              <Col span="12">企业电话: {{ orderDatalist.orderInfo.invoice.drawer_phone }}</Col>
+            </Row>
+          </div>
+          <Row class="mb10" v-if="orderDatalist.orderInfo.invoice.is_invoice">
+            <Col span="12">发票编号: {{ orderDatalist.orderInfo.invoice.invoice_number }}</Col>
+          </Row>
+          <Row class="mb10" v-if="orderDatalist.orderInfo.invoice.is_invoice">
+            <Col span="12">发票备注: {{ orderDatalist.orderInfo.invoice.remark }}</Col>
+          </Row>
+          <Row class="mb10 fontColor1">
+            <Col span="12">开票状态:{{ orderDatalist.orderInfo.invoice.is_invoice ? '已开票' : '未开票' }}</Col>
+          </Row>
+        </div>
+
         <Divider style="margin: 20px 0 !important" v-if="orderDatalist.orderInfo.custom_form.length" />
         <div class="ivu-description-list-title" v-if="orderDatalist.orderInfo.custom_form.length">表单信息</div>
         <Row class="mb10" v-if="orderDatalist.orderInfo.custom_form.length">

+ 236 - 0
template/admin/src/pages/product/components/addReply.vue

@@ -0,0 +1,236 @@
+<template>
+  <Modal :value="visible" :z-index="2" title="添加自评" width="700" @on-ok="onOk" @on-cancel="onCancel">
+    <Form :model="formData" :label-width="125">
+      <FormItem label="商品">
+        <div class="upload-box" @click="callGoods">
+          <img v-if="goods.id" :src="goods.image" class="image" />
+          <Icon v-else type="ios-add" />
+        </div>
+      </FormItem>
+      <FormItem v-if="goods.id" label="商品规格">
+        <div class="upload-box" @click="callAttr">
+          <img v-if="attr.image" :src="attr.image" class="image" />
+          <Icon v-else type="ios-add" />
+        </div>
+      </FormItem>
+      <FormItem label="用户头像">
+        <div class="upload-box" @click="callPicture('单选')">
+          <img v-if="avatar.att_dir" :src="avatar.att_dir" class="image" />
+          <Button v-if="avatar.att_dir" shape="circle" icon="md-close" class="btn" @click.stop="removeUser"></Button>
+          <Icon v-else type="ios-add" />
+        </div>
+      </FormItem>
+      <FormItem label="用户名称">
+        <Input v-model="formData.nickname" placeholder="请输入用户名称"></Input>
+      </FormItem>
+      <FormItem label="评价文字">
+        <Input
+          v-model="formData.comment"
+          type="textarea"
+          :autosize="{ minRows: 2 }"
+          placeholder="请输入评价文字"
+        ></Input>
+      </FormItem>
+      <FormItem label="商品分数">
+        <Rate v-model="product_score" />
+      </FormItem>
+      <FormItem label="服务分数">
+        <Rate v-model="service_score" />
+      </FormItem>
+      <FormItem label="评价图片">
+        <div v-for="item in picture" :key="item.att_id" class="upload-box">
+          <img :src="item.att_dir" class="image" />
+          <Button shape="circle" icon="md-close" class="btn" @click="removePicture(item.att_id)"></Button>
+        </div>
+        <div v-if="picture.length < 8" class="upload-box" @click="callPicture('多选')">
+          <Icon type="ios-add" />
+        </div>
+      </FormItem>
+      <FormItem label="评价时间">
+        <DatePicker
+          :value="add_time"
+          type="datetime"
+          placeholder="请选择评论时间(不选择默认当前添加时间)"
+          style="width: 200px"
+          @on-change="onChange"
+        />
+      </FormItem>
+    </Form>
+    <template slot="footer">
+      <Button @click="onCancel">取消</Button>
+      <Button type="primary" @click="onOk">确定</Button>
+    </template>
+  </Modal>
+</template>
+
+<script>
+import { saveFictitiousReply } from '@/api/product';
+export default {
+  props: {
+    visible: {
+      type: Boolean,
+      default: false,
+    },
+    goods: {
+      type: Object,
+      default() {
+        return {};
+      },
+    },
+    attr: {
+      type: Object,
+      default() {
+        return {};
+      },
+    },
+    avatar: {
+      type: Object,
+      default() {
+        return {};
+      },
+    },
+    picture: {
+      type: Array,
+      default() {
+        return [];
+      },
+    },
+  },
+  data() {
+    return {
+      formData: {
+        avatar: '',
+        nickname: '',
+        comment: '',
+      },
+      product_score: 0,
+      service_score: 0,
+      pics: [],
+      add_time: '',
+    };
+  },
+  watch: {
+    picture(value) {
+      this.pics = value.map((item) => {
+        return item.att_dir;
+      });
+    },
+    visible(value) {
+      if (!value) {
+        this.formData.nickname = '';
+        this.formData.comment = '';
+        this.product_score = 0;
+        this.service_score = 0;
+        this.add_time = '';
+      }
+    },
+  },
+  methods: {
+    removeUser() {
+      this.avatar.att_dir = '';
+    },
+    removePicture(att_id) {
+      this.$emit('removePicture', att_id);
+    },
+    onChange(date) {
+      this.add_time = date;
+    },
+    callGoods() {
+      this.$emit('callGoods');
+    },
+    callAttr() {
+      this.$emit('callAttr');
+    },
+    callPicture(type) {
+      this.$emit('callPicture', type);
+    },
+    onOk() {
+      if (!this.goods.id) {
+        return this.$Message.error('请选择商品');
+      }
+      if (!this.attr.image) {
+        return this.$Message.error('请选择商品规格');
+      }
+      if (!this.avatar.att_dir) {
+        return this.$Message.error('请选择用户头像');
+      }
+      if (!this.formData.nickname) {
+        return this.$Message.error('请填写用户昵称');
+      }
+      if (!this.formData.comment) {
+        return this.$Message.error('请填写评论内容');
+      }
+      if (!this.product_score) {
+        return this.$Message.error('商品分数必须是1-5之间的整数');
+      }
+      if (!this.service_score) {
+        return this.$Message.error('服务分数必须是1-5之间的整数');
+      }
+      let data = {
+        image: {
+          image: this.goods.image,
+          product_id: this.goods.id,
+        },
+        suk: this.attr.suk,
+        avatar: this.avatar.att_dir,
+        nickname: this.formData.nickname,
+        comment: this.formData.comment,
+        product_score: this.product_score,
+        service_score: this.service_score,
+        pics: this.pics,
+        add_time: this.add_time,
+      };
+      saveFictitiousReply(data)
+        .then((res) => {
+          this.$Message.success(res.msg);
+          this.$emit('update:visible', false);
+        })
+        .catch((res) => {
+          this.$Message.error(res.msg);
+        });
+    },
+    onCancel() {
+      this.$emit('update:visible', false);
+    },
+  },
+};
+</script>
+
+<style lang="stylus" scoped>
+.upload-box {
+  position: relative;
+  display: inline-block;
+  width: 58px;
+  height: 58px;
+  border: 1px dashed #c0ccda;
+  border-radius: 4px;
+  box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.1);
+  vertical-align: middle;
+  text-align: center;
+  line-height: 58px;
+  cursor: pointer;
+
+  + .upload-box {
+    margin-left: 10px;
+  }
+
+  .ivu-icon {
+    vertical-align: middle;
+    font-size: 20px;
+  }
+
+  .image {
+    width: 100%;
+    height: 100%;
+  }
+
+  .btn {
+    position: absolute;
+    top: 0;
+    right: 0;
+    width: 20px;
+    height: 20px;
+    transform: translate(50%, -50%);
+  }
+}
+</style>

+ 10 - 7
template/admin/src/pages/product/productAdd/index.vue

@@ -2081,7 +2081,7 @@ export default {
       });
     },
     // 初始化数据展示
-    infoData(data) {
+    infoData(data, isCopy) {
       let cate_id = data.cate_id.map(Number);
       let label_id = data.label_id.map(Number);
       this.attrs = data.items || [];
@@ -2108,9 +2108,9 @@ export default {
         this.oneFormValidate = [data.attr];
       }
       this.formValidate.header = [];
-      this.generate(0);
+      this.generate(0, isCopy, data.attrs);
       // this.manyFormValidate = data.attrs;
-      this.$set(this, 'manyFormValidate', data.attrs);
+      // this.$set(this, 'manyFormValidate', data.attrs);
       this.spec_type = data.spec_type;
       this.formValidate.is_virtual = data.is_virtual;
       if (data.spec_type === 0) {
@@ -2139,7 +2139,7 @@ export default {
     //关闭淘宝弹窗并生成数据;
     onClose(data) {
       this.modals = false;
-      this.infoData(data);
+      this.infoData(data, 1);
     },
 
     checkMove(evt) {
@@ -2506,7 +2506,7 @@ export default {
       this.showIput = true;
     },
     // 立即生成
-    generate(type) {
+    generate(type, isCopy, arr) {
       generateAttrApi(
         {
           attrs: this.attrs,
@@ -2519,9 +2519,12 @@ export default {
         .then((res) => {
           let info = res.data.info,
             header1 = JSON.parse(JSON.stringify(info.header));
-          if (this.$route.params.id !== '0' && (this.$route.query.type != -1 || type)) {
+          if (this.$route.params.id !== '0' && (this.$route.query.type != -1 || type) && !isCopy) {
             this.manyFormValidate = info.value;
           }
+          if (isCopy) {
+            this.manyFormValidate = arr;
+          }
           let header = info.header;
           if ([1, 2].includes(this.formValidate.virtual_type)) {
             this.columnsInstalM = header;
@@ -2531,7 +2534,7 @@ export default {
             this.columnsInstalM = info.header;
           }
           this.checkAllGroup(this.formValidate.is_sub);
-          if (!this.$route.params.id && this.formValidate.spec_type === 1) {
+          if (!this.$route.params.id && this.formValidate.spec_type === 1 && !isCopy) {
             this.manyFormValidate.map((item) => {
               item.pic = this.formValidate.image;
             });

+ 186 - 1
template/admin/src/pages/product/productReply/index.vue

@@ -124,17 +124,72 @@
         <Button @click="cancels">取消</Button>
       </div>
     </Modal>
+    <addReply
+      :visible.sync="replyModal"
+      :goods="goodsData"
+      :attr="attrData"
+      :avatar="avatarData"
+      :picture="pictureData"
+      @callGoods="callGoods"
+      @callAttr="callAttr"
+      @callPicture="callPicture"
+      @removePicture="removePicture"
+    ></addReply>
+    <Modal v-model="goodsModal" title="选择商品" width="960" scrollable footer-hide>
+      <goodsList v-if="replyModal" @getProductId="getProductId"></goodsList>
+    </Modal>
+    <Modal v-model="attrModal" title="选择商品规格" width="960" scrollable footer-hide>
+      <Table :columns="tableColumns" :data="goodsData.attrs" height="500">
+        <template slot-scope="{ row, index }" slot="image">
+          <div class="product-data">
+            <img class="image" :src="row.image" />
+          </div>
+        </template>
+      </Table>
+    </Modal>
+    <Modal
+      v-model="pictureModal"
+      width="960px"
+      scrollable
+      footer-hide
+      closable
+      title="上传商品图"
+      :mask-closable="false"
+      :z-index="1"
+    >
+      <uploadPictures
+        :isChoice="isChoice"
+        @getPic="getPic"
+        @getPicD="getPicD"
+        :gridBtn="gridBtn"
+        :gridPic="gridPic"
+        v-if="pictureModal"
+      ></uploadPictures>
+    </Modal>
   </div>
 </template>
 
 <script>
 import { mapState } from 'vuex';
 import { replyListApi, setReplyApi, fictitiousReply } from '@/api/product';
+import addReply from '../components/addReply.vue';
+import goodsList from '@/components/goodsList/index';
+import uploadPictures from '@/components/uploadPictures';
+
 export default {
   name: 'product_productEvaluate',
+  components: {
+    addReply,
+    goodsList,
+    uploadPictures,
+  },
   data() {
     return {
       modals: false,
+      replyModal: false,
+      pictureModal: false,
+      goodsModal: false,
+      attrModal: false, // 选择商品规格
       grid: {
         xl: 7,
         lg: 10,
@@ -142,6 +197,20 @@ export default {
         sm: 12,
         xs: 24,
       },
+      gridPic: {
+        xl: 6,
+        lg: 8,
+        md: 12,
+        sm: 12,
+        xs: 12,
+      },
+      gridBtn: {
+        xl: 4,
+        lg: 8,
+        md: 8,
+        sm: 8,
+        xs: 8,
+      },
       formValidate: {
         is_reply: '',
         data: '',
@@ -166,8 +235,65 @@ export default {
           { text: '本年', val: 'year' },
         ],
       },
+      tableColumns: [
+        // {
+        //   type: "selection",
+        //   width: 60,
+        //   align: "center",
+        // },
+        {
+          width: 60,
+          align: 'center',
+          render: (h, params) => {
+            return h('Radio', {
+              props: {
+                value: params.row.unique === this.attrData.unique,
+              },
+              on: {
+                'on-change': () => {
+                  this.attrData = params.row;
+                  this.attrModal = false;
+                },
+              },
+            });
+          },
+        },
+        {
+          title: '图片',
+          slot: 'image',
+          width: 120,
+          align: 'center',
+        },
+        {
+          title: '规格',
+          key: 'suk',
+          align: 'center',
+          minWidth: 120,
+        },
+        {
+          title: '售价',
+          key: 'ot_price',
+          align: 'center',
+          minWidth: 120,
+        },
+        {
+          title: '优惠价',
+          key: 'price',
+          align: 'center',
+          minWidth: 120,
+        },
+      ],
       value: '45',
       tableList: [],
+      goodsAddType: '',
+      goodsData: {},
+      attrData: {},
+      avatarData: {},
+      pictureData: [],
+      selectProductAttrList: [],
+      isChoice: '',
+      picTit: '',
+      tableIndex: 0,
       total: 0,
       loading: false,
       columns: [
@@ -235,11 +361,21 @@ export default {
       this.formValidate.product_id = 0;
       this.getList();
     },
+    replyModal(value) {
+      if (!value) {
+        this.goodsData = {};
+        this.attrData = {};
+        this.avatarData = {};
+        this.pictureData = [];
+        this.getList();
+      }
+    },
   },
   methods: {
     // 添加虚拟评论;
     add() {
-      this.$modalForm(fictitiousReply(this.formValidate.product_id)).then(() => this.getList());
+      // this.$modalForm(fictitiousReply(this.formValidate.product_id)).then(() => this.getList());
+      this.replyModal = true;
     },
     oks() {
       this.modals = true;
@@ -339,6 +475,45 @@ export default {
       this.getList();
     },
     search() {},
+    callGoods() {
+      this.goodsModal = true;
+    },
+    callAttr() {
+      this.attrModal = true;
+    },
+    getProductId(goods) {
+      this.goodsData = goods;
+      this.goodsModal = false;
+      this.attrData.unique = '';
+    },
+    getPic(pc) {
+      this.avatarData = pc;
+      this.pictureModal = false;
+    },
+    getPicD(pc) {
+      let pictureData = [...this.pictureData];
+      pictureData = pictureData.concat(pc);
+      pictureData.sort((a, b) => a.att_id - b.att_id);
+      let picture = [];
+      for (let i = 0; i < pictureData.length; i++) {
+        if (pictureData[i + 1] && pictureData[i].att_id != pictureData[i + 1].att_id) {
+          picture.push(pictureData[i]);
+        }
+        if (!pictureData[i + 1]) {
+          picture.push(pictureData[i]);
+        }
+      }
+      this.pictureData = picture;
+      this.pictureModal = false;
+    },
+    callPicture(type) {
+      this.isChoice = type;
+      this.pictureModal = true;
+    },
+    removePicture(att_id) {
+      let index = this.pictureData.findIndex((item) => item.att_id === att_id);
+      this.pictureData.splice(index, 1);
+    },
   },
 };
 </script>
@@ -394,4 +569,14 @@ export default {
   height: 100%;
   display: block;
 }
+.product-data {
+  display: flex;
+  align-items: center;
+
+  .image {
+    width: 50px !important;
+    height: 50px !important;
+    margin-right: 10px;
+  }
+}
 </style>

+ 1 - 1
template/admin/src/pages/setting/devise/diyIndex.vue

@@ -976,7 +976,7 @@ export default {
     top 20px
     display: flex;
     flex-direction: column;
-    z-index: 1000;
+    z-index: 9;
   }
   /* min-width 700px; */
 }

+ 17 - 2
template/admin/src/pages/setting/storage/index.vue

@@ -29,6 +29,15 @@
           <p v-if="currentTab == 4">
             腾讯云cos开通方法:<a href="https://doc.crmeb.com/web/single/crmeb_v4/986" target="_blank">点击查看</a>
           </p>
+		  <p v-if="currentTab == 5">
+		    京东云cos开通方法:<a href="https://doc.crmeb.com/web/single/crmeb_v4/986" target="_blank">点击查看</a>
+		  </p>
+		  <p v-if="currentTab == 6">
+		    华为云cos开通方法:<a href="https://doc.crmeb.com/web/single/crmeb_v4/986" target="_blank">点击查看</a>
+		  </p>
+		  <p v-if="currentTab == 7">
+		    天翼云cos开通方法:<a href="https://doc.crmeb.com/web/single/crmeb_v4/986" target="_blank">点击查看</a>
+		  </p>
           <p>第一步: 添加【存储空间】(空间名称不能重复)</p>
           <p>第二步: 开启【使用状态】</p>
           <template v-if="currentTab == 2">
@@ -52,6 +61,9 @@
               <Radio label="2">七牛云存储</Radio>
               <Radio label="3">阿里云存储</Radio>
               <Radio label="4">腾讯云存储</Radio>
+			  <Radio label="5">京东云存储</Radio>
+			  <Radio label="6">华为云存储</Radio>
+			  <Radio label="7">天翼云存储</Radio>
             </RadioGroup>
             <!-- <i-switch
               v-model="localStorage"
@@ -322,7 +334,7 @@
       </Card>
     </div>
     <!-- 缩略图配置 -->
-    <div class="pt10" v-else-if="currentTab == 5"></div>
+    <div class="pt10" v-else-if="currentTab == 10">我去恶趣味我去</div>
     <div class="pt10" v-else>
       <Card :bordered="false" dis-hover class="ivu-mt">
         <Row type="flex" class="mb20">
@@ -482,7 +494,10 @@ export default {
         { label: '七牛云储存', value: '2' },
         { label: '阿里云储存', value: '3' },
         { label: '腾讯云储存', value: '4' },
-        // { label: "缩略图配置", value: "5" },
+		{ label: '京东云储存', value: '5' },
+		{ label: '华为云储存', value: '6' },
+		{ label: '天翼云储存', value: '7' },
+        // { label: "缩略图配置", value: "10" },
       ],
       columns: [
         {

+ 4 - 18
template/uni-app/components/guide/index.vue

@@ -44,9 +44,9 @@
 		},
 		mounted() {
 			this.timer()
-		},
-		onHide() {
-			clearInterval(this.timecount)
+		},
+		onHide() {
+			clearInterval(this.timecount)
 		},
 		methods: {
 			timer() {
@@ -70,22 +70,8 @@
 			jump(url) {
 				if (url) {
 					clearInterval(this.timecount)
-					if (url.indexOf("http") != -1) {
-						uni.navigateTo({
-							url: `/pages/annex/web_view/index?url=${url}`
-						});
-					} else {
-						uni.reLaunch({
-							url: url,
-							fail: () => {
-								uni.switchTab({
-									url
-								})
-							}
-						})
-					}
+					this.$util.JumpPath(url);
 				}
-
 			},
 		}
 	}

+ 1 - 1
template/uni-app/components/orderGoods/index.vue

@@ -29,7 +29,7 @@
 					</view>
 					<view class='text'>
 						<view class='acea-row row-between-wrapper'>
-							<view class='name line1'>{{item.productInfo.store_name}}</view>
+							<view class='name line2'>{{item.productInfo.store_name}}</view>
 							<view class='num'>x {{item.cart_num}}</view>
 						</view>
 						<view class='attr line1' v-if="item.productInfo.attrInfo">{{item.productInfo.attrInfo.suk}}

+ 3 - 3
template/uni-app/components/recommend/index.vue

@@ -17,16 +17,16 @@
 					<span class="pictrue_log_big pictrue_log_class"
 						v-if="item.activity && item.activity.type === '3'">{{$t(`拼团`)}}</span>
 				</view>
-				<view class='name line1'>{{item.store_name}}</view>
+				<view class='name line2'>{{item.store_name}}</view>
 				<view class='money font-color'>{{$t(`¥`)}}<text class='num'>{{item.price}}</text></view>
-				<view class='vip-money' v-if="item.vip_price && item.vip_price > 0 && item.base">
+				<!-- <view class='vip-money' v-if="item.vip_price && item.vip_price > 0 && item.base">
 					{{$t(`¥`)}}{{item.vip_price}}
 					<image src='/static/images/jvip.png' class="jvip"></image>
 				</view>
 				<view class='vip-money' v-if="item.vip_price && item.vip_price > 0 && item.is_vip">
 					{{$t(`¥`)}}{{item.vip_price}}
 					<image src='/static/images/vip.png'></image>
-				</view>
+				</view> -->
 			</view>
 		</view>
 	</view>

+ 366 - 383
template/uni-app/pages/activity/goods_combination/index.vue

@@ -1,384 +1,367 @@
-<template>
-	<view class="group-list" :style="colorStyle">
-		<view class="swiper" v-if="bannerList.length">
-			<swiper indicator-dots="true" :autoplay="true" :circular="circular" :interval="interval"
-				:duration="duration" indicator-color="rgba(0,0,0,0.3)">
-				<block v-for="(item,index) in bannerList" :key="index">
-					<swiper-item>
-						<view @click="goDetail(item)" class='slide-navigator acea-row row-between-wrapper'>
-							<image :src="item.img" class="slide-image"></image>
-						</view>
-					</swiper-item>
-				</block>
-			</swiper>
-		</view>
-		<view class="groupMember acea-row row-center-wrapper">
-			<view class="line">
-				<image src="../static/groupLine.png"></image>
-			</view>
-			<view class="member acea-row row-center-wrapper">
-				<view class="pictrue" v-for="(item,index) in pinkPeople" :key="index" v-if="index<6">
-					<image :src="item"></image>
-				</view>
-				<text style="margin-left: 10rpx;">{{pinkCount}}{{$t(`人参与`)}}</text>
-				<view class="pictrue" v-if="pinkPeople.length>5">
-					<image :src="pinkPeople[pinkPeople.length-1]"></image>
-					<view class="iconfont icon-gengduo1"></view>
-				</view>
-			</view>
-			<view class="line right">
-				<image src="../static/groupLine.png"></image>
-			</view>
-		</view>
-		<view class="list" v-if="combinationList.length">
-			<view class="item acea-row row-between-wrapper" v-for="(item,index) in combinationList" :key='index'
-				@tap="openSubcribe(item)">
-				<view class="pictrue">
-					<image :src="item.image"></image>
-				</view>
-				<view class="text">
-					<view class="name line2">{{item.title}}</view>
-					<view class="bottom acea-row row-between row-bottom">
-						<view class="y_money">
-							<view class="price">{{$t(`¥`)}}{{item.product_price}}</view>
-							<view class="money">{{$t(`¥`)}}<text class="num">{{item.price}}</text></view>
-						</view>
-						<view class="bnt acea-row row-center-wrapper" v-if="item.stock>0&&item.quota>0">
-							<view class="light">
-								<image src="../static/lightning.png"></image>
-							</view>
-							<view class="num">{{item.people}}{{$t(`人团`)}}</view>
-							<view class="go">{{$t(`去拼团`)}}</view>
-						</view>
-						<view class="bnt gray acea-row row-center-wrapper" v-else>{{$t(`已售罄`)}}</view>
-					</view>
-				</view>
-			</view>
-		</view>
-		<!-- #ifndef MP -->
-		<home></home>
-		<!-- #endif -->
-	</view>
-</template>
-
-<script>
-	import {
-		getCombinationList,
-		getCombinationBannerList,
-		getPink
-	} from '@/api/activity.js';
-	import {
-		openPinkSubscribe
-	} from '../../../utils/SubscribeMessage.js';
-	import home from '@/components/home/index.vue'
-	import colors from "@/mixins/color";
-	let app = getApp();
-	export default {
-		components: {
-			home
-		},
-		mixins: [colors],
-		data() {
-			return {
-				pinkPeople: [],
-				pinkCount: 0,
-				bannerList: [],
-				circular: true,
-				autoplay: true,
-				interval: 3000,
-				duration: 500,
-				combinationList: [],
-				limit: 10,
-				page: 1,
-				loading: false,
-				loadend: false
-			}
-		},
-		onLoad() {
-			uni.setNavigationBarTitle({
-				title: this.$t(`拼团列表`)
-			})
-			this.getCombinationList();
-			this.getBannerList();
-			this.getPink();
-		},
-		methods: {
-			getPink: function() {
-				getPink().then(res => {
-					this.pinkPeople = res.data.avatars;
-					this.pinkCount = res.data.pink_count;
-				})
-			},
-			getBannerList: function() {
-				getCombinationBannerList().then(res => {
-					this.bannerList = res.data;
-				})
-			},
-			goDetail(item) {
-				let url = item.link;
-				if (url.indexOf("http") != -1) {
-					// #ifdef H5
-					location.href = url
-					// #endif
-				} else {
-					if (['/pages/goods_cate/goods_cate', '/pages/order_addcart/order_addcart', '/pages/user/index',
-							'/pages/index/index'
-						]
-						.indexOf(url) == -1) {
-						uni.navigateTo({
-							url: url
-						})
-					} else {
-						uni.switchTab({
-							url: url
-						})
-					}
-				}
-			},
-			openSubcribe: function(item) {
-				let page = item;
-				// #ifndef MP
-				uni.navigateTo({
-					url: `/pages/activity/goods_combination_details/index?id=${item.id}`
-				});
-				// #endif
-				// #ifdef MP
-				uni.showLoading({
-					title: this.$t(`正在加载中`),
-				})
-				openPinkSubscribe().then(res => {
-					uni.hideLoading();
-					uni.navigateTo({
-						url: `/pages/activity/goods_combination_details/index?id=${item.id}`
-					});
-				}).catch(() => {
-					uni.hideLoading();
-				});
-				// #endif
-			},
-			getCombinationList: function() {
-				var that = this;
-				if (that.loadend) return;
-				if (that.loading) return;
-				var data = {
-					page: that.page,
-					limit: that.limit
-				};
-				this.loading = true
-				getCombinationList(data).then(function(res) {
-					var combinationList = that.combinationList;
-					var limit = that.limit;
-					that.page++;
-					that.loadend = limit > res.data.length;
-					that.combinationList = combinationList.concat(res.data);
-					that.page = that.data.page;
-					that.loading = false;
-				}).catch(() => {
-					that.loading = false
-				})
-			},
-		},
-		onReachBottom: function() {
-			this.getCombinationList();
-		},
-	}
-</script>
-
-<style lang="scss">
-	page {
-		// background-color: var(--view-theme) !important;
-	}
-
-	.group-list {
-		min-height: 100vh;
-		background-color: var(--view-theme) !important;
-		padding: 30rpx 0;
-
-		.swiper {
-			width: 100%;
-			position: relative;
-			box-sizing: border-box;
-			padding: 0 30rpx;
-
-			swiper {
-				width: 100%;
-				height: 300rpx;
-
-				.slide-image {
-					width: 100%;
-					height: 300rpx;
-					border-radius: 20rpx;
-				}
-
-				/deep/.uni-swiper-dot {
-					width: 8rpx !important;
-					height: 8rpx !important;
-					border-radius: 50%;
-				}
-
-				/deep/.uni-swiper-dot-active {
-					width: 18rpx !important;
-					border-radius: 4rpx;
-					background-color: var(--view-theme) !important;
-				}
-			}
-		}
-
-		.groupMember {
-			height: 100rpx;
-
-			.line {
-				width: 102rpx;
-				height: 4rpx;
-
-				&.right {
-					transform: rotate(180deg);
-				}
-
-				image {
-					width: 100%;
-					height: 100%;
-					display: block;
-				}
-			}
-
-			.member {
-				margin: 0 30rpx;
-				color: #fff;
-
-				.pictrue {
-					width: 46rpx;
-					height: 46rpx;
-					position: relative;
-
-					image {
-						border: 2rpx solid #fff;
-						width: 100%;
-						height: 100%;
-						border-radius: 50%;
-					}
-
-					&~.pictrue {
-						margin-left: -8rpx;
-					}
-
-					.iconfont {
-						position: absolute;
-						width: 43rpx;
-						height: 43rpx;
-						background: rgba(51, 51, 51, 0.6);
-						border-radius: 50%;
-						top: 2rpx;
-						left: 2rpx;
-						color: #fff;
-						font-size: 10rpx;
-						text-align: center;
-						line-height: 43rpx;
-					}
-				}
-			}
-		}
-
-		.list {
-			.item {
-				width: 690rpx;
-				height: 230rpx;
-				background-color: #fff;
-				border-radius: 14rpx;
-				padding: 0 22rpx;
-				margin: 0 auto 18rpx auto;
-
-				.pictrue {
-					width: 186rpx;
-					height: 186rpx;
-
-					image {
-						width: 100%;
-						height: 100%;
-						border-radius: 10rpx;
-					}
-				}
-
-				.text {
-					width: 440rpx;
-
-					.name {
-						color: #333;
-						font-size: 30rpx;
-						line-height: 38rpx;
-						height: 70rpx;
-					}
-
-					.bottom {
-						margin-top: 10rpx;
-
-						.y_money {
-							font-size: 24rpx;
-							color: #999;
-
-							.price {
-								text-decoration: line-through;
-							}
-
-							.money {
-								color: var(--view-priceColor);
-								font-weight: 600;
-
-								.num {
-									font-size: 34rpx;
-								}
-							}
-						}
-
-						.bnt {
-							height: 58rpx;
-							font-size: 24rpx;
-							text-align: center;
-							position: relative;
-							background-color: var(--view-theme);
-							border-radius: 28rpx;
-
-							.light {
-								position: absolute;
-								width: 28rpx;
-								height: 58rpx;
-								top: 0;
-								left: 50%;
-								margin-left: -8rpx;
-
-								image {
-									width: 100%;
-									height: 100%;
-								}
-							}
-
-							.num {
-								width: 120rpx;
-								background-color: rgba(255, 255, 255, 0.85);
-								color: var(--view-theme);
-								height: 100%;
-								line-height: 58rpx;
-								border-radius: 28rpx 0 14rpx 28rpx;
-							}
-
-							.go {
-								width: 112rpx;
-								background-color: var(--view-theme);
-								height: 100%;
-								line-height: 58rpx;
-								border-radius: 0 28rpx 28rpx 0;
-								color: #fff;
-							}
-
-							&.gray {
-								width: 148rpx;
-								background-color: #cccccc;
-								color: #fff;
-							}
-						}
-					}
-				}
-			}
-		}
-	}
+<template>
+	<view class="group-list" :style="colorStyle">
+		<view class="swiper" v-if="bannerList.length">
+			<swiper indicator-dots="true" :autoplay="true" :circular="circular" :interval="interval"
+				:duration="duration" indicator-color="rgba(0,0,0,0.3)">
+				<block v-for="(item,index) in bannerList" :key="index">
+					<swiper-item>
+						<view @click="goDetail(item)" class='slide-navigator acea-row row-between-wrapper'>
+							<image :src="item.img" class="slide-image"></image>
+						</view>
+					</swiper-item>
+				</block>
+			</swiper>
+		</view>
+		<view class="groupMember acea-row row-center-wrapper">
+			<view class="line">
+				<image src="../static/groupLine.png"></image>
+			</view>
+			<view class="member acea-row row-center-wrapper">
+				<view class="pictrue" v-for="(item,index) in pinkPeople" :key="index" v-if="index<6">
+					<image :src="item"></image>
+				</view>
+				<text style="margin-left: 10rpx;">{{pinkCount}}{{$t(`人参与`)}}</text>
+				<view class="pictrue" v-if="pinkPeople.length>5">
+					<image :src="pinkPeople[pinkPeople.length-1]"></image>
+					<view class="iconfont icon-gengduo1"></view>
+				</view>
+			</view>
+			<view class="line right">
+				<image src="../static/groupLine.png"></image>
+			</view>
+		</view>
+		<view class="list" v-if="combinationList.length">
+			<view class="item acea-row row-between-wrapper" v-for="(item,index) in combinationList" :key='index'
+				@tap="openSubcribe(item)">
+				<view class="pictrue">
+					<image :src="item.image"></image>
+				</view>
+				<view class="text">
+					<view class="name line2">{{item.title}}</view>
+					<view class="bottom acea-row row-between row-bottom">
+						<view class="y_money">
+							<view class="price">{{$t(`¥`)}}{{item.product_price}}</view>
+							<view class="money">{{$t(`¥`)}}<text class="num">{{item.price}}</text></view>
+						</view>
+						<view class="bnt acea-row row-center-wrapper" v-if="item.stock>0&&item.quota>0">
+							<view class="light">
+								<image src="../static/lightning.png"></image>
+							</view>
+							<view class="num">{{item.people}}{{$t(`人团`)}}</view>
+							<view class="go">{{$t(`去拼团`)}}</view>
+						</view>
+						<view class="bnt gray acea-row row-center-wrapper" v-else>{{$t(`已售罄`)}}</view>
+					</view>
+				</view>
+			</view>
+		</view>
+		<!-- #ifndef MP -->
+		<home></home>
+		<!-- #endif -->
+	</view>
+</template>
+
+<script>
+	import {
+		getCombinationList,
+		getCombinationBannerList,
+		getPink
+	} from '@/api/activity.js';
+	import {
+		openPinkSubscribe
+	} from '../../../utils/SubscribeMessage.js';
+	import home from '@/components/home/index.vue'
+	import colors from "@/mixins/color";
+	let app = getApp();
+	export default {
+		components: {
+			home
+		},
+		mixins: [colors],
+		data() {
+			return {
+				pinkPeople: [],
+				pinkCount: 0,
+				bannerList: [],
+				circular: true,
+				autoplay: true,
+				interval: 3000,
+				duration: 500,
+				combinationList: [],
+				limit: 10,
+				page: 1,
+				loading: false,
+				loadend: false
+			}
+		},
+		onLoad() {
+			uni.setNavigationBarTitle({
+				title: this.$t(`拼团列表`)
+			})
+			this.getCombinationList();
+			this.getBannerList();
+			this.getPink();
+		},
+		methods: {
+			getPink: function() {
+				getPink().then(res => {
+					this.pinkPeople = res.data.avatars;
+					this.pinkCount = res.data.pink_count;
+				})
+			},
+			getBannerList: function() {
+				getCombinationBannerList().then(res => {
+					this.bannerList = res.data;
+				})
+			},
+			goDetail(item) {
+				let url = item.link;
+				this.$util.JumpPath(url);
+			},
+			openSubcribe: function(item) {
+				let page = item;
+				// #ifndef MP
+				uni.navigateTo({
+					url: `/pages/activity/goods_combination_details/index?id=${item.id}`
+				});
+				// #endif
+				// #ifdef MP
+				uni.showLoading({
+					title: this.$t(`正在加载中`),
+				})
+				openPinkSubscribe().then(res => {
+					uni.hideLoading();
+					uni.navigateTo({
+						url: `/pages/activity/goods_combination_details/index?id=${item.id}`
+					});
+				}).catch(() => {
+					uni.hideLoading();
+				});
+				// #endif
+			},
+			getCombinationList: function() {
+				var that = this;
+				if (that.loadend) return;
+				if (that.loading) return;
+				var data = {
+					page: that.page,
+					limit: that.limit
+				};
+				this.loading = true
+				getCombinationList(data).then(function(res) {
+					var combinationList = that.combinationList;
+					var limit = that.limit;
+					that.page++;
+					that.loadend = limit > res.data.length;
+					that.combinationList = combinationList.concat(res.data);
+					that.page = that.data.page;
+					that.loading = false;
+				}).catch(() => {
+					that.loading = false
+				})
+			},
+		},
+		onReachBottom: function() {
+			this.getCombinationList();
+		},
+	}
+</script>
+
+<style lang="scss">
+	page {
+		// background-color: var(--view-theme) !important;
+	}
+
+	.group-list {
+		min-height: 100vh;
+		background-color: var(--view-theme) !important;
+		padding: 30rpx 0;
+
+		.swiper {
+			width: 100%;
+			position: relative;
+			box-sizing: border-box;
+			padding: 0 30rpx;
+
+			swiper {
+				width: 100%;
+				height: 300rpx;
+
+				.slide-image {
+					width: 100%;
+					height: 300rpx;
+					border-radius: 20rpx;
+				}
+
+				/deep/.uni-swiper-dot {
+					width: 8rpx !important;
+					height: 8rpx !important;
+					border-radius: 50%;
+				}
+
+				/deep/.uni-swiper-dot-active {
+					width: 18rpx !important;
+					border-radius: 4rpx;
+					background-color: var(--view-theme) !important;
+				}
+			}
+		}
+
+		.groupMember {
+			height: 100rpx;
+
+			.line {
+				width: 102rpx;
+				height: 4rpx;
+
+				&.right {
+					transform: rotate(180deg);
+				}
+
+				image {
+					width: 100%;
+					height: 100%;
+					display: block;
+				}
+			}
+
+			.member {
+				margin: 0 30rpx;
+				color: #fff;
+
+				.pictrue {
+					width: 46rpx;
+					height: 46rpx;
+					position: relative;
+
+					image {
+						border: 2rpx solid #fff;
+						width: 100%;
+						height: 100%;
+						border-radius: 50%;
+					}
+
+					&~.pictrue {
+						margin-left: -8rpx;
+					}
+
+					.iconfont {
+						position: absolute;
+						width: 43rpx;
+						height: 43rpx;
+						background: rgba(51, 51, 51, 0.6);
+						border-radius: 50%;
+						top: 2rpx;
+						left: 2rpx;
+						color: #fff;
+						font-size: 10rpx;
+						text-align: center;
+						line-height: 43rpx;
+					}
+				}
+			}
+		}
+
+		.list {
+			.item {
+				width: 690rpx;
+				height: 230rpx;
+				background-color: #fff;
+				border-radius: 14rpx;
+				padding: 0 22rpx;
+				margin: 0 auto 18rpx auto;
+
+				.pictrue {
+					width: 186rpx;
+					height: 186rpx;
+
+					image {
+						width: 100%;
+						height: 100%;
+						border-radius: 10rpx;
+					}
+				}
+
+				.text {
+					width: 440rpx;
+
+					.name {
+						color: #333;
+						font-size: 30rpx;
+						line-height: 38rpx;
+						height: 70rpx;
+					}
+
+					.bottom {
+						margin-top: 10rpx;
+
+						.y_money {
+							font-size: 24rpx;
+							color: #999;
+
+							.price {
+								text-decoration: line-through;
+							}
+
+							.money {
+								color: var(--view-priceColor);
+								font-weight: 600;
+
+								.num {
+									font-size: 34rpx;
+								}
+							}
+						}
+
+						.bnt {
+							height: 58rpx;
+							font-size: 24rpx;
+							text-align: center;
+							position: relative;
+							background-color: var(--view-theme);
+							border-radius: 28rpx;
+
+							.light {
+								position: absolute;
+								width: 28rpx;
+								height: 58rpx;
+								top: 0;
+								left: 50%;
+								margin-left: -8rpx;
+
+								image {
+									width: 100%;
+									height: 100%;
+								}
+							}
+
+							.num {
+								width: 120rpx;
+								background-color: rgba(255, 255, 255, 0.85);
+								color: var(--view-theme);
+								height: 100%;
+								line-height: 58rpx;
+								border-radius: 28rpx 0 14rpx 28rpx;
+							}
+
+							.go {
+								width: 112rpx;
+								background-color: var(--view-theme);
+								height: 100%;
+								line-height: 58rpx;
+								border-radius: 0 28rpx 28rpx 0;
+								color: #fff;
+							}
+
+							&.gray {
+								width: 148rpx;
+								background-color: #cccccc;
+								color: #fff;
+							}
+						}
+					}
+				}
+			}
+		}
+	}
 </style>

+ 25 - 4
template/uni-app/pages/activity/goods_combination_status/index.vue

@@ -29,7 +29,10 @@
 			<div class="tips font-num" v-else-if="pinkBool === 0">{{$t(`拼团中,还差`)}}{{ count }}{{$t(`人拼团成功`)}}</div>
 			<div class="list acea-row row-middle"
 				:class="[pinkBool === 1 || pinkBool === -1 ? 'result' : '', iShidden ? 'on' : '']">
-				<div class="pictrue"><img :src="pinkT.avatar" /></div>
+				<div class="pictrue"><img :src="pinkT.avatar" />
+					<view class="dumpling">{{$t(`团长`)}}</view>
+				</div>
+
 				<div class="acea-row row-middle" v-if="pinkAll.length > 0">
 					<div class="pictrue" v-for="(item, index) in pinkAll" :key="index"><img :src="item.avatar" /></div>
 				</div>
@@ -634,8 +637,9 @@
 					title: that.$t(`您的好友`) + that.userInfo.nickname + that.$t(`邀请您参团`) + that.storeCombination.title,
 					desc: that.storeCombination.title,
 					link: window.location.protocol + '//' + window.location.host +
-						'/pages/activity/goods_combination_status/index?id=' + that.pinkId + '&bargain=' + that.userInfo.uid +
-						'&spid=' +
+						'/pages/activity/goods_combination_status/index?id=' + that.pinkId + '&bargain=' + that
+						.userInfo.uid +
+						'&spid=' +
 						that.userInfo.uid,
 					imgUrl: that.storeCombination.image
 				};
@@ -825,7 +829,6 @@
 
 	.group-con .wrapper .list.result {
 		max-height: 240rpx;
-		overflow: hidden;
 	}
 
 	.group-con .wrapper .list.result.on {
@@ -838,6 +841,23 @@
 		margin: 0 0 29rpx 35rpx;
 	}
 
+	.group-con .wrapper .list .pictrue {
+		position: relative;
+	}
+
+	.group-con .wrapper .list .pictrue .dumpling {
+		width: 72rpx;
+		height: 32rpx;
+		font-size: 18rpx;
+		text-align: center;
+		color: #fff;
+		top: -12rpx;
+		right: -20rpx;
+		border-radius: 18rpx;
+		position: absolute;
+		background-color: var(--view-theme);
+	}
+
 	.group-con .wrapper .list .pictrue img,
 	.group-con .wrapper .list .pictrue image {
 		width: 100%;
@@ -931,6 +951,7 @@
 		position: relative;
 	}
 
+
 	.group-con .group-recommend .list .item .pictrue img {
 		width: 100%;
 		height: 100%;

+ 1 - 1
template/uni-app/pages/activity/goods_seckill/index.vue

@@ -29,7 +29,7 @@
 							<image :src='item.image'></image>
 						</view>
 						<view class='text acea-row row-column-around'>
-							<view class='name line1'>{{item.title}}</view>
+							<view class='name line2'>{{item.title}}</view>
 							<view class='money font-color'>{{$t(`¥`)}}
 								<text class='num font-color'>{{item.price}}</text>
 								<text class="y_money">{{$t(`¥`)}}{{item.ot_price}}</text>

Fichier diff supprimé car celui-ci est trop grand
+ 495 - 463
template/uni-app/pages/activity/presell/index.vue


+ 178 - 193
template/uni-app/pages/columnGoods/HotNewGoods/index.vue

@@ -1,194 +1,179 @@
-<template>
-	<div class="quality-recommend" :style="colorStyle">
-		<div class="slider-banner swiper">
-			<view class="swiper">
-				<swiper indicator-dots="true" :autoplay="autoplay" :circular="circular" :interval="interval"
-					:duration="duration" indicator-color="rgba(255,255,255,0.6)" indicator-active-color="#fff">
-					<block v-for="(item, index) in imgUrls" :key="index">
-						<swiper-item>
-							<image :src="item.img" class="slide-image" @click="goPages(item)"></image>
-						</swiper-item>
-					</block>
-				</swiper>
-			</view>
-		</div>
-		<div class="title acea-row row-center-wrapper">
-			<div class="line"></div>
-			<div class="name">
-				<span class="iconfont" :class="icon"></span>
-				{{ typeName[type]}}
-			</div>
-			<div class="line"></div>
-		</div>
-		<view class="wrapper">
-			<GoodList :bastList="goodsList" :is-sort="false"></GoodList>
-			<emptyPage v-if="goodsList.length == 0 && !isScroll" :title="$t(`暂无数据`)"></emptyPage>
-		</view>
-		<!-- #ifndef MP -->
-		<home></home>
-		<!-- #endif -->
-		<!-- <pageFooter></pageFooter> -->
-	</div>
-</template>
-<script>
-	import emptyPage from '@/components/emptyPage.vue';
-	import GoodList from '@/components/goodList';
-	import pageFooter from '@/components/pageFooter/index.vue';
-	import {
-		getGroomList
-	} from '@/api/store';
-	import {
-		goPage
-	} from '@/libs/order.js';
-	import home from '@/components/home/index.vue'
-	import colors from "@/mixins/color";
-	export default {
-		name: 'HotNewGoods',
-		components: {
-			GoodList,
-			emptyPage,
-			home,
-			pageFooter
-		},
-		props: {},
-		mixins: [colors],
-		data: function() {
-			return {
-				imgUrls: [],
-				goodsList: [],
-				name: '',
-				icon: '',
-				type: 0,
-				typeName: ['', this.$t(`精品推荐`), this.$t(`热门榜单`), this.$t(`首发新品`),
-					this.$t(`促销单品`)
-				],
-				autoplay: true,
-				circular: true,
-				interval: 3000,
-				duration: 500,
-				page: 1,
-				limit: 8,
-				isScroll: true,
-			};
-		},
-		onLoad: function(option) {
-			this.type = option.type;
-			this.titleInfo();
-			this.name = option.name;
-			// document.title = "精品推荐";
-			uni.setNavigationBarTitle({
-				title: option.name
-			});
-			this.getIndexGroomList();
-		},
-		methods: {
-			titleInfo: function() {
-				if (this.type === '1') {
-					this.icon = 'icon-jingpintuijian';
-				} else if (this.type === '2') {
-					this.icon = 'icon-remen';
-				} else if (this.type === '3') {
-					this.icon = 'icon-xinpin';
-				} else if (this.type === '4') {
-					this.icon = 'icon-xinpin';
-				}
-			},
-			goPages(item) {
-				let url = item.link || '';
-				goPage().then(res => {
-					if (url.indexOf('http') != -1) {
-						// #ifdef H5
-						location.href = url;
-						// #endif
-					} else {
-						if (['/pages/goods_cate/goods_cate', '/pages/order_addcart/order_addcart',
-								'/pages/user/index'
-							].indexOf(url) == -1) {
-							uni.navigateTo({
-								url: url
-							});
-						} else {
-							uni.navigateTo({
-								url: url
-							});
-						}
-					}
-				});
-			},
-			getIndexGroomList() {
-				if (!this.isScroll) return;
-				let that = this;
-				let type = this.type;
-				getGroomList(type, {
-						page: this.page,
-						limit: this.limit
-					})
-					.then(res => {
-						that.imgUrls = res.data.banner;
-						that.goodsList = that.goodsList.concat(res.data.list);
-						that.isScroll = res.data.list.length >= that.limit;
-						that.page++;
-					})
-					.catch(function(res) {
-						that.$util.Tips({
-							title: res
-						});
-					});
-			},
-			onReachBottom() {
-				this.getIndexGroomList();
-			}
-		}
-	}
-</script>
-<style lang="scss">
-	/deep/ .empty-box {
-		background-color: #f5f5f5;
-	}
-
-	.swiper,
-	swiper,
-	swiper-item,
-	.slide-image {
-		width: 100%;
-		height: 280rpx;
-	}
-
-	.quality-recommend {
-		.wrapper {
-			background: #fff;
-		}
-
-		.title {
-			height: 120rpx;
-			font-size: 32rpx;
-			color: #282828;
-			background-color: #f5f5f5;
-
-			.name {
-				margin: 0 20rpx;
-
-				.iconfont {
-					margin-right: 10rpx;
-				}
-			}
-
-			.line {
-				width: 190rpx;
-				height: 2rpx;
-				background-color: #e9e9e9;
-			}
-		}
-	}
-
-	.txt-bar {
-		padding: 20rpx 0;
-		text-align: center;
-		font-size: 26rpx;
-		color: #666;
-		background-color: #f5f5f5;
-	}
-	.acea-row {
-		flex-wrap: nowrap !important;
-	}
+<template>
+	<div class="quality-recommend" :style="colorStyle">
+		<div class="slider-banner swiper">
+			<view class="swiper">
+				<swiper indicator-dots="true" :autoplay="autoplay" :circular="circular" :interval="interval"
+					:duration="duration" indicator-color="rgba(255,255,255,0.6)" indicator-active-color="#fff">
+					<block v-for="(item, index) in imgUrls" :key="index">
+						<swiper-item>
+							<image :src="item.img" class="slide-image" @click="goPages(item)"></image>
+						</swiper-item>
+					</block>
+				</swiper>
+			</view>
+		</div>
+		<div class="title acea-row row-center-wrapper">
+			<div class="line"></div>
+			<div class="name">
+				<span class="iconfont" :class="icon"></span>
+				{{ typeName[type]}}
+			</div>
+			<div class="line"></div>
+		</div>
+		<view class="wrapper">
+			<GoodList :bastList="goodsList" :is-sort="false"></GoodList>
+			<emptyPage v-if="goodsList.length == 0 && !isScroll" :title="$t(`暂无数据`)"></emptyPage>
+		</view>
+		<!-- #ifndef MP -->
+		<home></home>
+		<!-- #endif -->
+		<!-- <pageFooter></pageFooter> -->
+	</div>
+</template>
+<script>
+	import emptyPage from '@/components/emptyPage.vue';
+	import GoodList from '@/components/goodList';
+	import pageFooter from '@/components/pageFooter/index.vue';
+	import {
+		getGroomList
+	} from '@/api/store';
+	import {
+		goPage
+	} from '@/libs/order.js';
+	import home from '@/components/home/index.vue'
+	import colors from "@/mixins/color";
+	export default {
+		name: 'HotNewGoods',
+		components: {
+			GoodList,
+			emptyPage,
+			home,
+			pageFooter
+		},
+		props: {},
+		mixins: [colors],
+		data: function() {
+			return {
+				imgUrls: [],
+				goodsList: [],
+				name: '',
+				icon: '',
+				type: 0,
+				typeName: ['', this.$t(`精品推荐`), this.$t(`热门榜单`), this.$t(`首发新品`),
+					this.$t(`促销单品`)
+				],
+				autoplay: true,
+				circular: true,
+				interval: 3000,
+				duration: 500,
+				page: 1,
+				limit: 8,
+				isScroll: true,
+			};
+		},
+		onLoad: function(option) {
+			this.type = option.type;
+			this.titleInfo();
+			this.name = option.name;
+			// document.title = "精品推荐";
+			uni.setNavigationBarTitle({
+				title: option.name
+			});
+			this.getIndexGroomList();
+		},
+		methods: {
+			titleInfo: function() {
+				if (this.type === '1') {
+					this.icon = 'icon-jingpintuijian';
+				} else if (this.type === '2') {
+					this.icon = 'icon-remen';
+				} else if (this.type === '3') {
+					this.icon = 'icon-xinpin';
+				} else if (this.type === '4') {
+					this.icon = 'icon-xinpin';
+				}
+			},
+			goPages(item) {
+				let url = item.link || '';
+				goPage().then(res => {
+					this.$util.JumpPath(url);
+				});
+			},
+			getIndexGroomList() {
+				if (!this.isScroll) return;
+				let that = this;
+				let type = this.type;
+				getGroomList(type, {
+						page: this.page,
+						limit: this.limit
+					})
+					.then(res => {
+						that.imgUrls = res.data.banner;
+						that.goodsList = that.goodsList.concat(res.data.list);
+						that.isScroll = res.data.list.length >= that.limit;
+						that.page++;
+					})
+					.catch(function(res) {
+						that.$util.Tips({
+							title: res
+						});
+					});
+			},
+			onReachBottom() {
+				this.getIndexGroomList();
+			}
+		}
+	}
+</script>
+<style lang="scss">
+	/deep/ .empty-box {
+		background-color: #f5f5f5;
+	}
+
+	.swiper,
+	swiper,
+	swiper-item,
+	.slide-image {
+		width: 100%;
+		height: 280rpx;
+	}
+
+	.quality-recommend {
+		.wrapper {
+			background: #fff;
+		}
+
+		.title {
+			height: 120rpx;
+			font-size: 32rpx;
+			color: #282828;
+			background-color: #f5f5f5;
+
+			.name {
+				margin: 0 20rpx;
+
+				.iconfont {
+					margin-right: 10rpx;
+				}
+			}
+
+			.line {
+				width: 190rpx;
+				height: 2rpx;
+				background-color: #e9e9e9;
+			}
+		}
+	}
+
+	.txt-bar {
+		padding: 20rpx 0;
+		text-align: center;
+		font-size: 26rpx;
+		color: #666;
+		background-color: #f5f5f5;
+	}
+
+	.acea-row {
+		flex-wrap: nowrap !important;
+	}
 </style>

+ 1 - 1
template/uni-app/pages/goods/goods_list/index.vue

@@ -40,7 +40,7 @@
 							v-if="item.activity && item.activity.type === '3'">{{$t(`拼团`)}}</span>
 					</view>
 					<view class='text' :class='is_switch==true?"":"on"'>
-						<view class='name line1'>{{item.store_name}}</view>
+						<view class='name line2'>{{item.store_name}}</view>
 						<view class='money font-color' :class='is_switch==true?"":"on"'>{{$t(`¥`)}}<text
 								class='num'>{{item.price}}</text></view>
 						<view class='vip acea-row row-between-wrapper' :class='is_switch==true?"":"on"'>

+ 60 - 1
template/uni-app/pages/goods/order_confirm/index.vue

@@ -10,7 +10,19 @@
 					<view class="item font-num" :class="shippingType == 1 ? 'on' : 'on2'" @tap="addressType(1)"
 						v-if='store_self_mention && is_shipping'></view>
 				</view>
+				<view class="add-title acea-row row-between-wrapper" v-if="!store_self_mention || !is_shipping">
+					<view class="acea-row row-middle">
+						<view class="icon" :class="shippingType==1?'orange':'red'">
+							{{shippingType==0?'商城配送':'门店自提'}}
+						</view>
+						<view class="text add-text line1" v-if="shippingType==0">{{$t(`由平台为您提供配送服务`)}}</view>
+						<view class="text add-text line1" v-if="shippingType==1">{{$t(`线上下单,到店自提`)}}</view>
+					</view>
+					<view class="text">{{shippingType == 0 ? $t('切换地址') : $t('切换门店')}}</view>
+					<view class='iconfont icon-jiantou'></view>
+				</view>
 				<view class='address acea-row row-between-wrapper' @tap='onAddress' v-if='shippingType == 0'>
+
 					<view class='addressCon' v-if="addressInfo.real_name || ''">
 						<view class='name'>{{addressInfo.real_name || ''}}
 							<text class='phone'>{{addressInfo.phone || ''}}</text>
@@ -34,7 +46,7 @@
 							</view>
 							<view class="line1"> {{system_store.address}}{{", " + system_store.detailed_address}}</view>
 						</view>
-						<view class='iconfont icon-jiantou'></view>
+						<!-- <view class='iconfont icon-jiantou'></view> -->
 					</block>
 					<block v-else>
 						<view>{{$t(`暂无门店信息`)}}</view>
@@ -1517,6 +1529,53 @@
 		background: linear-gradient(to bottom, var(--view-theme) 0%, #f5f5f5 100%);
 		padding-top: 100rpx;
 		margin-bottom: 12rpx;
+
+		.add-title {
+			height: 72rpx;
+			margin: 0 26rpx;
+			border-bottom: 1px solid #eee;
+			background-color: #fff;
+			width: 710rpx;
+			margin: 0 auto;
+			padding: 0 26rpx;
+			border-radius: 12rpx 12rpx 0 0;
+
+			.icon {
+				height: 32rpx;
+				background: #1890FF;
+				border-radius: 4rpx;
+				font-size: 20rpx;
+				font-weight: 400;
+				color: #FFFFFF;
+				text-align: center;
+				line-height: 32rpx;
+				padding: 0 6rpx;
+
+				&.orange {
+					background: #FE960F;
+				}
+
+				&.red {
+					background: #E93323;
+				}
+			}
+
+			.add-text {
+				margin-left: 14rpx;
+				width: 360rpx;
+			}
+
+			.text {
+				font-size: 24rpx;
+				font-weight: 400;
+				color: #999999;
+
+				.icon-jiantou {
+					display: inline-block;
+					font-size: 20rpx;
+				}
+			}
+		}
 	}
 
 	.order-submission .allAddress .nav {

+ 39 - 15
template/uni-app/pages/goods/order_details/index.vue

@@ -87,8 +87,8 @@
 						<view class="pictrue">
 							<image :src="codeSrc" mode=""></image>
 							<zb-code ref="qrcode" :show="codeShow" :cid="cid" :val="val" :size="size" :unit="unit"
-								:background="background" :foreground="foreground" :pdground="pdground" :icon="icon" :iconSize="iconsize"
-								:onval="onval" :loadMake="loadMake" @result="qrR" />
+								:background="background" :foreground="foreground" :pdground="pdground" :icon="icon"
+								:iconSize="iconsize" :onval="onval" :loadMake="loadMake" @result="qrR" />
 						</view>
 					</view>
 					<view class="gear">
@@ -155,8 +155,8 @@
 				:delivery_type="item.delivery_type" @confirmOrder="confirmOrder" @openSubcribe="openSubcribe">
 			</orderGoods>
 			<orderGoods :evaluate='evaluate' :deliveryType="orderInfo.shipping_type" :statusType="status.type"
-				:sendType="orderInfo.delivery_type" :orderId="order_id" :oid="orderInfo.id" :cartInfo="cartInfo" :pid="pid"
-				:jump="true" :refund_status="orderInfo.refund_status" :paid="orderInfo.paid"
+				:sendType="orderInfo.delivery_type" :orderId="order_id" :oid="orderInfo.id" :cartInfo="cartInfo"
+				:pid="pid" :jump="true" :refund_status="orderInfo.refund_status" :paid="orderInfo.paid"
 				:virtualType="orderInfo.virtual_type" @openSubcribe="openSubcribe">
 			</orderGoods>
 			<!-- #ifdef H5 || APP-PLUS -->
@@ -231,7 +231,8 @@
 						</view>
 						<!-- #endif -->
 						<!-- #ifdef H5 -->
-						<view v-if="orderInfo.virtual_type == 1" class='copy copy-data' :data-clipboard-text="orderInfo.remark">
+						<view v-if="orderInfo.virtual_type == 1" class='copy copy-data'
+							:data-clipboard-text="orderInfo.remark">
 							{{$t(`复制`)}}
 						</view>
 						<!-- #endif -->
@@ -250,6 +251,7 @@
 					<view v-if="item.label !== 'img'">{{item.title}}:</view>
 					<view v-if="item.label !== 'img'" class='conter'>{{item.value}}</view>
 				</view>
+				<view class="copy-text" @click="copyText()">{{$t(`复制`)}}</view>
 			</view>
 			<!-- 退款订单详情 -->
 			<view class='wrapper' v-if="isGoodsReturn && orderInfo.cartInfo[0].productInfo.virtual_type != 3">
@@ -292,8 +294,8 @@
 					</view>
 					<view class='item acea-row row-between'>
 						<view>{{$t(`送货人电话`)}}:</view>
-						<view class='conter acea-row row-middle row-right'>{{orderInfo.delivery_id || ''}}<text class='copy'
-								@tap='goTel'>{{$t(`拨打`)}}</text></view>
+						<view class='conter acea-row row-middle row-right'>{{orderInfo.delivery_id || ''}}<text
+								class='copy' @tap='goTel'>{{$t(`拨打`)}}</text></view>
 					</view>
 				</view>
 				<view class='wrapper' v-else-if='orderInfo.delivery_type=="fictitious"'>
@@ -343,7 +345,8 @@
 							{{orderInfo.help_info.pay_nickname || ''}}
 						</view>
 					</view>
-					{{$t(`总代付`)}}:<text class='money font-color'>{{$t(`¥`)}}{{parseFloat(orderInfo.pay_price).toFixed(2)}}</text>
+					{{$t(`总代付`)}}:<text
+						class='money font-color'>{{$t(`¥`)}}{{parseFloat(orderInfo.pay_price).toFixed(2)}}</text>
 				</view>
 			</view>
 			<view style='height:120rpx;'></view>
@@ -375,8 +378,8 @@
 						hover-class='none' :url="'/pages/goods/goods_logistics/index?orderId='+ orderInfo.order_id">
 						{{$t(`查看物流`)}}
 					</navigator>
-					<view class='bnt bg-color' v-if="orderInfo.type == 3 && orderInfo.refund_type == 0 && orderInfo.paid"
-						@tap='goJoinPink'>
+					<view class='bnt bg-color'
+						v-if="orderInfo.type == 3 && orderInfo.refund_type == 0 && orderInfo.paid" @tap='goJoinPink'>
 						{{$t(`查看拼团`)}}
 					</view>
 					<view class='bnt bg-color' v-if="status.class_status==3 && !split.length" @click='confirmOrder()'>
@@ -396,7 +399,8 @@
 						:url="'/pages/goods/goods_logistics/index?orderId='+ orderInfo.order_id + '&type=refund'">
 						{{$t(`查看退货物流`)}}
 					</navigator>
-					<view class='bnt cancel' v-if="status.type==4 &&  !split.length || status.type == -2" @tap='delOrder'>
+					<view class='bnt cancel' v-if="status.type==4 &&  !split.length || status.type == -2"
+						@tap='delOrder'>
 						{{$t(`删除订单`)}}
 					</view>
 				</view>
@@ -425,9 +429,9 @@
 		</invoiceModal>
 		<view class="mask invoice-mask" v-if="aleartStatus" @click="aleartStatus = false"></view>
 		<view class="mask more-mask" v-if="moreBtn" @click="moreBtn = false"></view>
-		<invoice-picker :inv-show="invShow" :is-special="special_invoice" :url-query="urlQuery" :inv-checked="invChecked"
-			:order-id='order_id' :inv-list="invList" :is-order="1" @inv-close="invClose" @inv-change="invSub"
-			@inv-cancel="invCancel">
+		<invoice-picker :inv-show="invShow" :is-special="special_invoice" :url-query="urlQuery"
+			:inv-checked="invChecked" :order-id='order_id' :inv-list="invList" :is-order="1" @inv-close="invClose"
+			@inv-change="invSub" @inv-cancel="invCancel">
 		</invoice-picker>
 	</view>
 </template>
@@ -978,6 +982,17 @@
 				});
 			},
 			// #endif
+			copyText(text) {
+				let str = ''
+				this.customForm.map(e => {
+					if (e.label !== 'img') {
+						str += e.title + e.value
+					}
+				})
+				uni.setClipboardData({
+					data: str,
+				});
+			},
 			// #ifdef H5
 			copyAddress() {
 				// console.log('1111111111111')
@@ -2174,6 +2189,15 @@
 		}
 	}
 
+	.copy-text {
+		width: max-content;
+		font-size: 10px;
+		border-radius: 1px;
+		border: 0.5px solid #666;
+		padding: 1px 7px;
+		margin-left: auto;
+	}
+
 	.upload .pictrue {
 		display: inline-block;
 		margin: 22rpx 17rpx 20rpx 0;
@@ -2186,4 +2210,4 @@
 		width: 100%;
 		height: 100%;
 	}
-</style>
+</style>

+ 29 - 19
template/uni-app/pages/goods/order_list/index.vue

@@ -270,25 +270,35 @@
 					return that.$util.Tips({
 						title: that.$t(`缺少订单号无法取消订单`)
 					});
-				orderCancel(order_id)
-					.then(res => {
-						return that.$util.Tips({
-								title: res.msg,
-								icon: 'success'
-							},
-							function() {
-								that.orderList.splice(index, 1);
-								that.$set(that, 'orderList', that.orderList);
-								that.$set(that.orderData, 'unpaid_count', that.orderData.unpaid_count - 1);
-								that.getOrderData();
-							}
-						);
-					})
-					.catch(err => {
-						return that.$util.Tips({
-							title: err
-						});
-					});
+				uni.showModal({
+					title: this.$t(`提示`),
+					content: this.$t(`确认取消该订单`),
+					success: function(res) {
+						if (res.confirm) {
+							orderCancel(order_id)
+								.then(res => {
+									return that.$util.Tips({
+											title: res.msg,
+											icon: 'success'
+										},
+										function() {
+											that.orderList.splice(index, 1);
+											that.$set(that, 'orderList', that.orderList);
+											that.$set(that.orderData, 'unpaid_count', that
+												.orderData.unpaid_count - 1);
+											that.getOrderData();
+										}
+									);
+								})
+								.catch(err => {
+									return that.$util.Tips({
+										title: err
+									});
+								});
+						} else if (res.cancel) {}
+					}
+				});
+
 			},
 			/**
 			 * 打开支付组件

+ 11 - 0
template/uni-app/pages/goods_cate/goods_cate1.vue

@@ -35,6 +35,16 @@
 								<view class='line'></view>
 							</view>
 							<view class='list acea-row'>
+								<navigator hover-class='none'
+									:url='"/pages/goods/goods_list/index?cid="+item.id+"&title="+item.cate_name'
+									class='item acea-row row-column row-middle'>
+									<view class='picture'>
+										<easy-loadimage mode="widthFix" :image-src="item.pic || defimg">
+										</easy-loadimage>
+										<!-- <image src="/static/images/sort-img.png" v-else></image> -->
+									</view>
+									<view class='name line1'>{{$t(`全部商品`)}}</view>
+								</navigator>
 								<block v-for="(itemn,indexn) in item.children" :key="indexn">
 									<navigator hover-class='none'
 										:url='"/pages/goods/goods_list/index?sid="+itemn.id+"&title="+itemn.cate_name'
@@ -86,6 +96,7 @@
 		},
 		data() {
 			return {
+				defimg: require('@/static/images/2-002.png'),
 				navlist: [],
 				productList: [],
 				navActive: 0,

+ 1 - 10
template/uni-app/pages/index/diy/components/activeParty.vue

@@ -54,16 +54,7 @@
 		methods: {
 			goDetail(item) {
 				let urls = item.info[2].value
-				if (['/pages/goods_cate/goods_cate', '/pages/order_addcart/order_addcart', '/pages/user/index']
-					.indexOf(urls) == -1) {
-					uni.navigateTo({
-						url: urls
-					})
-				} else {
-					uni.switchTab({
-						url: urls
-					})
-				}
+				this.$util.JumpPath(urls);
 			}
 		}
 	}

+ 240 - 252
template/uni-app/pages/index/diy/components/menus.vue

@@ -1,253 +1,241 @@
-<template>
-	<view v-show="!isSortType && menus.length" :class="bgStyle?'borderRadius15':''" :style="{background:bgColor,margin:'0 '+prConfig*2+'rpx',marginTop:mbConfig*2+'rpx'}">
-		<view v-if="isMany">
-			<view class="swiper">
-				<swiper :interval="interval" :duration="duration" :style="'height:'+(navHigh*2+17)+'rpx;'" @change='bannerfun'>
-					<block>
-						<swiper-item v-for="(item,indexw) in menuList" :key="indexw">
-							<view class="nav acea-row" :id="'nav' + indexw">
-								<view :style="'color:' + titleColor" class="item" :class="number===1?'four':number===2?'five':''" v-for="(itemn,indexn) in item.list" :key="indexn" @click="menusTap(itemn.info[1].value)">
-									<view class="pictrue skeleton-radius" :class="menuStyle?'':'on'">
-										<image :src="itemn.img" mode="aspectFill"></image>
-									</view>
-									<view class="menu-txt">{{ $t(itemn.info[0].value) }}</view>
-								</view>
-							</view>
-						</swiper-item>
-					</block>
-				</swiper>
-			</view>
-			<view class="dot acea-row row-center-wrapper" v-if="docConfig<2">
-				<view class="dot-item" :class="{ 'line_dot-item': docConfig === 0,'': docConfig === 1}" :style="active==index?'background:'+ dotColor:''" v-for="(item,index) in menuList"></view>
-			</view>
-		</view>
-		<view class="nav oneNav" v-else>
-			<scroll-view scroll-x="true" style="white-space: nowrap; display: flex" show-scrollbar="false">
-				<block v-for="(item, index) in menus" :key="index">
-					<view class="item" :style="'color:' + titleColor" @click="menusTap(item.info[1].value)">
-						<view class="pictrue skeleton-radius" :class="menuStyle?'':'on'">
-							<image :src="item.img" mode="aspectFill"></image>
-						</view>
-						<view class="menu-txt">{{ $t(item.info[0].value) }}</view>
-					</view>
-				</block>
-			</scroll-view>
-		</view>
-	</view>
-</template>
-
-<script>
-	export default {
-		name: 'menus',
-		props: {
-			dataConfig: {
-				type: Object,
-				default: () => {}
-			},
-			isSortType: {
-				type: String | Number,
-				default: 0
-			}
-		},
-		data() {
-			return {
-				interval: 3000,
-				duration: 500,
-				menus: this.dataConfig.menuConfig.list || [],
-				titleColor: this.dataConfig.titleColor.color[0].item,
-				mbConfig: this.dataConfig.mbConfig.val,
-				rowsNum: this.dataConfig.rowsNum.type,
-				number: this.dataConfig.number.type,
-				isMany: this.dataConfig.tabConfig.tabVal,
-				menuStyle: this.dataConfig.menuStyle.type,
-				docConfig: this.dataConfig.pointerStyle.type,
-				dotColor: this.dataConfig.pointerColor.color[0].item,
-				bgColor: this.dataConfig.bgColor.color[0].item,
-				bgStyle: this.dataConfig.bgStyle.type,
-				prConfig: this.dataConfig.prConfig.val,
-				navHigh: 0,
-				menuList: [],
-				active: 0
-			};
-		},
-		created() {},
-		mounted() {
-			if (this.rowsNum === 0) {
-				if (this.number === 0) {
-					this.pageNum(6)
-				} else if (this.number === 1) {
-					this.pageNum(8)
-				} else {
-					this.pageNum(10)
-				}
-			} else if (this.rowsNum === 1) {
-				if (this.number === 0) {
-					this.pageNum(9)
-				} else if (this.number === 1) {
-					this.pageNum(12)
-				} else {
-					this.pageNum(15)
-				}
-			} else {
-				if (this.number === 0) {
-					this.pageNum(12)
-				} else if (this.number === 1) {
-					this.pageNum(16)
-				} else {
-					this.pageNum(20)
-				}
-			}
-			this.$nextTick(() => {
-				if (this.menuList.length&&this.isMany) {
-					let that = this
-					// #ifdef H5
-					that.menuHeight()
-					// #endif
-					// #ifndef H5
-					setTimeout(() => {
-						that.menuHeight()
-					},100)
-					// #endif
-				}
-			})
-		},
-		methods: {
-			bannerfun(e) {
-				this.active = e.detail.current;
-			},
-			menuHeight(){
-				let that = this;
-				const query = uni.createSelectorQuery().in(this);
-				query.select('#nav0').boundingClientRect(data => {
-					that.navHigh = data.height;
-				}).exec();
-			},
-			pageNum(num) {
-				let count = Math.ceil(this.menus.length / num);
-				let goodArray = new Array();
-				for (let i = 0; i < count; i++) {
-					let list = this.menus.slice(i * num, i * num + num);
-					if (list.length)
-						goodArray.push({
-							list: list
-						});
-				}
-				this.$set(this, 'menuList', goodArray);
-			},
-			menusTap(url) {
-				if (url.indexOf("http") != -1) {
-					// #ifdef H5
-					location.href = url
-					// #endif
-					// #ifdef MP || APP-PLUS
-					uni.navigateTo({
-						url: `/pages/annex/web_view/index?url=${url}`
-					});
-					// #endif
-				} else {
-					if (['/pages/goods_cate/goods_cate', '/pages/order_addcart/order_addcart', '/pages/user/index']
-						.indexOf(url) == -1) {
-						uni.navigateTo({
-							url: url
-						})
-					} else {
-						uni.reLaunch({
-							url: url
-						})
-					}
-				}
-			}
-		}
-	};
-</script>
-
-<style lang="scss">
-	.dot {
-		width: 100%;
-		padding-bottom: 20rpx;
-	
-		.instruct {
-			width: 50rpx;
-			height: 36rpx;
-			line-height: 36rpx;
-			background-color: rgba(0, 0, 0, 0.8);
-			color: #fff;
-			border-radius: 16rpx;
-			font-size: 24rpx;
-			text-align: center;
-		}
-	
-		.dot-item {
-			width: 10rpx;
-			height: 10rpx;
-			background: rgba(0, 0, 0, .4);
-			border-radius: 50%;
-			margin: 0 4px;
-	
-			&.line_dot-item {
-				width: 20rpx;
-				height: 5rpx;
-				border-radius: 3rpx;
-			}
-		}
-	}
-	.nav {
-		&.oneNav{
-			padding-bottom: 25rpx;
-		}
-		.item {
-			margin-top: 30rpx;
-			width: 160rpx;
-			text-align: center;
-			font-size: 24rpx;
-			display: inline-block;
-
-			.pictrue {
-				width: 90rpx;
-				height: 90rpx;
-				margin: 0 auto;
-
-				image {
-					width: 100%;
-					height: 100%;
-					border-radius: 50%;
-				}
-
-				&.on {
-					image {
-						border-radius: 0;
-					}
-				}
-			}
-
-			.menu-txt {
-				margin-top: 15rpx;
-			}
-		}
-	}
-
-	.swiper {
-		z-index: 20;
-		position: relative;
-		overflow: hidden;
-		.nav {
-			.item {
-				width: 33.3333%;
-
-				&.four {
-					width: 25%;
-				}
-
-				&.five {
-					width: 20%;
-				}
-			}
-		}
-
-		swiper,
-		.swiper-item {
-			width: 100%;
-			display: block;
-		}
-	}
+<template>
+	<view v-show="!isSortType && menus.length" :class="bgStyle?'borderRadius15':''"
+		:style="{background:bgColor,margin:'0 '+prConfig*2+'rpx',marginTop:mbConfig*2+'rpx'}">
+		<view v-if="isMany">
+			<view class="swiper">
+				<swiper :interval="interval" :duration="duration" :style="'height:'+(navHigh*2+17)+'rpx;'"
+					@change='bannerfun'>
+					<block>
+						<swiper-item v-for="(item,indexw) in menuList" :key="indexw">
+							<view class="nav acea-row" :id="'nav' + indexw">
+								<view :style="'color:' + titleColor" class="item"
+									:class="number===1?'four':number===2?'five':''" v-for="(itemn,indexn) in item.list"
+									:key="indexn" @click="menusTap(itemn.info[1].value)">
+									<view class="pictrue skeleton-radius" :class="menuStyle?'':'on'">
+										<image :src="itemn.img" mode="aspectFill"></image>
+									</view>
+									<view class="menu-txt">{{ $t(itemn.info[0].value) }}</view>
+								</view>
+							</view>
+						</swiper-item>
+					</block>
+				</swiper>
+			</view>
+			<view class="dot acea-row row-center-wrapper" v-if="docConfig<2">
+				<view class="dot-item" :class="{ 'line_dot-item': docConfig === 0,'': docConfig === 1}"
+					:style="active==index?'background:'+ dotColor:''" v-for="(item,index) in menuList"></view>
+			</view>
+		</view>
+		<view class="nav oneNav" v-else>
+			<scroll-view scroll-x="true" style="white-space: nowrap; display: flex" show-scrollbar="false">
+				<block v-for="(item, index) in menus" :key="index">
+					<view class="item" :style="'color:' + titleColor" @click="menusTap(item.info[1].value)">
+						<view class="pictrue skeleton-radius" :class="menuStyle?'':'on'">
+							<image :src="item.img" mode="aspectFill"></image>
+						</view>
+						<view class="menu-txt">{{ $t(item.info[0].value) }}</view>
+					</view>
+				</block>
+			</scroll-view>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		name: 'menus',
+		props: {
+			dataConfig: {
+				type: Object,
+				default: () => {}
+			},
+			isSortType: {
+				type: String | Number,
+				default: 0
+			}
+		},
+		data() {
+			return {
+				interval: 3000,
+				duration: 500,
+				menus: this.dataConfig.menuConfig.list || [],
+				titleColor: this.dataConfig.titleColor.color[0].item,
+				mbConfig: this.dataConfig.mbConfig.val,
+				rowsNum: this.dataConfig.rowsNum.type,
+				number: this.dataConfig.number.type,
+				isMany: this.dataConfig.tabConfig.tabVal,
+				menuStyle: this.dataConfig.menuStyle.type,
+				docConfig: this.dataConfig.pointerStyle.type,
+				dotColor: this.dataConfig.pointerColor.color[0].item,
+				bgColor: this.dataConfig.bgColor.color[0].item,
+				bgStyle: this.dataConfig.bgStyle.type,
+				prConfig: this.dataConfig.prConfig.val,
+				navHigh: 0,
+				menuList: [],
+				active: 0
+			};
+		},
+		created() {},
+		mounted() {
+			if (this.rowsNum === 0) {
+				if (this.number === 0) {
+					this.pageNum(6)
+				} else if (this.number === 1) {
+					this.pageNum(8)
+				} else {
+					this.pageNum(10)
+				}
+			} else if (this.rowsNum === 1) {
+				if (this.number === 0) {
+					this.pageNum(9)
+				} else if (this.number === 1) {
+					this.pageNum(12)
+				} else {
+					this.pageNum(15)
+				}
+			} else {
+				if (this.number === 0) {
+					this.pageNum(12)
+				} else if (this.number === 1) {
+					this.pageNum(16)
+				} else {
+					this.pageNum(20)
+				}
+			}
+			this.$nextTick(() => {
+				if (this.menuList.length && this.isMany) {
+					let that = this
+					// #ifdef H5
+					that.menuHeight()
+					// #endif
+					// #ifndef H5
+					setTimeout(() => {
+						that.menuHeight()
+					}, 100)
+					// #endif
+				}
+			})
+		},
+		methods: {
+			bannerfun(e) {
+				this.active = e.detail.current;
+			},
+			menuHeight() {
+				let that = this;
+				const query = uni.createSelectorQuery().in(this);
+				query.select('#nav0').boundingClientRect(data => {
+					that.navHigh = data.height;
+				}).exec();
+			},
+			pageNum(num) {
+				let count = Math.ceil(this.menus.length / num);
+				let goodArray = new Array();
+				for (let i = 0; i < count; i++) {
+					let list = this.menus.slice(i * num, i * num + num);
+					if (list.length)
+						goodArray.push({
+							list: list
+						});
+				}
+				this.$set(this, 'menuList', goodArray);
+			},
+			menusTap(url) {
+				this.$util.JumpPath(url);
+			}
+		}
+	};
+</script>
+
+<style lang="scss">
+	.dot {
+		width: 100%;
+		padding-bottom: 20rpx;
+
+		.instruct {
+			width: 50rpx;
+			height: 36rpx;
+			line-height: 36rpx;
+			background-color: rgba(0, 0, 0, 0.8);
+			color: #fff;
+			border-radius: 16rpx;
+			font-size: 24rpx;
+			text-align: center;
+		}
+
+		.dot-item {
+			width: 10rpx;
+			height: 10rpx;
+			background: rgba(0, 0, 0, .4);
+			border-radius: 50%;
+			margin: 0 4px;
+
+			&.line_dot-item {
+				width: 20rpx;
+				height: 5rpx;
+				border-radius: 3rpx;
+			}
+		}
+	}
+
+	.nav {
+		&.oneNav {
+			padding-bottom: 25rpx;
+		}
+
+		.item {
+			margin-top: 30rpx;
+			width: 160rpx;
+			text-align: center;
+			font-size: 24rpx;
+			display: inline-block;
+
+			.pictrue {
+				width: 90rpx;
+				height: 90rpx;
+				margin: 0 auto;
+
+				image {
+					width: 100%;
+					height: 100%;
+					border-radius: 50%;
+				}
+
+				&.on {
+					image {
+						border-radius: 0;
+					}
+				}
+			}
+
+			.menu-txt {
+				margin-top: 15rpx;
+			}
+		}
+	}
+
+	.swiper {
+		z-index: 20;
+		position: relative;
+		overflow: hidden;
+
+		.nav {
+			.item {
+				width: 33.3333%;
+
+				&.four {
+					width: 25%;
+				}
+
+				&.five {
+					width: 20%;
+				}
+			}
+		}
+
+		swiper,
+		.swiper-item {
+			width: 100%;
+			display: block;
+		}
+	}
 </style>

+ 133 - 137
template/uni-app/pages/index/diy/components/news.vue

@@ -1,138 +1,134 @@
-<template>
-	<view v-show="!isSortType">
-		<view class='news acea-row row-middle' :class="{pageOn:bgStyle===1}" v-if="itemNew.length" :style="'margin:0 '+prConfig*2+'rpx;margin-top:'+mbConfig*2+'rpx;color:'+txtColor+';background-color:'+bgColor+';'">
-			<!-- ../../../static/images/news.png -->
-			<view class='pictrue skeleton-rect'>
-				<image :src='logoConfig'></image>
-			</view>
-			<view class='swiperTxt skeleton-rect'>
-				<swiper :indicator-dots="indicatorDots" :autoplay="autoplay" interval="2500" :duration="duration"
-					vertical="true" circular="true">
-					<block v-for="(item,index) in itemNew" :key='index'>
-						<swiper-item catchtouchmove='catchTouchMove'>
-							<view @click="jump(item.chiild[1].val)" class='acea-row row-between-wrapper'>
-								<view class='text acea-row row-between-wrapper'>
-									<view class='newsTitle line1'
-										:style="'text-align:'+ (txtStyle==1?'center':txtStyle==2?'right':'left') +';color:'+txtColor+';'">
-										{{item.chiild[0].val}}</view>
-								</view>
-								<view class='iconfont icon-xiangyou'></view>
-							</view>
-						</swiper-item>
-					</block>
-				</swiper>
-			</view>
-		</view>
-	</view>
-</template>
-
-<script>
-	export default {
-		name: 'news',
-		props: {
-			dataConfig: {
-				type: Object,
-				default: () => {}
-			},
-			isSortType: {
-				type: String | Number,
-				default: 0
-			}
-		},
-		data() {
-			return {
-				indicatorDots: false,
-				autoplay: true,
-				duration: 500,
-				itemNew: this.dataConfig.listConfig.list,
-				logoConfig: this.dataConfig.logoConfig.url,
-				mbConfig: this.dataConfig.mbConfig.val,
-				txtStyle: this.dataConfig.txtStyle.type,
-				txtColor: this.dataConfig.txtColor.color[0].item,
-				bgColor: this.dataConfig.bgColor.color[0].item,
-				bgStyle: this.dataConfig.bgStyle.type,
-				prConfig: this.dataConfig.prConfig.val
-			};
-		},
-		created() {},
-		mounted() {},
-		methods: {
-			jump(url){
-				uni.navigateTo({
-					url:url,
-					fail:()=>{
-						uni.switchTab({
-							url:url
-						})
-					}
-				})
-			}
-		}
-	}
-</script>
-
-<style lang="scss">
-	.pageOn{
-	    border-radius: 12rpx!important;
-	}
-	.news {
-		display: flex;
-		align-items: center;
-		flex-wrap: nowrap;
-		height: 77rpx;
-		border-top: 1rpx solid #f4f4f4;
-		padding: 0 20rpx;
-		box-shadow: 0 10rpx 30rpx #f5f5f5;
-	}
-
-	.news .pictrue {
-		width: 130rpx;
-		height: 36rpx;
-		border-right: 1rpx solid #ddd;
-		padding-right: 23rpx;
-		box-sizing: content-box;
-	}
-
-	.news .pictrue image {
-		width: 100%;
-		height: 100%;
-	}
-
-	.news .swiperTxt {
-		width: 523rpx;
-		height: 100%;
-		line-height: 77rpx;
-		overflow: hidden;
-		margin-left: 22rpx;
-	}
-
-	.news .swiperTxt .text {
-		width: 89%;
-	}
-
-	.news .swiperTxt .text .label {
-		font-size: 20rpx;
-		color: #ff4c48;
-		width: 64rpx;
-		height: 30rpx;
-		border-radius: 40rpx;
-		text-align: center;
-		line-height: 28rpx;
-		border: 2rpx solid #ff4947;
-	}
-
-	.news .swiperTxt .text .newsTitle {
-		width: 100%;
-		font-size: 24rpx;
-		color: #666;
-	}
-
-	.news .swiperTxt .iconfont {
-		font-size: 28rpx;
-		color: #888;
-	}
-
-	.news .swiperTxt swiper {
-		height: 100%;
-	}
+<template>
+	<view v-show="!isSortType">
+		<view class='news acea-row row-middle' :class="{pageOn:bgStyle===1}" v-if="itemNew.length"
+			:style="'margin:0 '+prConfig*2+'rpx;margin-top:'+mbConfig*2+'rpx;color:'+txtColor+';background-color:'+bgColor+';'">
+			<!-- ../../../static/images/news.png -->
+			<view class='pictrue skeleton-rect'>
+				<image :src='logoConfig'></image>
+			</view>
+			<view class='swiperTxt skeleton-rect'>
+				<swiper :indicator-dots="indicatorDots" :autoplay="autoplay" interval="2500" :duration="duration"
+					vertical="true" circular="true">
+					<block v-for="(item,index) in itemNew" :key='index'>
+						<swiper-item catchtouchmove='catchTouchMove'>
+							<view @click="jump(item.chiild[1].val)" class='acea-row row-between-wrapper'>
+								<view class='text acea-row row-between-wrapper'>
+									<view class='newsTitle line1'
+										:style="'text-align:'+ (txtStyle==1?'center':txtStyle==2?'right':'left') +';color:'+txtColor+';'">
+										{{item.chiild[0].val}}
+									</view>
+								</view>
+								<view class='iconfont icon-xiangyou'></view>
+							</view>
+						</swiper-item>
+					</block>
+				</swiper>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		name: 'news',
+		props: {
+			dataConfig: {
+				type: Object,
+				default: () => {}
+			},
+			isSortType: {
+				type: String | Number,
+				default: 0
+			}
+		},
+		data() {
+			return {
+				indicatorDots: false,
+				autoplay: true,
+				duration: 500,
+				itemNew: this.dataConfig.listConfig.list,
+				logoConfig: this.dataConfig.logoConfig.url,
+				mbConfig: this.dataConfig.mbConfig.val,
+				txtStyle: this.dataConfig.txtStyle.type,
+				txtColor: this.dataConfig.txtColor.color[0].item,
+				bgColor: this.dataConfig.bgColor.color[0].item,
+				bgStyle: this.dataConfig.bgStyle.type,
+				prConfig: this.dataConfig.prConfig.val
+			};
+		},
+		created() {},
+		mounted() {},
+		methods: {
+			jump(url) {
+				this.$util.JumpPath(url);
+			}
+		}
+	}
+</script>
+
+<style lang="scss">
+	.pageOn {
+		border-radius: 12rpx !important;
+	}
+
+	.news {
+		display: flex;
+		align-items: center;
+		flex-wrap: nowrap;
+		height: 77rpx;
+		border-top: 1rpx solid #f4f4f4;
+		padding: 0 20rpx;
+		box-shadow: 0 10rpx 30rpx #f5f5f5;
+	}
+
+	.news .pictrue {
+		width: 130rpx;
+		height: 36rpx;
+		border-right: 1rpx solid #ddd;
+		padding-right: 23rpx;
+		box-sizing: content-box;
+	}
+
+	.news .pictrue image {
+		width: 100%;
+		height: 100%;
+	}
+
+	.news .swiperTxt {
+		width: 523rpx;
+		height: 100%;
+		line-height: 77rpx;
+		overflow: hidden;
+		margin-left: 22rpx;
+	}
+
+	.news .swiperTxt .text {
+		width: 89%;
+	}
+
+	.news .swiperTxt .text .label {
+		font-size: 20rpx;
+		color: #ff4c48;
+		width: 64rpx;
+		height: 30rpx;
+		border-radius: 40rpx;
+		text-align: center;
+		line-height: 28rpx;
+		border: 2rpx solid #ff4947;
+	}
+
+	.news .swiperTxt .text .newsTitle {
+		width: 100%;
+		font-size: 24rpx;
+		color: #666;
+	}
+
+	.news .swiperTxt .iconfont {
+		font-size: 28rpx;
+		color: #888;
+	}
+
+	.news .swiperTxt swiper {
+		height: 100%;
+	}
 </style>

+ 310 - 330
template/uni-app/pages/index/diy/components/pictureCube.vue

@@ -1,331 +1,311 @@
-<template>
-	<view class="pictureCube skeleton-rect" :class="{pageOn:bgStyle===1}"
-		:style="{margin:'0 '+prConfig*2+'rpx',marginTop:slider*2+'rpx',background:bgColor}" v-if="picList.length"
-		v-show="!isSortType">
-		<view class="advertItem01" v-for="(item,index) in picList" :key="index" v-if="style==0" @click="goDetail(item)">
-			<image :src="item.image" mode="widthFix"></image>
-		</view>
-		<view class="advertItem02 acea-row" v-if="style==1">
-			<view class="item" v-for="(item,index) in picList" :key="index" @click="goDetail(item)">
-				<image :src="item.image" mode="aspectFill" :style="'height:'+ imageH +'rpx;'"></image>
-			</view>
-		</view>
-		<view class="advertItem02 advertItem03 acea-row" v-if="style==2">
-			<view class="item" v-for="(item,index) in picList" :key="index" @click="goDetail(item)">
-				<image :src="item.image" mode="aspectFill" :style="'height:'+ imageH +'rpx;'"></image>
-			</view>
-		</view>
-		<view class="advertItem04 acea-row" v-if="style==3">
-			<view class="item" @click="goDetail(picList[0])">
-				<image :src="picList[0].image"></image>
-			</view>
-			<view class="item">
-				<view class="pic" @click="goDetail(picList[1])">
-					<image :src="picList[1].image"></image>
-				</view>
-				<view class="pic" @click="goDetail(picList[2])">
-					<image :src="picList[2].image"></image>
-				</view>
-			</view>
-		</view>
-		<view class="advertItem02 advertItem05 acea-row" v-if="style==4">
-			<view class="item" v-for="(item,index) in picList" :key="index" @click="goDetail(item)">
-				<image :src="item.image" mode="aspectFill" :style="'height:'+ imageH +'rpx;'"></image>
-			</view>
-		</view>
-		<view class="advertItem02 advertItem06 acea-row" v-if="style==5">
-			<view class="item" v-for="(item,index) in picList" :key="index" @click="goDetail(item)">
-				<image :src="item.image" mode="aspectFill"></image>
-			</view>
-		</view>
-	</view>
-</template>
-
-<script>
-	export default {
-		name: 'pictureCube',
-		props: {
-			dataConfig: {
-				type: Object,
-				default: () => {}
-			},
-			isSortType: {
-				type: String | Number,
-				default: 0
-			}
-		},
-		data() {
-			return {
-				picList: this.dataConfig.picStyle.picList,
-				style: this.dataConfig.tabConfig.tabVal,
-				bgStyle: this.dataConfig.bgStyle.type,
-				prConfig: this.dataConfig.prConfig.val,
-				slider: this.dataConfig.mbConfig.val,
-				bgColor: this.dataConfig.bgColor.color[0].item,
-				widthC: '',
-				imageH: ''
-			};
-		},
-		mounted() {
-			if (this.picList.length) {
-				let that = this;
-				this.$nextTick((e) => {
-					if (this.style == 1) {
-						this.widthC = 375
-					} else if (this.style == 2) {
-						this.widthC = 250
-					} else if (this.style == 4) {
-						this.widthC = 188
-					}
-					uni.getImageInfo({
-						src: that.setDomain(that.picList[0].image),
-						success: (res) => {
-							if (res && res.height > 0) {
-								let height = res.height * ((that.widthC - that.prConfig * 2) / res
-									.width)
-								that.$set(that, 'imageH', height);
-							} else {
-								that.$set(that, 'imageH', (that.widthC - that.prConfig * 2) * 2);
-							}
-						},
-						fail: function(error) {
-							that.$set(that, 'imageH', (that.widthC - that.prConfig * 2) * 2);
-						}
-					})
-				})
-			}
-		},
-		created() {},
-		methods: {
-			//替换安全域名
-			setDomain: function(url) {
-				url = url ? url.toString() : '';
-				//本地调试打开,生产请注销
-				if (url.indexOf("https://") > -1) return url;
-				else return url.replace('http://', 'https://');
-			},
-			goDetail(url) {
-				let urls = url.link
-				if (urls.indexOf("http") != -1) {
-					// #ifdef H5
-					location.href = urls
-					// #endif
-					// #ifdef MP || APP-PLUS
-					uni.navigateTo({
-						url: `/pages/annex/web_view/index?url=${urls}`
-					});
-					// #endif
-				} else {
-					if (['/pages/goods_cate/goods_cate', '/pages/order_addcart/order_addcart', '/pages/user/index']
-						.indexOf(urls) == -1) {
-						uni.navigateTo({
-							url: urls
-						})
-					} else {
-						uni.reLaunch({
-							url: urls
-						})
-					}
-				}
-			}
-		}
-	}
-</script>
-
-<style lang="scss">
-	.pageOn {
-		border-radius: 24rpx !important;
-
-		.advertItem01 {
-			image {
-				border-radius: 20rpx;
-			}
-		}
-
-		.advertItem02 {
-			.item {
-				&:nth-child(1) {
-					image {
-						border-radius: 20rpx 0 0 20rpx
-					}
-				}
-
-				&:nth-child(2) {
-					image {
-						border-radius: 0 20rpx 20rpx 0
-					}
-				}
-			}
-		}
-
-		.advertItem03 {
-			.item {
-				&:nth-child(1) {
-					image {
-						border-radius: 20rpx 0 0 20rpx
-					}
-				}
-
-				&:nth-child(2) {
-					image {
-						border-radius: 0
-					}
-				}
-
-				&:nth-child(3) {
-					image {
-						border-radius: 0 20rpx 20rpx 0
-					}
-				}
-			}
-		}
-
-		.advertItem04 {
-			.item {
-				&:nth-child(1) {
-					image {
-						border-radius: 20rpx 0 0 20rpx
-					}
-				}
-
-				&:nth-child(2) {
-					.pic {
-						&:nth-child(1) {
-							image {
-								border-radius: 0 20rpx 0 0
-							}
-						}
-
-						&:nth-child(2) {
-							image {
-								border-radius: 0 0 20rpx 0
-							}
-						}
-					}
-				}
-			}
-		}
-
-		.advertItem05 {
-			.item {
-				&:nth-child(1) {
-					image {
-						border-radius: 20rpx 0 0 20rpx
-					}
-				}
-
-				&:nth-child(2) {
-					image {
-						border-radius: 0
-					}
-				}
-
-				&:nth-child(4) {
-					image {
-						border-radius: 0 20rpx 20rpx 0
-					}
-				}
-			}
-		}
-
-		.advertItem06 {
-			.item {
-				&:nth-child(1) {
-					image {
-						border-radius: 20rpx 0 0 0
-					}
-				}
-
-				&:nth-child(2) {
-					image {
-						border-radius: 0 20rpx 0 0
-					}
-				}
-
-				&:nth-child(3) {
-					image {
-						border-radius: 0 0 0 20rpx
-					}
-				}
-
-				&:nth-child(4) {
-					image {
-						border-radius: 0 0 20rpx 0
-					}
-				}
-			}
-		}
-	}
-
-	.pictureCube {
-		background-color: #fff;
-
-		.advertItem01 {
-			width: 100%;
-			height: auto;
-
-			image {
-				width: 100%;
-				height: 100%;
-				display: block;
-			}
-		}
-
-		.advertItem02 {
-			// /deep/uni-image>img{
-			// 	position: unset;
-			// }
-			width: 100%;
-
-			.item {
-				width: 50%;
-				height: auto;
-
-				image {
-					width: 100%;
-					height: 100%;
-					display: block;
-				}
-			}
-		}
-
-		.advertItem03 {
-			.item {
-				width: 33.3333%;
-			}
-		}
-
-		.advertItem04 {
-			width: 100%;
-
-			.item {
-				width: 50%;
-				height: 376rpx;
-
-				.pic {
-					width: 100%;
-					height: 188rpx;
-				}
-
-				image {
-					width: 100%;
-					height: 100%;
-					display: block;
-				}
-			}
-		}
-
-		.advertItem05 {
-			.item {
-				width: 25%;
-			}
-		}
-
-		.advertItem06 {
-			.item {
-				width: 50%;
-				height: 188rpx;
-			}
-		}
-	}
+<template>
+	<view class="pictureCube skeleton-rect" :class="{pageOn:bgStyle===1}"
+		:style="{margin:'0 '+prConfig*2+'rpx',marginTop:slider*2+'rpx',background:bgColor}" v-if="picList.length"
+		v-show="!isSortType">
+		<view class="advertItem01" v-for="(item,index) in picList" :key="index" v-if="style==0" @click="goDetail(item)">
+			<image :src="item.image" mode="widthFix"></image>
+		</view>
+		<view class="advertItem02 acea-row" v-if="style==1">
+			<view class="item" v-for="(item,index) in picList" :key="index" @click="goDetail(item)">
+				<image :src="item.image" mode="aspectFill" :style="'height:'+ imageH +'rpx;'"></image>
+			</view>
+		</view>
+		<view class="advertItem02 advertItem03 acea-row" v-if="style==2">
+			<view class="item" v-for="(item,index) in picList" :key="index" @click="goDetail(item)">
+				<image :src="item.image" mode="aspectFill" :style="'height:'+ imageH +'rpx;'"></image>
+			</view>
+		</view>
+		<view class="advertItem04 acea-row" v-if="style==3">
+			<view class="item" @click="goDetail(picList[0])">
+				<image :src="picList[0].image"></image>
+			</view>
+			<view class="item">
+				<view class="pic" @click="goDetail(picList[1])">
+					<image :src="picList[1].image"></image>
+				</view>
+				<view class="pic" @click="goDetail(picList[2])">
+					<image :src="picList[2].image"></image>
+				</view>
+			</view>
+		</view>
+		<view class="advertItem02 advertItem05 acea-row" v-if="style==4">
+			<view class="item" v-for="(item,index) in picList" :key="index" @click="goDetail(item)">
+				<image :src="item.image" mode="aspectFill" :style="'height:'+ imageH +'rpx;'"></image>
+			</view>
+		</view>
+		<view class="advertItem02 advertItem06 acea-row" v-if="style==5">
+			<view class="item" v-for="(item,index) in picList" :key="index" @click="goDetail(item)">
+				<image :src="item.image" mode="aspectFill"></image>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		name: 'pictureCube',
+		props: {
+			dataConfig: {
+				type: Object,
+				default: () => {}
+			},
+			isSortType: {
+				type: String | Number,
+				default: 0
+			}
+		},
+		data() {
+			return {
+				picList: this.dataConfig.picStyle.picList,
+				style: this.dataConfig.tabConfig.tabVal,
+				bgStyle: this.dataConfig.bgStyle.type,
+				prConfig: this.dataConfig.prConfig.val,
+				slider: this.dataConfig.mbConfig.val,
+				bgColor: this.dataConfig.bgColor.color[0].item,
+				widthC: '',
+				imageH: ''
+			};
+		},
+		mounted() {
+			if (this.picList.length) {
+				let that = this;
+				this.$nextTick((e) => {
+					if (this.style == 1) {
+						this.widthC = 375
+					} else if (this.style == 2) {
+						this.widthC = 250
+					} else if (this.style == 4) {
+						this.widthC = 188
+					}
+					uni.getImageInfo({
+						src: that.setDomain(that.picList[0].image),
+						success: (res) => {
+							if (res && res.height > 0) {
+								let height = res.height * ((that.widthC - that.prConfig * 2) / res
+									.width)
+								that.$set(that, 'imageH', height);
+							} else {
+								that.$set(that, 'imageH', (that.widthC - that.prConfig * 2) * 2);
+							}
+						},
+						fail: function(error) {
+							that.$set(that, 'imageH', (that.widthC - that.prConfig * 2) * 2);
+						}
+					})
+				})
+			}
+		},
+		created() {},
+		methods: {
+			//替换安全域名
+			setDomain: function(url) {
+				url = url ? url.toString() : '';
+				//本地调试打开,生产请注销
+				if (url.indexOf("https://") > -1) return url;
+				else return url.replace('http://', 'https://');
+			},
+			goDetail(url) {
+				let urls = url.link
+				this.$util.JumpPath(urls);
+			}
+		}
+	}
+</script>
+
+<style lang="scss">
+	.pageOn {
+		border-radius: 24rpx !important;
+
+		.advertItem01 {
+			image {
+				border-radius: 20rpx;
+			}
+		}
+
+		.advertItem02 {
+			.item {
+				&:nth-child(1) {
+					image {
+						border-radius: 20rpx 0 0 20rpx
+					}
+				}
+
+				&:nth-child(2) {
+					image {
+						border-radius: 0 20rpx 20rpx 0
+					}
+				}
+			}
+		}
+
+		.advertItem03 {
+			.item {
+				&:nth-child(1) {
+					image {
+						border-radius: 20rpx 0 0 20rpx
+					}
+				}
+
+				&:nth-child(2) {
+					image {
+						border-radius: 0
+					}
+				}
+
+				&:nth-child(3) {
+					image {
+						border-radius: 0 20rpx 20rpx 0
+					}
+				}
+			}
+		}
+
+		.advertItem04 {
+			.item {
+				&:nth-child(1) {
+					image {
+						border-radius: 20rpx 0 0 20rpx
+					}
+				}
+
+				&:nth-child(2) {
+					.pic {
+						&:nth-child(1) {
+							image {
+								border-radius: 0 20rpx 0 0
+							}
+						}
+
+						&:nth-child(2) {
+							image {
+								border-radius: 0 0 20rpx 0
+							}
+						}
+					}
+				}
+			}
+		}
+
+		.advertItem05 {
+			.item {
+				&:nth-child(1) {
+					image {
+						border-radius: 20rpx 0 0 20rpx
+					}
+				}
+
+				&:nth-child(2) {
+					image {
+						border-radius: 0
+					}
+				}
+
+				&:nth-child(4) {
+					image {
+						border-radius: 0 20rpx 20rpx 0
+					}
+				}
+			}
+		}
+
+		.advertItem06 {
+			.item {
+				&:nth-child(1) {
+					image {
+						border-radius: 20rpx 0 0 0
+					}
+				}
+
+				&:nth-child(2) {
+					image {
+						border-radius: 0 20rpx 0 0
+					}
+				}
+
+				&:nth-child(3) {
+					image {
+						border-radius: 0 0 0 20rpx
+					}
+				}
+
+				&:nth-child(4) {
+					image {
+						border-radius: 0 0 20rpx 0
+					}
+				}
+			}
+		}
+	}
+
+	.pictureCube {
+		background-color: #fff;
+
+		.advertItem01 {
+			width: 100%;
+			height: auto;
+
+			image {
+				width: 100%;
+				height: 100%;
+				display: block;
+			}
+		}
+
+		.advertItem02 {
+			// /deep/uni-image>img{
+			// 	position: unset;
+			// }
+			width: 100%;
+
+			.item {
+				width: 50%;
+				height: auto;
+
+				image {
+					width: 100%;
+					height: 100%;
+					display: block;
+				}
+			}
+		}
+
+		.advertItem03 {
+			.item {
+				width: 33.3333%;
+			}
+		}
+
+		.advertItem04 {
+			width: 100%;
+
+			.item {
+				width: 50%;
+				height: 376rpx;
+
+				.pic {
+					width: 100%;
+					height: 188rpx;
+				}
+
+				image {
+					width: 100%;
+					height: 100%;
+					display: block;
+				}
+			}
+		}
+
+		.advertItem05 {
+			.item {
+				width: 25%;
+			}
+		}
+
+		.advertItem06 {
+			.item {
+				width: 50%;
+				height: 188rpx;
+			}
+		}
+	}
 </style>

+ 1 - 21
template/uni-app/pages/index/diy/components/swiperBg.vue

@@ -117,27 +117,7 @@
 			},
 			goDetail(url) {
 				let urls = url.info[1].value
-				if (urls.indexOf("http") != -1) {
-					// #ifdef H5
-					location.href = urls
-					// #endif
-					// #ifdef MP || APP-PLUS
-					uni.navigateTo({
-						url: `/pages/annex/web_view/index?url=${urls}`
-					});
-					// #endif
-				} else {
-					if (['/pages/goods_cate/goods_cate', '/pages/order_addcart/order_addcart', '/pages/user/index']
-						.indexOf(urls) == -1) {
-						uni.navigateTo({
-							url: urls
-						})
-					} else {
-						uni.reLaunch({
-							url: urls
-						})
-					}
-				}
+				this.$util.JumpPath(urls);
 			}
 		}
 	}

+ 74 - 66
template/uni-app/pages/index/diy/components/titles.vue

@@ -1,67 +1,75 @@
-<template>
-	<view v-show="!isSortType">
-		<view v-if="titleConfig" :style="'margin:0 '+prConfig*2+'rpx;'">
-			<navigator :url="linkConfig" hover-class="none" class='title' :class="[(textPosition==0?'left':textPosition==2?'right':''),(textStyle==1?'italics':textStyle==2?'blod':''), (bgStyle===0?'':'borderRadius15')]" :style="'font-size:'+fontSize+'rpx;margin-top:'+mbConfig*2+'rpx;background-color:'+titleColor+';color:'+themeColor+';'">
-				<div>{{titleConfig}}</div>
-			</navigator>
-		</view>
-	</view>
-
-</template>
-
-<script>
-	export default {
-		name: 'titles',
-		props: {
-			dataConfig: {
-				type: Object,
-				default: () => {}
-			},
-			isSortType:{
-				type: String | Number,
-				default:0
-			}
-		},
-		data() {
-			return {
-				fontSize:this.dataConfig.fontSize.val*2,
-				linkConfig:this.dataConfig.linkConfig.value,
-				mbConfig:this.dataConfig.mbConfig.val,
-				textPosition:this.dataConfig.textPosition.type,
-				textStyle:this.dataConfig.textStyle.type,
-				titleColor:this.dataConfig.titleColor.color[0].item,
-				titleConfig:this.dataConfig.titleConfig.value,
-				themeColor:this.dataConfig.themeColor.color[0].item,
-				prConfig:this.dataConfig.prConfig.val,
-				bgStyle:this.dataConfig.bgStyle.type
-			};
-		},
-		created() {},
-		methods: {}
-	}
-</script>
-
-<style lang="scss">
-	.title{
-		font-size: 40rpx;
-		color: #282828;
-		text-align: center;
-		width: 100%;
-		padding: 20rpx;
-		box-sizing: border-box;
-		
-		&.left{
-			text-align: left;
-		}
-		&.right{
-			text-align: right;
-		}
-		&.blod{
-			font-weight: bold;
-		}
-		&.italics{
-			font-style: italic;
-		}
-	}
-	
+<template>
+	<view v-show="!isSortType">
+		<view v-if="titleConfig" :style="'margin:0 '+prConfig*2+'rpx;'">
+			<view @click="goLink" class='title'
+				:class="[(textPosition==0?'left':textPosition==2?'right':''),(textStyle==1?'italics':textStyle==2?'blod':''), (bgStyle===0?'':'borderRadius15')]"
+				:style="'font-size:'+fontSize+'rpx;margin-top:'+mbConfig*2+'rpx;background-color:'+titleColor+';color:'+themeColor+';'">
+				<div>{{titleConfig}}</div>
+			</view>
+		</view>
+	</view>
+
+</template>
+
+<script>
+	export default {
+		name: 'titles',
+		props: {
+			dataConfig: {
+				type: Object,
+				default: () => {}
+			},
+			isSortType: {
+				type: String | Number,
+				default: 0
+			}
+		},
+		data() {
+			return {
+				fontSize: this.dataConfig.fontSize.val * 2,
+				linkConfig: this.dataConfig.linkConfig.value,
+				mbConfig: this.dataConfig.mbConfig.val,
+				textPosition: this.dataConfig.textPosition.type,
+				textStyle: this.dataConfig.textStyle.type,
+				titleColor: this.dataConfig.titleColor.color[0].item,
+				titleConfig: this.dataConfig.titleConfig.value,
+				themeColor: this.dataConfig.themeColor.color[0].item,
+				prConfig: this.dataConfig.prConfig.val,
+				bgStyle: this.dataConfig.bgStyle.type
+			};
+		},
+		created() {},
+		methods: {
+			goLink() {
+				this.$util.JumpPath(this.linkConfig);
+			}
+		}
+	}
+</script>
+
+<style lang="scss">
+	.title {
+		font-size: 40rpx;
+		color: #282828;
+		text-align: center;
+		width: 100%;
+		padding: 20rpx;
+		box-sizing: border-box;
+
+		&.left {
+			text-align: left;
+		}
+
+		&.right {
+			text-align: right;
+		}
+
+		&.blod {
+			font-weight: bold;
+		}
+
+		&.italics {
+			font-style: italic;
+		}
+	}
 </style>

+ 1 - 1
template/uni-app/pages/index/index.vue

@@ -68,7 +68,7 @@
 					this.$util.Tips({
 						title: err
 					});
-					// #endiff
+					// #endif
 				})
 			},
 			// 微信分享;

+ 1 - 18
template/uni-app/pages/index/visualization/components/activity.vue

@@ -81,24 +81,7 @@
 		methods: {
 			gopage(url) {
 				goPage().then(res => {
-					if (url.indexOf("http") != -1) {
-						// #ifdef H5
-						location.href = url
-						// #endif
-					} else {
-						if (['/pages/goods_cate/goods_cate', '/pages/order_addcart/order_addcart',
-								'/pages/user/index'
-							].indexOf(url) ==
-							-1) {
-							uni.navigateTo({
-								url: url
-							})
-						} else {
-							uni.navigateTo({
-								url: url
-							})
-						}
-					}
+					this.$util.JumpPath(url);
 				})
 			}
 		}

+ 1 - 19
template/uni-app/pages/index/visualization/components/mBanner.vue

@@ -103,25 +103,7 @@
 			},
 			goDetail(url) {
 				goPage().then(res => {
-					let urls = url.info[1].value
-					if (urls.indexOf("http") != -1) {
-						// #ifdef H5 || APP-PLUS
-						location.href = urls
-						// #endif
-					} else {
-						if (['/pages/goods_cate/goods_cate', '/pages/order_addcart/order_addcart',
-								'/pages/user/index'
-							].indexOf(urls) ==
-							-1) {
-							uni.navigateTo({
-								url: urls
-							})
-						} else {
-							uni.navigateTo({
-								url: urls
-							})
-						}
-					}
+					this.$util.JumpPath(urls);
 				})
 			}
 		}

+ 1 - 20
template/uni-app/pages/index/visualization/components/menus.vue

@@ -71,26 +71,7 @@
 		methods: {
 			menusTap(url) {
 				goPage().then(res => {
-					if (url.indexOf("http") != -1) {
-						// #ifdef H5
-						location.href = url
-						// #endif
-					} else {
-						// uni.navigateTo({
-						// 	url: url
-						// })
-						if (['/pages/goods_cate/goods_cate', '/pages/order_addcart/order_addcart',
-								'/pages/user/index'
-							].indexOf(url) == -1) {
-							uni.navigateTo({
-								url: url
-							})
-						} else {
-							uni.switchTab({
-								url: url
-							})
-						}
-					}
+					this.$util.JumpPath(url);
 				})
 			}
 		}

+ 1 - 3
template/uni-app/pages/index/visualization/components/newGoods.vue

@@ -207,9 +207,7 @@
 			},
 			gopage(url) {
 				goPage().then(res => {
-					uni.navigateTo({
-						url: url
-					})
+					this.$util.JumpPath(url);
 				})
 			},
 			goDetail(item) {

+ 174 - 190
template/uni-app/pages/index/visualization/components/news.vue

@@ -1,191 +1,175 @@
-<template>
-	<view class="new" :style="colorStyle">
-		<view class="news default" v-if="isIframe && !itemNew.length">{{$t(`暂无新闻,请上传新闻`)}}</view>
-		<view class='news acea-row row-between-wrapper skeleton-rect' v-if="isShow && itemNew.length">
-			<view class='pictrue'>
-				<image :src='img'></image>
-			</view>
-			<view class='swiperTxt'>
-				<swiper :indicator-dots="indicatorDots" :autoplay="autoplay" interval="2500" :duration="duration"
-					vertical="true" circular="true" disable-touch="true">
-					<block v-for="(item,index) in itemNew" :key='index'>
-						<swiper-item catchtouchmove='catchTouchMove'>
-							<view class='acea-row row-between-wrapper' hover-class='none'
-								@click="gopage(item.chiild[1].val)">
-								<view class='text acea-row row-between-wrapper'>
-									<view class='newsTitle line1'>{{item.chiild[0].val}}</view>
-								</view>
-								<view class='iconfont icon-xiangyou'></view>
-							</view>
-						</swiper-item>
-					</block>
-				</swiper>
-			</view>
-		</view>
-		<view class='news acea-row row-between-wrapper' v-if="!isShow && isIframe && itemNew.length">
-			<view class='pictrue'>
-				<image :src='img'></image>
-			</view>
-			<view class='swiperTxt'>
-				<swiper :indicator-dots="indicatorDots" :autoplay="autoplay" interval="2500" :duration="duration"
-					vertical="true" circular="true">
-					<block v-for="(item,index) in itemNew" :key='index'>
-						<swiper-item catchtouchmove='catchTouchMove'>
-							<view class='acea-row row-between-wrapper' hover-class='none'
-								@click="gopage(item.chiild[1].val)">
-								<view class='text acea-row row-between-wrapper'>
-									<view class='newsTitle line1'>{{item.chiild[0].val}}</view>
-								</view>
-								<view class='iconfont icon-xiangyou'></view>
-							</view>
-						</swiper-item>
-					</block>
-				</swiper>
-			</view>
-		</view>
-	</view>
-</template>
-
-<script>
-	let app = getApp()
-	import colors from '@/mixins/color.js';
-	import {
-		goPage
-	} from '@/libs/order.js'
-	export default {
-		name: 'news',
-		props: {
-			dataConfig: {
-				type: Object,
-				default: () => {}
-			},
-		},
-		mixins:[colors],
-		watch: {
-			dataConfig: {
-				immediate: true,
-				handler(nVal, oVal) {
-					if (nVal) {
-						this.img = nVal.imgUrl.url;
-						this.itemNew = nVal.newList.list;
-						this.isShow = nVal.isShow.val;
-					}
-				}
-			}
-		},
-		data() {
-			return {
-				indicatorDots: false,
-				autoplay: true,
-				duration: 500,
-				img: '',
-				itemNew: [],
-				name: this.$options.name,
-				isIframe: false,
-				isShow: true
-			};
-		},
-		created() {
-			this.isIframe = app.globalData.isIframe;
-		},
-		mounted() {},
-		methods: {
-			gopage(url) {
-				goPage().then(res => {
-					if (url.indexOf("http") != -1) {
-						// #ifdef H5
-						location.href = url
-						// #endif
-					} else {
-						if (['/pages/goods_cate/goods_cate', '/pages/order_addcart/order_addcart',
-								'/pages/user/index'
-							].indexOf(url) ==
-							-1) {
-							uni.navigateTo({
-								url: url
-							})
-						} else {
-							uni.navigateTo({
-								url: url
-							})
-						}
-					}
-				})
-			}
-		}
-	}
-</script>
-
-<style lang="scss">
-	.new{
-		background-color: #fff;
-		padding: 20rpx 0;
-	}
-	.news {
-		height: 60rpx;
-		padding: 0 26rpx;
-		// box-shadow: 0 10rpx 30rpx #f5f5f5;
-		background-color: var(--view-op-point-four);
-		margin: 0 $uni-index-margin-col;
-		border-radius: 60rpx;
-		// box-shadow: $uni-index-box-shadow;
-
-		&.default {
-			text-align: center;
-			line-height: 77rpx;
-		}
-	}
-
-	.news .pictrue {
-		width: 116rpx;
-		height: 28rpx;
-		line-height: 28rpx;
-		border-right: 1rpx solid #ddd;
-		padding-right: 23rpx;
-		box-sizing: content-box;
-	}
-
-	.news .pictrue image {
-		width: 100%;
-		height: 100%;
-	}
-
-	.news .swiperTxt {
-		width: 470rpx;
-		height: 100%;
-		line-height: 60rpx;
-		overflow: hidden;
-	}
-
-	.news .swiperTxt .text {
-		line-height: 28rpx;
-		margin-bottom: 4rpx;
-	}
-
-	.news .swiperTxt .text .label {
-		font-size: 20rpx;
-		color: #ff4c48;
-		width: 64rpx;
-		height: 30rpx;
-		border-radius: 40rpx;
-		text-align: center;
-		line-height: 28rpx;
-		border: 2rpx solid #ff4947;
-	}
-
-	.news .swiperTxt .text .newsTitle {
-		width: 400rpx;
-		font-size: 24rpx;
-		line-height: 28rpx;
-		color: #666;
-	}
-
-	.news .swiperTxt .iconfont {
-		font-size: 28rpx;
-		color: #888;
-	}
-
-	.news .swiperTxt swiper {
-		height: 100%;
-	}
+<template>
+	<view class="new" :style="colorStyle">
+		<view class="news default" v-if="isIframe && !itemNew.length">{{$t(`暂无新闻,请上传新闻`)}}</view>
+		<view class='news acea-row row-between-wrapper skeleton-rect' v-if="isShow && itemNew.length">
+			<view class='pictrue'>
+				<image :src='img'></image>
+			</view>
+			<view class='swiperTxt'>
+				<swiper :indicator-dots="indicatorDots" :autoplay="autoplay" interval="2500" :duration="duration"
+					vertical="true" circular="true" disable-touch="true">
+					<block v-for="(item,index) in itemNew" :key='index'>
+						<swiper-item catchtouchmove='catchTouchMove'>
+							<view class='acea-row row-between-wrapper' hover-class='none'
+								@click="gopage(item.chiild[1].val)">
+								<view class='text acea-row row-between-wrapper'>
+									<view class='newsTitle line1'>{{item.chiild[0].val}}</view>
+								</view>
+								<view class='iconfont icon-xiangyou'></view>
+							</view>
+						</swiper-item>
+					</block>
+				</swiper>
+			</view>
+		</view>
+		<view class='news acea-row row-between-wrapper' v-if="!isShow && isIframe && itemNew.length">
+			<view class='pictrue'>
+				<image :src='img'></image>
+			</view>
+			<view class='swiperTxt'>
+				<swiper :indicator-dots="indicatorDots" :autoplay="autoplay" interval="2500" :duration="duration"
+					vertical="true" circular="true">
+					<block v-for="(item,index) in itemNew" :key='index'>
+						<swiper-item catchtouchmove='catchTouchMove'>
+							<view class='acea-row row-between-wrapper' hover-class='none'
+								@click="gopage(item.chiild[1].val)">
+								<view class='text acea-row row-between-wrapper'>
+									<view class='newsTitle line1'>{{item.chiild[0].val}}</view>
+								</view>
+								<view class='iconfont icon-xiangyou'></view>
+							</view>
+						</swiper-item>
+					</block>
+				</swiper>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	let app = getApp()
+	import colors from '@/mixins/color.js';
+	import {
+		goPage
+	} from '@/libs/order.js'
+	export default {
+		name: 'news',
+		props: {
+			dataConfig: {
+				type: Object,
+				default: () => {}
+			},
+		},
+		mixins: [colors],
+		watch: {
+			dataConfig: {
+				immediate: true,
+				handler(nVal, oVal) {
+					if (nVal) {
+						this.img = nVal.imgUrl.url;
+						this.itemNew = nVal.newList.list;
+						this.isShow = nVal.isShow.val;
+					}
+				}
+			}
+		},
+		data() {
+			return {
+				indicatorDots: false,
+				autoplay: true,
+				duration: 500,
+				img: '',
+				itemNew: [],
+				name: this.$options.name,
+				isIframe: false,
+				isShow: true
+			};
+		},
+		created() {
+			this.isIframe = app.globalData.isIframe;
+		},
+		mounted() {},
+		methods: {
+			gopage(url) {
+				goPage().then(res => {
+					this.$util.JumpPath(url);
+				})
+			}
+		}
+	}
+</script>
+
+<style lang="scss">
+	.new {
+		background-color: #fff;
+		padding: 20rpx 0;
+	}
+
+	.news {
+		height: 60rpx;
+		padding: 0 26rpx;
+		// box-shadow: 0 10rpx 30rpx #f5f5f5;
+		background-color: var(--view-op-point-four);
+		margin: 0 $uni-index-margin-col;
+		border-radius: 60rpx;
+		// box-shadow: $uni-index-box-shadow;
+
+		&.default {
+			text-align: center;
+			line-height: 77rpx;
+		}
+	}
+
+	.news .pictrue {
+		width: 116rpx;
+		height: 28rpx;
+		line-height: 28rpx;
+		border-right: 1rpx solid #ddd;
+		padding-right: 23rpx;
+		box-sizing: content-box;
+	}
+
+	.news .pictrue image {
+		width: 100%;
+		height: 100%;
+	}
+
+	.news .swiperTxt {
+		width: 470rpx;
+		height: 100%;
+		line-height: 60rpx;
+		overflow: hidden;
+	}
+
+	.news .swiperTxt .text {
+		line-height: 28rpx;
+		margin-bottom: 4rpx;
+	}
+
+	.news .swiperTxt .text .label {
+		font-size: 20rpx;
+		color: #ff4c48;
+		width: 64rpx;
+		height: 30rpx;
+		border-radius: 40rpx;
+		text-align: center;
+		line-height: 28rpx;
+		border: 2rpx solid #ff4947;
+	}
+
+	.news .swiperTxt .text .newsTitle {
+		width: 400rpx;
+		font-size: 24rpx;
+		line-height: 28rpx;
+		color: #666;
+	}
+
+	.news .swiperTxt .iconfont {
+		font-size: 28rpx;
+		color: #888;
+	}
+
+	.news .swiperTxt swiper {
+		height: 100%;
+	}
 </style>

+ 4 - 6
template/uni-app/pages/index/visualization/components/popular.vue

@@ -223,9 +223,7 @@
 			},
 			gopage(url) {
 				goPage().then(res => {
-					uni.navigateTo({
-						url: url
-					})
+					this.$util.JumpPath(url);
 				})
 			}
 		}
@@ -235,7 +233,7 @@
 <style lang="scss" scoped>
 	/deep/.uni-scroll-view-content,
 	.scroll-view_x {
-		display: flex;
+		display: flex;
 		flex-wrap: nowrap;
 	}
 
@@ -302,8 +300,8 @@
 		padding: 20rpx 20rpx;
 		box-sizing: border-box;
 		display: flex;
-		justify-content: space-between;
-		width: 100%;
+		justify-content: space-between;
+		width: 100%;
 		white-space: nowrap;
 	}
 

+ 1 - 3
template/uni-app/pages/index/visualization/components/promotion.vue

@@ -138,9 +138,7 @@
 			},
 			gopage(url) {
 				goPage().then(res => {
-					uni.navigateTo({
-						url: url
-					})
+					this.$util.JumpPath(url);
 				})
 			}
 		}

+ 1 - 27
template/uni-app/pages/index/visualization/components/swiperBg.vue

@@ -122,33 +122,7 @@
 		methods: {
 			goDetail(url) {
 				goPage().then(res => {
-					let urls = url.info[1].value
-					if (urls) {
-						if (urls.indexOf("http") != -1) {
-							// #ifdef H5
-							location.href = urls
-							// #endif
-						} else {
-							if (['/pages/goods_cate/goods_cate', '/pages/order_addcart/order_addcart',
-									'/pages/user/index'
-								].indexOf(urls) ==
-								-1) {
-								uni.navigateTo({
-									url: urls
-								})
-							} else {
-								uni.switchTab({
-									url: urls,
-									fail() {
-										uni.reLaunch({
-											url: urls
-										})
-									}
-								})
-
-							}
-						}
-					}
+					this.$util.JumpPath(url);
 				})
 			},
 			//替换安全域名

+ 1 - 1
template/uni-app/pages/order_addcart/order_addcart.vue

@@ -35,7 +35,7 @@
 										<image v-else :src='item.productInfo.image'></image>
 									</view>
 									<view class='text'>
-										<view class='line1' :class="item.attrStatus?'':'reColor'">
+										<view class='line2' :class="item.attrStatus?'':'reColor'">
 											{{item.productInfo.store_name}}
 										</view>
 										<view class='infor line1' v-if="item.productInfo.attrInfo">

+ 395 - 410
template/uni-app/pages/points_mall/index.vue

@@ -1,411 +1,396 @@
-<template>
-	<view :style="colorStyle">
-		<view class="points-swiper">
-			<image class="bag" src="../../static/images/jf-head.png" mode=""></image>
-			<view class="swiper">
-				<swiper indicator-dots="true" :autoplay="autoplay" :circular="circular" :interval="interval"
-					:duration="duration" indicator-color="rgba(255,255,255,0.6)" indicator-active-color="#fff">
-					<block v-for="(item, index) in imgUrls" :key="index">
-						<swiper-item>
-							<image :src="item.img" class="slide-image" @click="goPages(item)"></image>
-						</swiper-item>
-					</block>
-				</swiper>
-			</view>
-		</view>
-		<view class="model">
-			<view class="model-list" v-for="(model,index) in modelList" :key="index" @click="jump(model.url)">
-				<image class="img" :src="model.imgUrl" mode=""></image>
-				<text>{{model.title}}</text>
-			</view>
-		</view>
-		<view class="body">
-			<view class="body-title">
-				<text class="title">{{$t(`大家都在换`)}}</text>
-				<text class="jump-trip" @click="jumpMore">{{$t(`查看更多`)}}
-					<text class="iconfont icon-xiangyou"></text></text>
-			</view>
-			<view class="product-list" v-if="goodList.length">
-				<view class="product-item" v-for="(item, index) in goodList" @click="goGoodsDetail(item)">
-					<image :src="item.image"></image>
-					<view class="info">
-						<view class="title line1">{{ item.title }}</view>
-						<view class="price-box">
-							{{ item.price }} {{$t(`积分`)}}
-						</view>
-						<view class="sales">{{item.sales}}{{$t(`人兑换`)}}</view>
-					</view>
-				</view>
-			</view>
-			<view v-else class="no-goods">
-				<image :src="imgHost + '/statics/images/no-thing.png'" mode=""></image>
-				<view class="fontimg">{{$t(`暂无商品,去看点别的吧`)}}</view>
-			</view>
-			<view class="footer">
-				<view class="body-title">
-					<text class="title">{{$t(`轻松赚积分`)}}</text>
-					<text></text>
-				</view>
-				<view class="footer-list">
-					<view class="list-left">
-						<image class="icon-sty" src="./static/go-shoping.png" mode=""></image>
-						<view class="list-left-right">
-							<view class="title">
-								{{$t(`购买商品`)}}
-							</view>
-							<view class="trip">
-								{{$t(`购买商品可获得积分奖励`)}}
-							</view>
-						</view>
-					</view>
-					<navigator url="/pages/index/index" open-type="switchTab" class="right-box">
-						<text class="go-jump">
-							{{$t(`去完成`)}}
-						</text>
-					</navigator>
-				</view>
-				<view class="footer-list">
-					<view class="list-left">
-						<image class="icon-sty" src="./static/everyday.png" mode=""></image>
-						<view class="list-left-right">
-							<view class="title">
-								{{$t(`每日签到活动`)}}
-							</view>
-							<view class="trip">
-								{{$t(`每日签到可获得积分奖励`)}}
-							</view>
-						</view>
-					</view>
-					<navigator url="/pages/users/user_sgin/index" class="right-box">
-						<text class="go-jump">
-							{{$t(`去完成`)}}
-						</text>
-					</navigator>
-				</view>
-				<view class="footer-list">
-					<view class="list-left">
-						<image class="icon-sty" src="./static/luck-draw.png" mode=""></image>
-						<view class="list-left-right">
-							<view class="title">
-								{{$t(`九宫格抽奖活动`)}}
-							</view>
-							<view class="trip">
-								{{$t(`幸运抽奖可获得积分奖励`)}}
-							</view>
-						</view>
-					</view>
-					<navigator url="/pages/goods/lottery/grids/index?type=1" class="right-box">
-						<text class="go-jump">
-							{{$t(`去完成`)}}
-						</text>
-					</navigator>
-				</view>
-			</view>
-		</view>
-	</view>
-</template>
-
-<script>
-	// import swipers from './components/swiper.vue';
-	import {
-		mapGetters
-	} from 'vuex';
-	import {
-		getStoreIntegral
-	} from '@/api/points_mall.js'
-	import {
-		goShopDetail
-	} from '@/libs/order.js';
-	import colors from "@/mixins/color";
-	import {HTTP_REQUEST_URL} from '@/config/app';
-	export default {
-		components: {
-			// swipers
-		},
-		mixins: [colors],
-		data() {
-			return {
-				imgHost:HTTP_REQUEST_URL,
-				autoplay: true,
-				circular: true,
-				interval: 3000,
-				duration: 500,
-				imgUrls: [],
-				goodList: [],
-				modelList: [{
-						title: this.$t(`我的积分`),
-						imgUrl: './static/my-point.png',
-						url: "/pages/users/user_integral/index"
-					},
-					{
-						title: this.$t(`每日签到`),
-						imgUrl: './static/sign-in.png',
-						url: '/pages/users/user_sgin/index'
-					}, {
-						title: this.$t(`积分抽奖`),
-						imgUrl: './static/points-lottery.png',
-						url: '/pages/goods/lottery/grids/index?type=1'
-					}, {
-						title: this.$t(`兑换记录`),
-						imgUrl: './static/exchange.png',
-						url: "/pages/points_mall/exchange_record"
-					},
-				]
-			}
-		},
-		computed: mapGetters(['isLogin']),
-		onLoad() {
-			this.getStoreIntegral()
-		},
-		watch: {
-			isLogin: {
-				handler: function(newV, oldV) {
-					if (newV == true) {
-						this.getStoreIntegral();
-					}
-				},
-				deep: true
-			},
-		},
-		methods: {
-			getStoreIntegral() {
-				getStoreIntegral().then(res => {
-					this.imgUrls = res.data.banner
-					this.goodList = res.data.list
-				})
-			},
-			// 去商品详情
-			goGoodsDetail(item) {
-				goShopDetail(item).then(res => {
-					uni.navigateTo({
-						url: `/pages/points_mall/integral_goods_details?id=${item.id}`
-					});
-				});
-			},
-			jumpMore() {
-				uni.navigateTo({
-					url: '/pages/points_mall/integral_goods_list'
-				})
-			},
-			goPages(item) {
-				let url = item.link;
-				if (url.indexOf("http") != -1) {
-					// #ifdef H5
-					location.href = url
-					// #endif
-				} else {
-					if (['/pages/goods_cate/goods_cate', '/pages/order_addcart/order_addcart', '/pages/user/index',
-							'/pages/index/index'
-						]
-						.indexOf(url) == -1) {
-						uni.navigateTo({
-							url: url
-						})
-					} else {
-						uni.switchTab({
-							url: url
-						})
-					}
-				}
-			},
-			jump(url) {
-				uni.navigateTo({
-					url
-				})
-			}
-		}
-	}
-</script>
-
-<style lang="scss" scoped>
-	.swiper,
-	swiper,
-	swiper-item,
-	.slide-image {
-		width: 100%;
-		height: 280rpx;
-	}
-
-	/deep/ .uni-swiper-wrapper {
-		border-radius: 10rpx;
-	}
-
-	.swiper {
-		padding: 20rpx;
-	}
-
-	.points-swiper {
-		position: relative;
-		width: 100%;
-		background-color: #fff;
-
-		.bag {
-			position: absolute;
-			width: 100%;
-			height: 285rpx;
-		}
-
-		.points-swiper-sty {
-			padding: 20rpx 26rpx;
-		}
-	}
-
-	.model {
-		display: flex;
-		justify-content: space-between;
-		padding: 56rpx 42rpx;
-		background-color: #fff;
-	}
-
-	.model-list {
-		display: flex;
-		flex-direction: column;
-		align-items: center;
-		justify-content: center;
-		font-size: 26rpx;
-		color: #333;
-		margin-top: 27rpx;
-		font-weight: 500;
-
-		.img {
-			width: 84rpx;
-			height: 84rpx;
-			margin-bottom: 19rpx;
-		}
-
-	}
-
-	.body {
-		background-color: #fff;
-		padding: 0 30rpx;
-		margin-top: 20rpx;
-
-		.body-title {
-			display: flex;
-			justify-content: space-between;
-			padding: 30rpx 0 10rpx 0;
-
-			.title {
-				font-size: 32rpx;
-				font-family: PingFang SC;
-				font-weight: bold;
-			}
-
-			.jump-trip,
-			.icon-xiangyou {
-				font-size: 24rpx;
-				color: #999999;
-			}
-		}
-
-		.product-list {
-			display: flex;
-			flex-wrap: wrap;
-			justify-content: space-between;
-			margin-top: 30rpx;
-
-			.product-item {
-				position: relative;
-				width: 334rpx;
-				background: #fff;
-				border-radius: 10rpx;
-				margin-bottom: 20rpx;
-				box-shadow: 0px 0px 7px rgba(0, 0, 0, 0.06);
-
-				image {
-					width: 100%;
-					height: 344rpx;
-					border-radius: 10rpx 10rpx 0 0;
-				}
-
-				.info {
-					padding: 14rpx 16rpx;
-
-					.title {
-						font-size: 28rpx;
-					}
-
-					.price-box {
-						font-size: 26rpx;
-						font-weight: 700;
-						margin-top: 8px;
-						color: var(--view-theme);
-					}
-
-					.sales {
-						font-size: 22rpx;
-						color: #999999;
-					}
-				}
-			}
-		}
-	}
-
-	.footer {
-		margin-top: 20rpx;
-
-		.footer-list {
-			display: flex;
-			justify-content: space-between;
-			padding: 26rpx 0;
-
-			.list-left {
-				display: flex;
-				align-items: center;
-
-				.icon-sty {
-					width: 80rpx;
-					height: 80rpx;
-					margin-right: 18rpx;
-				}
-
-				.list-left-right {
-					.title {
-						font-size: 28rpx;
-						font-weight: bold;
-						color: #333333;
-					}
-
-					.trip {
-						font-size: 22rpx;
-						color: #999999;
-					}
-				}
-			}
-
-			.right-box {
-				display: flex;
-				align-items: center;
-			}
-
-			.go-jump {
-				display: flex;
-				align-items: center;
-				background-color: #E93323;
-				border-radius: 26rpx;
-				color: #fff;
-				font-size: 28rpx;
-				height: 48rpx;
-				line-height: 48rpx;
-				padding: 6rpx 24rpx;
-			}
-		}
-	}
-
-	.no-goods {
-		display: flex;
-		flex-direction: column;
-		height: 472rpx;
-
-		image {
-			width: 100%;
-			display: block;
-			margin: 0 auto;
-		}
-
-		.fontimg {
-			text-align: center;
-			color: #bebebe;
-		}
-	}
+<template>
+	<view :style="colorStyle">
+		<view class="points-swiper">
+			<image class="bag" src="../../static/images/jf-head.png" mode=""></image>
+			<view class="swiper">
+				<swiper indicator-dots="true" :autoplay="autoplay" :circular="circular" :interval="interval"
+					:duration="duration" indicator-color="rgba(255,255,255,0.6)" indicator-active-color="#fff">
+					<block v-for="(item, index) in imgUrls" :key="index">
+						<swiper-item>
+							<image :src="item.img" class="slide-image" @click="goPages(item)"></image>
+						</swiper-item>
+					</block>
+				</swiper>
+			</view>
+		</view>
+		<view class="model">
+			<view class="model-list" v-for="(model,index) in modelList" :key="index" @click="jump(model.url)">
+				<image class="img" :src="model.imgUrl" mode=""></image>
+				<text>{{model.title}}</text>
+			</view>
+		</view>
+		<view class="body">
+			<view class="body-title">
+				<text class="title">{{$t(`大家都在换`)}}</text>
+				<text class="jump-trip" @click="jumpMore">{{$t(`查看更多`)}}
+					<text class="iconfont icon-xiangyou"></text></text>
+			</view>
+			<view class="product-list" v-if="goodList.length">
+				<view class="product-item" v-for="(item, index) in goodList" @click="goGoodsDetail(item)">
+					<image :src="item.image"></image>
+					<view class="info">
+						<view class="title line1">{{ item.title }}</view>
+						<view class="price-box">
+							{{ item.price }} {{$t(`积分`)}}
+						</view>
+						<view class="sales">{{item.sales}}{{$t(`人兑换`)}}</view>
+					</view>
+				</view>
+			</view>
+			<view v-else class="no-goods">
+				<image :src="imgHost + '/statics/images/no-thing.png'" mode=""></image>
+				<view class="fontimg">{{$t(`暂无商品,去看点别的吧`)}}</view>
+			</view>
+			<view class="footer">
+				<view class="body-title">
+					<text class="title">{{$t(`轻松赚积分`)}}</text>
+					<text></text>
+				</view>
+				<view class="footer-list">
+					<view class="list-left">
+						<image class="icon-sty" src="./static/go-shoping.png" mode=""></image>
+						<view class="list-left-right">
+							<view class="title">
+								{{$t(`购买商品`)}}
+							</view>
+							<view class="trip">
+								{{$t(`购买商品可获得积分奖励`)}}
+							</view>
+						</view>
+					</view>
+					<navigator url="/pages/index/index" open-type="switchTab" class="right-box">
+						<text class="go-jump">
+							{{$t(`去完成`)}}
+						</text>
+					</navigator>
+				</view>
+				<view class="footer-list">
+					<view class="list-left">
+						<image class="icon-sty" src="./static/everyday.png" mode=""></image>
+						<view class="list-left-right">
+							<view class="title">
+								{{$t(`每日签到活动`)}}
+							</view>
+							<view class="trip">
+								{{$t(`每日签到可获得积分奖励`)}}
+							</view>
+						</view>
+					</view>
+					<navigator url="/pages/users/user_sgin/index" class="right-box">
+						<text class="go-jump">
+							{{$t(`去完成`)}}
+						</text>
+					</navigator>
+				</view>
+				<view class="footer-list">
+					<view class="list-left">
+						<image class="icon-sty" src="./static/luck-draw.png" mode=""></image>
+						<view class="list-left-right">
+							<view class="title">
+								{{$t(`九宫格抽奖活动`)}}
+							</view>
+							<view class="trip">
+								{{$t(`幸运抽奖可获得积分奖励`)}}
+							</view>
+						</view>
+					</view>
+					<navigator url="/pages/goods/lottery/grids/index?type=1" class="right-box">
+						<text class="go-jump">
+							{{$t(`去完成`)}}
+						</text>
+					</navigator>
+				</view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	// import swipers from './components/swiper.vue';
+	import {
+		mapGetters
+	} from 'vuex';
+	import {
+		getStoreIntegral
+	} from '@/api/points_mall.js'
+	import {
+		goShopDetail
+	} from '@/libs/order.js';
+	import colors from "@/mixins/color";
+	import {
+		HTTP_REQUEST_URL
+	} from '@/config/app';
+	export default {
+		components: {
+			// swipers
+		},
+		mixins: [colors],
+		data() {
+			return {
+				imgHost: HTTP_REQUEST_URL,
+				autoplay: true,
+				circular: true,
+				interval: 3000,
+				duration: 500,
+				imgUrls: [],
+				goodList: [],
+				modelList: [{
+						title: this.$t(`我的积分`),
+						imgUrl: './static/my-point.png',
+						url: "/pages/users/user_integral/index"
+					},
+					{
+						title: this.$t(`每日签到`),
+						imgUrl: './static/sign-in.png',
+						url: '/pages/users/user_sgin/index'
+					}, {
+						title: this.$t(`积分抽奖`),
+						imgUrl: './static/points-lottery.png',
+						url: '/pages/goods/lottery/grids/index?type=1'
+					}, {
+						title: this.$t(`兑换记录`),
+						imgUrl: './static/exchange.png',
+						url: "/pages/points_mall/exchange_record"
+					},
+				]
+			}
+		},
+		computed: mapGetters(['isLogin']),
+		onLoad() {
+			this.getStoreIntegral()
+		},
+		watch: {
+			isLogin: {
+				handler: function(newV, oldV) {
+					if (newV == true) {
+						this.getStoreIntegral();
+					}
+				},
+				deep: true
+			},
+		},
+		methods: {
+			getStoreIntegral() {
+				getStoreIntegral().then(res => {
+					this.imgUrls = res.data.banner
+					this.goodList = res.data.list
+				})
+			},
+			// 去商品详情
+			goGoodsDetail(item) {
+				goShopDetail(item).then(res => {
+					uni.navigateTo({
+						url: `/pages/points_mall/integral_goods_details?id=${item.id}`
+					});
+				});
+			},
+			jumpMore() {
+				uni.navigateTo({
+					url: '/pages/points_mall/integral_goods_list'
+				})
+			},
+			goPages(item) {
+				let url = item.link;
+				this.$util.JumpPath(url);
+			},
+			jump(url) {
+				uni.navigateTo({
+					url
+				})
+			}
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.swiper,
+	swiper,
+	swiper-item,
+	.slide-image {
+		width: 100%;
+		height: 280rpx;
+	}
+
+	/deep/ .uni-swiper-wrapper {
+		border-radius: 10rpx;
+	}
+
+	.swiper {
+		padding: 20rpx;
+	}
+
+	.points-swiper {
+		position: relative;
+		width: 100%;
+		background-color: #fff;
+
+		.bag {
+			position: absolute;
+			width: 100%;
+			height: 285rpx;
+		}
+
+		.points-swiper-sty {
+			padding: 20rpx 26rpx;
+		}
+	}
+
+	.model {
+		display: flex;
+		justify-content: space-between;
+		padding: 56rpx 42rpx;
+		background-color: #fff;
+	}
+
+	.model-list {
+		display: flex;
+		flex-direction: column;
+		align-items: center;
+		justify-content: center;
+		font-size: 26rpx;
+		color: #333;
+		margin-top: 27rpx;
+		font-weight: 500;
+
+		.img {
+			width: 84rpx;
+			height: 84rpx;
+			margin-bottom: 19rpx;
+		}
+
+	}
+
+	.body {
+		background-color: #fff;
+		padding: 0 30rpx;
+		margin-top: 20rpx;
+
+		.body-title {
+			display: flex;
+			justify-content: space-between;
+			padding: 30rpx 0 10rpx 0;
+
+			.title {
+				font-size: 32rpx;
+				font-family: PingFang SC;
+				font-weight: bold;
+			}
+
+			.jump-trip,
+			.icon-xiangyou {
+				font-size: 24rpx;
+				color: #999999;
+			}
+		}
+
+		.product-list {
+			display: flex;
+			flex-wrap: wrap;
+			justify-content: space-between;
+			margin-top: 30rpx;
+
+			.product-item {
+				position: relative;
+				width: 334rpx;
+				background: #fff;
+				border-radius: 10rpx;
+				margin-bottom: 20rpx;
+				box-shadow: 0px 0px 7px rgba(0, 0, 0, 0.06);
+
+				image {
+					width: 100%;
+					height: 344rpx;
+					border-radius: 10rpx 10rpx 0 0;
+				}
+
+				.info {
+					padding: 14rpx 16rpx;
+
+					.title {
+						font-size: 28rpx;
+					}
+
+					.price-box {
+						font-size: 26rpx;
+						font-weight: 700;
+						margin-top: 8px;
+						color: var(--view-theme);
+					}
+
+					.sales {
+						font-size: 22rpx;
+						color: #999999;
+					}
+				}
+			}
+		}
+	}
+
+	.footer {
+		margin-top: 20rpx;
+
+		.footer-list {
+			display: flex;
+			justify-content: space-between;
+			padding: 26rpx 0;
+
+			.list-left {
+				display: flex;
+				align-items: center;
+
+				.icon-sty {
+					width: 80rpx;
+					height: 80rpx;
+					margin-right: 18rpx;
+				}
+
+				.list-left-right {
+					.title {
+						font-size: 28rpx;
+						font-weight: bold;
+						color: #333333;
+					}
+
+					.trip {
+						font-size: 22rpx;
+						color: #999999;
+					}
+				}
+			}
+
+			.right-box {
+				display: flex;
+				align-items: center;
+			}
+
+			.go-jump {
+				display: flex;
+				align-items: center;
+				background-color: #E93323;
+				border-radius: 26rpx;
+				color: #fff;
+				font-size: 28rpx;
+				height: 48rpx;
+				line-height: 48rpx;
+				padding: 6rpx 24rpx;
+			}
+		}
+	}
+
+	.no-goods {
+		display: flex;
+		flex-direction: column;
+		height: 472rpx;
+
+		image {
+			width: 100%;
+			display: block;
+			margin: 0 auto;
+		}
+
+		.fontimg {
+			text-align: center;
+			color: #bebebe;
+		}
+	}
 </style>

+ 3 - 0
template/uni-app/pages/users/user_spread_money/index.vue

@@ -25,6 +25,9 @@
 											<view class="fail-msg" v-if="child.fail_msg">
 												{{$t(`原因`)}}:{{child.fail_msg}}
 											</view>
+											<view class="fail-msg" v-else>
+												{{$t(`提现方式`)}}:{{child.extract_type}}
+											</view>
 										</view>
 										<view class='num font-color' v-if="child.pm == 1">+{{child.number}}</view>
 										<view class='num' v-else>-{{child.number}}</view>

+ 1 - 1
template/uni-app/pages/users/wechat_login/index.vue

@@ -315,7 +315,7 @@
 					}, {
 						tab: 3
 					});
-					// #endiff
+					// #endif
 				}
 			},
 			// #ifdef MP

+ 1 - 1
template/uni-app/static/css/style.scss

@@ -340,7 +340,7 @@
 .coupon-list .item.svip .line1 .image{width:30rpx;height:30rpx;margin-right:10rpx;vertical-align:middle;z-index:0;}
 
 .noCommodity {
-	border-top: 7rpx solid #f5f5f5
+	// border-top: 7rpx solid #f5f5f5
 }
 
 .noCommodity .pictrue {

+ 51 - 5
template/uni-app/utils/util.js

@@ -746,10 +746,10 @@ export default {
 		}
 
 		return 0
-	},
-	/*
-	* 获取当前时间
-	*/
+	},
+	/*
+	 * 获取当前时间
+	 */
 	getNowTime() {
 		let today = new Date();
 		let year = today.getFullYear(); // 获取当前年份
@@ -995,6 +995,52 @@ export default {
 			}
 			return status;
 		},
-	}
+	},
+	/**
+	 * 跳转路径封装函数
+	 * @param url 跳转路径
+	 */
+	JumpPath: function(url) {
+		let arr = url.split('@APPID=');
+		if (arr.length > 1) {
+			//#ifdef MP
+			uni.navigateToMiniProgram({
+				appId: arr[arr.length - 1], // 此为生活缴费appid
+				path: arr[0], // 此为生活缴费首页路径
+				envVersion: "release",
+				success: res => {
+					console.log("打开成功", res);
+				},
+				fail: err => {
+					console.log('sgdhgf', err);
+				}
+			})
+			//#endif
+			//#ifndef MP
+			this.Tips({
+				title: 'h5与app端不支持跳转外部小程序'
+			});
+			//#endif
+		} else {
+			if (url.indexOf("http") != -1) {
+				uni.navigateTo({
+					url: `/pages/annex/web_view/index?url=${url}`
+				});
+			} else {
+				if (['/pages/goods_cate/goods_cate', '/pages/order_addcart/order_addcart', '/pages/user/index',
+						'/pages/index/index'
+					]
+					.indexOf(url) == -1) {
+					uni.navigateTo({
+						url
+					})
+				} else {
+					uni.switchTab({
+						url
+					})
+				}
+			}
+		}
+	},
 
 }