quanwei
2025-12-09 ca425b889f3c1b5847ffc26a0229307f7f8ef43e
添加消费券
商户端添加页面diy
122 files added
40 files modified
14686 ■■■■■ changed files
admin/app/agent/model/product/Comment.php 2 ●●● patch | view | raw | blame | history
admin/app/api/controller/consumption/Log.php 31 ●●●●● patch | view | raw | blame | history
admin/app/api/controller/supplier/Page.php 217 ●●●●● patch | view | raw | blame | history
admin/app/api/model/store/Store.php 4 ●●●● patch | view | raw | blame | history
admin/app/api/model/supplier/page/Page.php 252 ●●●●● patch | view | raw | blame | history
admin/app/api/model/user/ConsumptionLog.php 23 ●●●●● patch | view | raw | blame | history
admin/app/api/service/consumption/ConsumptionDeductService.php 83 ●●●●● patch | view | raw | blame | history
admin/app/api/service/order/settled/AdvanceSettledService.php 4 ●●●● patch | view | raw | blame | history
admin/app/api/service/order/settled/BranchActivitySettledService.php 21 ●●●● patch | view | raw | blame | history
admin/app/api/service/order/settled/MasterOrderSettledService.php 6 ●●●●● patch | view | raw | blame | history
admin/app/api/service/order/settled/OrderSettledService.php 148 ●●●●● patch | view | raw | blame | history
admin/app/common/enum/settings/SettingEnum.php 6 ●●●●● patch | view | raw | blame | history
admin/app/common/model/plus/shareholder/Apply.php 4 ●●●● patch | view | raw | blame | history
admin/app/common/model/release/Capital.php 26 ●●●●● patch | view | raw | blame | history
admin/app/common/model/release/Cart.php 231 ●●●●● patch | view | raw | blame | history
admin/app/common/model/release/Cash.php 64 ●●●●● patch | view | raw | blame | history
admin/app/common/model/release/DemandApply.php 82 ●●●●● patch | view | raw | blame | history
admin/app/common/model/release/DemandProject.php 157 ●●●●● patch | view | raw | blame | history
admin/app/common/model/release/DemandUser.php 67 ●●●●● patch | view | raw | blame | history
admin/app/common/model/release/Order.php 109 ●●●●● patch | view | raw | blame | history
admin/app/common/model/release/Project.php 70 ●●●●● patch | view | raw | blame | history
admin/app/common/model/release/ReleaseCategory.php 41 ●●●●● patch | view | raw | blame | history
admin/app/common/model/release/ReleaseProjectImage.php 33 ●●●●● patch | view | raw | blame | history
admin/app/common/model/release/ReleaseProjectTag.php 47 ●●●●● patch | view | raw | blame | history
admin/app/common/model/release/Setting.php 398 ●●●●● patch | view | raw | blame | history
admin/app/common/model/release/SupplyApply.php 82 ●●●●● patch | view | raw | blame | history
admin/app/common/model/release/SupplyProject.php 186 ●●●●● patch | view | raw | blame | history
admin/app/common/model/release/SupplyUser.php 67 ●●●●● patch | view | raw | blame | history
admin/app/common/model/release/Tag.php 35 ●●●●● patch | view | raw | blame | history
admin/app/common/model/settings/Setting.php 21 ●●●●● patch | view | raw | blame | history
admin/app/common/model/supplier/Supplier.php 12 ●●●●● patch | view | raw | blame | history
admin/app/common/model/supplier/User.php 12 ●●●●● patch | view | raw | blame | history
admin/app/common/model/supplier/page/Page.php 809 ●●●●● patch | view | raw | blame | history
admin/app/common/model/user/ConsumptionLog.php 41 ●●●●● patch | view | raw | blame | history
admin/app/common/model/user/User.php 50 ●●●●● patch | view | raw | blame | history
admin/app/common/service/delivery/ExpressService.php 4 ●●●● patch | view | raw | blame | history
admin/app/common/service/order/OrderCompleteService.php 44 ●●●●● patch | view | raw | blame | history
admin/app/job/event/VipUserGrade.php 3 ●●●●● patch | view | raw | blame | history
admin/app/shop/controller/product/Product.php 16 ●●●● patch | view | raw | blame | history
admin/app/shop/controller/user/Consumption.php 40 ●●●●● patch | view | raw | blame | history
admin/app/shop/model/product/Comment.php 2 ●●● patch | view | raw | blame | history
admin/app/shop/model/user/ConsumptionLog.php 37 ●●●●● patch | view | raw | blame | history
admin/app/supplier/controller/product/Product.php 7 ●●●● patch | view | raw | blame | history
admin/app/supplier/controller/supplier/Page.php 254 ●●●●● patch | view | raw | blame | history
admin/app/supplier/model/supplier/page/Page.php 89 ●●●●● patch | view | raw | blame | history
mobile/main.js 10 ●●●●● patch | view | raw | blame | history
mobile/pages.json 9 ●●●● patch | view | raw | blame | history
mobile/pages/order/confirm-order.vue 30 ●●●●● patch | view | raw | blame | history
mobile/pages/order/pay-success/pay-success.vue 6 ●●●●● patch | view | raw | blame | history
mobile/pages/shop/shop.vue 540 ●●●● patch | view | raw | blame | history
mobile/pages/shop/shop_list.vue 7 ●●●●● patch | view | raw | blame | history
mobile/pages/tabBar/user/index.vue 8 ●●●● patch | view | raw | blame | history
mobile/pages/user/index/index.vue 6 ●●●● patch | view | raw | blame | history
mobile/store/index.js 6 ●●●● patch | view | raw | blame | history
shop_vue/src/api/consumption.js 17 ●●●●● patch | view | raw | blame | history
shop_vue/src/views/product/product/add.vue 8 ●●●●● patch | view | raw | blame | history
shop_vue/src/views/product/product/edit.vue 12 ●●●●● patch | view | raw | blame | history
shop_vue/src/views/product/product/index.vue 12 ●●●●● patch | view | raw | blame | history
shop_vue/src/views/product/product/part/Basic.vue 29 ●●●● patch | view | raw | blame | history
shop_vue/src/views/product/product/part/Buyset.vue 23 ●●●●● patch | view | raw | blame | history
shop_vue/src/views/product/product/part/spec/Single.vue 3 ●●●●● patch | view | raw | blame | history
shop_vue/src/views/product/product/part/spec/many/Table.vue 6 ●●●●● patch | view | raw | blame | history
shop_vue/src/views/user/consumption/index.vue 42 ●●●●● patch | view | raw | blame | history
shop_vue/src/views/user/consumption/part/Log.vue 134 ●●●●● patch | view | raw | blame | history
shop_vue/src/views/user/consumption/part/Setting.vue 172 ●●●●● patch | view | raw | blame | history
supplier_vue/src/api/link.js 12 ●●●●● patch | view | raw | blame | history
supplier_vue/src/api/page.js 119 ●●●●● patch | view | raw | blame | history
supplier_vue/src/assets/img/category_40.jpg patch | view | raw | blame | history
supplier_vue/src/assets/img/theme1.jpg patch | view | raw | blame | history
supplier_vue/src/assets/img/theme2.jpg patch | view | raw | blame | history
supplier_vue/src/assets/img/theme3.jpg patch | view | raw | blame | history
supplier_vue/src/assets/img/theme4.jpg patch | view | raw | blame | history
supplier_vue/src/assets/img/theme5.jpg patch | view | raw | blame | history
supplier_vue/src/assets/img/theme6.jpg patch | view | raw | blame | history
supplier_vue/src/assets/img/theme7.jpg patch | view | raw | blame | history
supplier_vue/src/components/setlink/SetTab.vue 102 ●●●●● patch | view | raw | blame | history
supplier_vue/src/components/setlink/part/Article.vue 131 ●●●●● patch | view | raw | blame | history
supplier_vue/src/components/setlink/part/DiyPage.vue 66 ●●●●● patch | view | raw | blame | history
supplier_vue/src/components/setlink/part/H5.vue 37 ●●●●● patch | view | raw | blame | history
supplier_vue/src/components/setlink/part/Marketing.vue 175 ●●●●● patch | view | raw | blame | history
supplier_vue/src/components/setlink/part/Menu.vue 165 ●●●●● patch | view | raw | blame | history
supplier_vue/src/components/setlink/part/Pages.vue 117 ●●●●● patch | view | raw | blame | history
supplier_vue/src/components/setlink/part/SmallProgram.vue 39 ●●●●● patch | view | raw | blame | history
supplier_vue/src/components/setlink/part/Store.vue 146 ●●●●● patch | view | raw | blame | history
supplier_vue/src/views/page/page/add.vue 137 ●●●●● patch | view | raw | blame | history
supplier_vue/src/views/page/page/addpage.vue 136 ●●●●● patch | view | raw | blame | history
supplier_vue/src/views/page/page/bottom/Edit.vue 133 ●●●●● patch | view | raw | blame | history
supplier_vue/src/views/page/page/bottomnav.vue 332 ●●●●● patch | view | raw | blame | history
supplier_vue/src/views/page/page/category.vue 111 ●●●●● patch | view | raw | blame | history
supplier_vue/src/views/page/page/diy/Model.vue 313 ●●●●● patch | view | raw | blame | history
supplier_vue/src/views/page/page/diy/Params.vue 407 ●●●●● patch | view | raw | blame | history
supplier_vue/src/views/page/page/diy/Preview.vue 322 ●●●●● patch | view | raw | blame | history
supplier_vue/src/views/page/page/diy/Type.vue 72 ●●●●● patch | view | raw | blame | history
supplier_vue/src/views/page/page/diy/model/Article.vue 77 ●●●●● patch | view | raw | blame | history
supplier_vue/src/views/page/page/diy/model/Banner.vue 120 ●●●●● patch | view | raw | blame | history
supplier_vue/src/views/page/page/diy/model/BargainProduct.vue 193 ●●●●● patch | view | raw | blame | history
supplier_vue/src/views/page/page/diy/model/Blank.vue 36 ●●●●● patch | view | raw | blame | history
supplier_vue/src/views/page/page/diy/model/Button.vue 58 ●●●●● patch | view | raw | blame | history
supplier_vue/src/views/page/page/diy/model/Coupon.vue 106 ●●●●● patch | view | raw | blame | history
supplier_vue/src/views/page/page/diy/model/Guide.vue 36 ●●●●● patch | view | raw | blame | history
supplier_vue/src/views/page/page/diy/model/ImageSingle.vue 37 ●●●●● patch | view | raw | blame | history
supplier_vue/src/views/page/page/diy/model/Live.vue 93 ●●●●● patch | view | raw | blame | history
supplier_vue/src/views/page/page/diy/model/NavBar.vue 50 ●●●●● patch | view | raw | blame | history
supplier_vue/src/views/page/page/diy/model/Notice.vue 44 ●●●●● patch | view | raw | blame | history
supplier_vue/src/views/page/page/diy/model/Preview.vue 173 ●●●●● patch | view | raw | blame | history
supplier_vue/src/views/page/page/diy/model/Product.vue 211 ●●●●● patch | view | raw | blame | history
supplier_vue/src/views/page/page/diy/model/RichText.vue 37 ●●●●● patch | view | raw | blame | history
supplier_vue/src/views/page/page/diy/model/Search.vue 50 ●●●●● patch | view | raw | blame | history
supplier_vue/src/views/page/page/diy/model/Seckill.vue 165 ●●●●● patch | view | raw | blame | history
supplier_vue/src/views/page/page/diy/model/Service.vue 44 ●●●●● patch | view | raw | blame | history
supplier_vue/src/views/page/page/diy/model/Setpages.vue 77 ●●●●● patch | view | raw | blame | history
supplier_vue/src/views/page/page/diy/model/Special.vue 54 ●●●●● patch | view | raw | blame | history
supplier_vue/src/views/page/page/diy/model/Store.vue 70 ●●●●● patch | view | raw | blame | history
supplier_vue/src/views/page/page/diy/model/Tab.vue 66 ●●●●● patch | view | raw | blame | history
supplier_vue/src/views/page/page/diy/model/Title.vue 78 ●●●●● patch | view | raw | blame | history
supplier_vue/src/views/page/page/diy/model/Video.vue 41 ●●●●● patch | view | raw | blame | history
supplier_vue/src/views/page/page/diy/model/Window.vue 81 ●●●●● patch | view | raw | blame | history
supplier_vue/src/views/page/page/diy/model/assembleProduct.vue 221 ●●●●● patch | view | raw | blame | history
supplier_vue/src/views/page/page/diy/params/Article.vue 77 ●●●●● patch | view | raw | blame | history
supplier_vue/src/views/page/page/diy/params/Banner.vue 112 ●●●●● patch | view | raw | blame | history
supplier_vue/src/views/page/page/diy/params/BargainProduct.vue 97 ●●●●● patch | view | raw | blame | history
supplier_vue/src/views/page/page/diy/params/Blank.vue 46 ●●●●● patch | view | raw | blame | history
supplier_vue/src/views/page/page/diy/params/Button.vue 99 ●●●●● patch | view | raw | blame | history
supplier_vue/src/views/page/page/diy/params/Coupon.vue 41 ●●●●● patch | view | raw | blame | history
supplier_vue/src/views/page/page/diy/params/Guide.vue 62 ●●●●● patch | view | raw | blame | history
supplier_vue/src/views/page/page/diy/params/ImageSingle.vue 93 ●●●●● patch | view | raw | blame | history
supplier_vue/src/views/page/page/diy/params/Live.vue 55 ●●●●● patch | view | raw | blame | history
supplier_vue/src/views/page/page/diy/params/NavBar.vue 104 ●●●●● patch | view | raw | blame | history
supplier_vue/src/views/page/page/diy/params/Notice.vue 62 ●●●●● patch | view | raw | blame | history
supplier_vue/src/views/page/page/diy/params/Preview.vue 83 ●●●●● patch | view | raw | blame | history
supplier_vue/src/views/page/page/diy/params/Product.vue 246 ●●●●● patch | view | raw | blame | history
supplier_vue/src/views/page/page/diy/params/RichText.vue 69 ●●●●● patch | view | raw | blame | history
supplier_vue/src/views/page/page/diy/params/Search.vue 47 ●●●●● patch | view | raw | blame | history
supplier_vue/src/views/page/page/diy/params/Seckill.vue 79 ●●●●● patch | view | raw | blame | history
supplier_vue/src/views/page/page/diy/params/Service.vue 60 ●●●●● patch | view | raw | blame | history
supplier_vue/src/views/page/page/diy/params/Setpages.vue 97 ●●●●● patch | view | raw | blame | history
supplier_vue/src/views/page/page/diy/params/Special.vue 87 ●●●●● patch | view | raw | blame | history
supplier_vue/src/views/page/page/diy/params/Store.vue 102 ●●●●● patch | view | raw | blame | history
supplier_vue/src/views/page/page/diy/params/Tab.vue 118 ●●●●● patch | view | raw | blame | history
supplier_vue/src/views/page/page/diy/params/Title.vue 68 ●●●●● patch | view | raw | blame | history
supplier_vue/src/views/page/page/diy/params/Video.vue 72 ●●●●● patch | view | raw | blame | history
supplier_vue/src/views/page/page/diy/params/Window.vue 98 ●●●●● patch | view | raw | blame | history
supplier_vue/src/views/page/page/diy/params/assembleProduct.vue 58 ●●●●● patch | view | raw | blame | history
supplier_vue/src/views/page/page/edit.vue 141 ●●●●● patch | view | raw | blame | history
supplier_vue/src/views/page/page/editpage.vue 138 ●●●●● patch | view | raw | blame | history
supplier_vue/src/views/page/page/home.vue 129 ●●●●● patch | view | raw | blame | history
supplier_vue/src/views/page/page/index.vue 190 ●●●●● patch | view | raw | blame | history
supplier_vue/src/views/page/page/list.vue 231 ●●●●● patch | view | raw | blame | history
supplier_vue/src/views/page/page/mymenu/add.vue 188 ●●●●● patch | view | raw | blame | history
supplier_vue/src/views/page/page/mymenu/edit.vue 197 ●●●●● patch | view | raw | blame | history
supplier_vue/src/views/page/page/mymenu/index.vue 212 ●●●●● patch | view | raw | blame | history
supplier_vue/src/views/page/page/nav.vue 267 ●●●●● patch | view | raw | blame | history
supplier_vue/src/views/page/theme/index.vue 146 ●●●●● patch | view | raw | blame | history
supplier_vue/src/views/product/product/add.vue 8 ●●●●● patch | view | raw | blame | history
supplier_vue/src/views/product/product/edit.vue 9 ●●●●● patch | view | raw | blame | history
supplier_vue/src/views/product/product/part/Basic.vue 13 ●●●●● patch | view | raw | blame | history
supplier_vue/src/views/product/product/part/Buyset.vue 18 ●●●●● patch | view | raw | blame | history
supplier_vue/src/views/product/product/part/spec/Single.vue 3 ●●●●● patch | view | raw | blame | history
supplier_vue/src/views/product/product/part/spec/many/Table.vue 9 ●●●● patch | view | raw | blame | history
supplier_vue/src/views/user/consumption/index.vue 42 ●●●●● patch | view | raw | blame | history
supplier_vue/src/views/user/consumption/part/Log.vue 134 ●●●●● patch | view | raw | blame | history
supplier_vue/src/views/user/consumption/part/Setting.vue 172 ●●●●● patch | view | raw | blame | history
admin/app/agent/model/product/Comment.php
@@ -49,7 +49,7 @@
            ->field('round(avg(express_score),1) as score')->find();
        $server = $this->where(['shop_supplier_id' => $shop_supplier_id, 'status'=>1,'is_delete'=>0])
            ->field('round(avg(server_score),1) as score')->find();
        $describe = $this->where(['shop_supplier_id '=> $shop_supplier_id,'status'=>1,'is_delete'=>0])
        $describe = $this->where(['shop_supplier_id'=> $shop_supplier_id,'status'=>1,'is_delete'=>0])
            ->field('round(avg(describe_score),1) as score')->find();
        //更新店铺分数
        $SupplierModel->where('shop_supplier_id','=', $shop_supplier_id)
admin/app/api/controller/consumption/Log.php
New file
@@ -0,0 +1,31 @@
<?php
namespace app\api\controller\consumption;
use app\api\controller\Controller;
use app\api\model\user\ConsumptionLog as ConsumptionLogModel;
use app\api\model\settings\Setting as SettingModel;
/**
 * 消费券明细控制器
 */
class Log extends Controller
{
    /**
     * 消费券明细列表
     */
    public function index()
    {
        $user = $this->getUser();
        $consumer_coupon = $user['consumer_coupon'];
        $list = (new ConsumptionLogModel)->getList($user['user_id'], $this->postData());
        //消费券商城是否开放
        $is_open = false;
        //消费券设置
        $setting = SettingModel::getItem('consumption');
        $discount_ratio = $setting['discount']['discount_ratio'];
        $is_trans_balance = $setting['is_trans_balance'];
        return $this->renderSuccess('', compact('list', 'consumer_coupon', 'is_open', 'discount_ratio', 'is_trans_balance'));
    }
}
admin/app/api/controller/supplier/Page.php
New file
@@ -0,0 +1,217 @@
<?php
namespace app\api\controller\supplier;
use app\api\controller\Controller;
use app\api\model\supplier\page\Page as AppPage;
use app\api\model\settings\Setting as SettingModel;
use app\api\model\supplier\Supplier;
use app\common\enum\settings\SettingEnum;
use app\common\model\app\AppUpdate as AppUpdateModel;
use app\common\model\supplier\Service as ServiceModel;
use app\api\model\plus\chat\Chat as ChatModel;
use app\common\model\settings\Region as RegionModel;
use app\common\model\store\Store as StoreModel;
/**
 * 页面控制器
 */
class Page extends Controller
{
    /**
     * 首页
     */
    public function index($page_id = null, $url = '',$shop_supplier_id)
    {
        $shop_supplier=Supplier::detail($shop_supplier_id);
        if (!$shop_supplier) {
            return $this->renderError('供应商不存在');
        }
        $page=(new AppPage())
            ->where('is_default',1)
            ->where('page_type',10)
            ->where('shop_supplier_id',$shop_supplier_id)
            ->find();
        if (!$page) {
            $page=(new AppPage())
                ->where('page_type',10)
                ->where('shop_supplier_id',$shop_supplier_id)
                ->find();
        }
        if ($page){
            $page_id=$page['page_id'];
        }
        // 页面元素
        $data = AppPage::getPageData($this->getUser(false), $page_id,'',$shop_supplier_id);
        //消息条数
        $Chat = new ChatModel;
        $data['msgNum'] = $Chat->mCount($this->getUser(false));
        $data['setting'] = array(
            'collection' => SettingModel::getItem('collection'),
            'officia' => SettingModel::getItem('officia'),
            'homepush' => SettingModel::getItem('homepush'),
            'store' => SettingModel::getItem('store'),
        );
        // 扫一扫参数
        $data['signPackage'] = $this->getScanParams($url)['signPackage'];
        return $this->renderSuccess('', $data);
    }
    /**
     * 单独获取首页数据
     */
    public function getPageData($page_id = null,$city_supplier_ids='')
    {
        // 页面元素
        $data = AppPage::getPageData($this->getUser(false), $page_id,$city_supplier_ids);
        return $this->renderSuccess('', $data);
    }
    /**
     * 首页
     */
    public function diy($page_id = null, $url = '')
    {
        // 页面元素
        $data = AppPage::getPageData($this->getUser(false), $page_id);
        // 微信公众号分享参数
        $data['share'] = $this->getShareParams($url, $data['page']['params']['share_title'], $data['page']['params']['share_title'], '/pages/diy-page/diy-page', $data['page']['style']['toplogo']);
        return $this->renderSuccess('', $data);
    }
    // 公众号客服
    public function mpService($shop_supplier_id)
    {
        $mp_service = ServiceModel::detail($shop_supplier_id);
        return $this->renderSuccess('', compact('mp_service'));
    }
    //底部导航
    public function nav()
    {
        $data['vars'] = SettingModel::getItem(SettingEnum::NAV);
        $data['theme'] = SettingModel::getItem(SettingEnum::THEME);
        $data['points_name'] = SettingModel::getPointsName();
        return $this->renderSuccess('', $data);
    }
    // app更新
    public function update($name, $version, $platform)
    {
        $result = [
            'update' => false,
            'wgtUrl' => '',
            'pkgUrl' => '',
        ];
        try {
            $model = AppUpdateModel::getLast();
            if($platform == 'android'){
                $compare_version = $model['version_android'];
            }else{
                $compare_version = $model['version_ios'];
            }
            // 这里简单判定下,不相等就是有更新。
            if($model && $version != $compare_version){
                $currentVersions = explode('.', $version);
                $resultVersions = explode('.', $compare_version);
                if ($currentVersions[0] < $resultVersions[0]) {
                    // 说明有大版本更新
                    $result['update'] = true;
                    $result['pkgUrl'] = $platform == 'android' ? $model['pkg_url_android'] : $model['pkg_url_ios'];
                    log_write('大版本');
                } else {
                    // 其它情况均认为是小版本更新
                    $result['update'] = true;
                    $result['wgtUrl'] = $model['wgt_url'];
                    log_write('小版本'.$result['wgtUrl']);
                }
            }
        } catch (\Exception $e) {
        }
        return $this->renderSuccess('', compact('result'));
    }
    //坐标解析站点并根据站点获取匹配的商户
    public function getCitySupplierBycity($city)
    {
        $city_id = RegionModel::getIdByCityName($city, 2);
        $storeData = StoreModel::where('city_id', '=', $city_id)->select()->toArray();
        $supplier_ids = array_column($storeData,'shop_supplier_id');
        $name = $city;
        $level = 2;
        return $this->renderSuccess('', compact('supplier_ids', 'city', 'name', 'level'));
    }
    //坐标解析站点并根据站点获取匹配的商户 by yj
    public function getCitySupplierByRegion($city)
    {
        $region_id = RegionModel::getIdByCityName($city, 3);
        $storeData = StoreModel::where('region_id','=',$region_id)->select()->toArray();
        $supplier_ids = array_column($storeData,'shop_supplier_id');
        $name = RegionModel::getParentNameById($region_id);
        $level = 3;
        return $this->renderSuccess('', compact('supplier_ids','city', 'name', 'level'));
    }
    //坐标解析站点并根据站点获取匹配的商户
    public function getCitySupplier($longitude,$latitude)
    {
        //$city=$this->getAddress($longitude,$latitude);
        $address = $this->getAddress($longitude,$latitude);//省
        $name = $address["city"];
        $city = $address["district"];
        $region_id = RegionModel::getIdByCityName($city,3);
        $storeData = StoreModel::where('region_id','=',$region_id)->select()->toArray();
        /*$city=$address["city"];
        $city_id = RegionModel::getIdByCityName($city,2);
        if(empty($storeData)){
            $storeData=StoreModel::where('city_id','=',$city_id)->select()->toArray();
        }*/
        $supplier_ids = array_column($storeData,'shop_supplier_id');
        $level = 3;
        return $this->renderSuccess('',compact('supplier_ids', 'city', 'name', 'level'));
    }
    //输入经纬度获取地址(腾讯地图)
    function getAddress($longitude,$latitude) {
      header("Content-type:text/html;charset=utf-8");
      $ak = 'LS7BZ-NHSWK-CWOJQ-AJC7Y-H5HE2-UGBWR';//你腾讯地图的k值
      $url = "http://apis.map.qq.com/ws/geocoder/v1/?location={$latitude},{$longitude}&key={$ak}";
      $json = file_get_contents($url);
      $data = json_decode($json,TRUE);
      //return $data['result']['ad_info']['city'];//获取地址
        return $data['result']['ad_info'];//获取地址
    }
    //坐标解析站点并根据站点获取匹配的商户
    public function getCityData()
    {
        $formData = SettingModel::getItem('store');
        $citysData = array();
        if(!empty($formData['citysData'])){
               $citysData = unserialize($formData['citysData']);
        }
        return $this->renderSuccess('', $citysData);
    }
    //坐标解析站点并根据站点获取匹配的商户
    public function getCityList()
    {
        $formData = SettingModel::getItem('store');
        $citysData = array();
        if(!empty($formData['citysData'])){
               $citysData = unserialize($formData['citysData']);
        }
        // 整理数据 by lyzflash
        $cityList = array();
        foreach ($citysData as $row) {
            $cityList = array_merge($cityList, $row['citys']);
        }
        $cityList = array_values(array_sort($cityList, 'pinyin'));
        // 字母列表
        $alphabet = array_unique(array_merge(['area', 'record'], array_column($cityList, 'first')));
        return $this->renderSuccess('', compact('cityList', 'alphabet'));
    }
    //调用接口执行定时器
    public function ss(){
         event('AgentOrder');
    }
}
admin/app/api/model/store/Store.php
@@ -53,6 +53,10 @@
        $list = $data->isEmpty() ? [] : $data->toArray();
        $sortArr = [];
        foreach ($list as &$store) {
            if (empty($store['longitude']) || empty($store['latitude'])) {// 排序列
                $sortArr[] = 0;
                continue;
            }
            // 计算距离
            $distance = self::getDistance($longitude, $latitude, $store['longitude'], $store['latitude']);
            // 排序列
admin/app/api/model/supplier/page/Page.php
New file
@@ -0,0 +1,252 @@
<?php
namespace app\api\model\supplier\page;
use app\api\model\product\Product as ProductModel;
use app\api\model\plus\article\Article;
use app\common\model\supplier\page\Page as PageModel;
use app\api\model\plus\coupon\Coupon;
use app\api\model\plus\seckill\Product as SeckillProductModel;
use app\api\model\plus\seckill\Active as SeckillActiveModel;
use app\api\model\plus\assemble\Product as AssembleProductModel;
use app\api\model\plus\assemble\Active as AssembleActiveModel;
use app\api\model\plus\bargain\Product as BargainProductModel;
use app\api\model\plus\bargain\Active as BargainActiveModel;
use app\api\model\plus\live\Room as RoomModel;
/**
 * 首页模型
 */
class Page extends PageModel
{
    /**
     * 隐藏字段
     */
    protected $hidden = [
        'app_id',
        'create_time',
        'update_time'
    ];
    /**
     * DIY页面详情
     */
    public static function getPageData($user, $page_id = null,$city_supplier_ids='',$shop_supplier_id=0)
    {
        // 页面详情
        $detail = $page_id > 0 ? parent::detail($page_id) : parent::getDefault($shop_supplier_id);
        // 页面diy元素
        $items = $detail['page_data']['items'];
        // 页面顶部导航
        isset($detail['page_data']['page']) && $items['page'] = $detail['page_data']['page'];
        // 获取动态数据
        $model = new self;
        foreach ($items as $key => $item) {
            unset($items[$key]['defaultData']);
            if ($item['type'] === 'window') {
                $items[$key]['data'] = array_values($item['data']);
            } else if ($item['type'] === 'product') {
                $items[$key]['data'] = $model->getProductList($user, $item,$city_supplier_ids,$shop_supplier_id);
            } else if ($item['type'] === 'coupon') {
                $items[$key]['data'] = $model->getCouponList($user, $item, true, 1);
            } else if ($item['type'] === 'article') {
                $items[$key]['data'] = $model->getArticleList($item);
            } else if ($item['type'] === 'special') {
                $items[$key]['data'] = $model->getSpecialList($item);
            } else if ($item['type'] === 'seckillProduct') {
                // 如果没有活动,则不显示
                $item_data = $model->getSeckillList($item);
                if (empty($item_data)) {
                    unset($items[$key]);
                } else {
                    $items[$key]['data'] = $item_data;
                }
            } else if ($item['type'] === 'assembleProduct') {
                // 如果没有活动,则不显示
                $item_data = $model->getAssembleList($item);
                if (empty($item_data)) {
                    unset($items[$key]);
                } else {
                    $items[$key]['data'] = $item_data;
                }
            } else if ($item['type'] === 'bargainProduct') {
                // 如果没有活动,则不显示
                $item_data = $model->getBargainList($item);
                if (empty($item_data)) {
                    unset($items[$key]);
                } else {
                    $items[$key]['data'] = $item_data;
                }
            } else if ($item['type'] === 'live') {
                $items[$key]['data'] = $model->getLiveList($item);
            } else if ($item['type'] === 'previewProduct') {
                $items[$key]['data'] = $model->getPreviewList($user, $item);
            }
        }
        return ['page' => $items['page'], 'items' => $items];
    }
    /**
     * 商品组件:获取商品列表
     */
    private function getProductList($user, $item,$city_supplier_ids='',$shop_supplier_id=0)
    {
        // 获取商品数据
        $model = new ProductModel;
        if ($item['params']['source'] === 'choice') {
            // 数据来源:手动
            $productIds = array_column($item['data'], 'product_id');
            $productList = $model->getListByIdsFromApi($productIds, $user);
        } else {
            $list = [];
            // 数据来源:自动
            $productList = $model->getList([
                'shop_supplier_id'=>$shop_supplier_id,
                'type' => 'sell',
                'category_id' => $item['params']['auto']['category'],
                'sortType' => $item['params']['auto']['productSort'],
                'list_rows' => $item['params']['auto']['showNum'],
                'audit_status' => 10,
                'city_supplier_ids' => $city_supplier_ids,
            ], $user);
        }
        if ($productList->isEmpty()) return [];
        // 格式化商品列表
        $data = [];
        foreach ($productList as $product) {
            $show_sku = ProductModel::getShowSku($product);
            $data[] = [
                'product_id' => $product['product_id'],
                'product_name' => $product['product_name'],
                'selling_point' => $product['selling_point'],
                'image' => $product['image'][0]['file_path'],
                'product_image' => $product['image'][0]['file_path'],
                'product_price' => $show_sku['product_price'],
                'line_price' => $show_sku['line_price'],
                'product_sales' => $product['product_sales'],
                'shop_supplier_id'=>$product['shop_supplier_id'],
            ];
        }
        return $data;
    }
    /**
     * 优惠券组件:获取优惠券列表
     */
    private function getCouponList($user, $item)
    {
        // 获取优惠券数据
        return (new Coupon)->getList($user, $item['params']['limit'], true);
    }
    /**
     * 文章组件:获取文章列表
     */
    private function getArticleList($item)
    {
        // 获取文章数据
        $model = new Article;
        $articleList = $model->getList($item['params']['auto']['category'], $item['params']['auto']['showNum'],0);
        return $articleList->isEmpty() ? [] : $articleList->toArray()['data'];
    }
    /**
     * 头条快报:获取头条列表
     */
    private function getSpecialList($item)
    {
        // 获取头条数据
        $model = new Article;
        $articleList = $model->getList($item['params']['auto']['category'], $item['params']['auto']['showNum'],0);
        return $articleList->isEmpty() ? [] : $articleList->toArray()['data'];
    }
    /**
     * 获取限时秒杀
     */
    private function getSeckillList($item)
    {
        // 获取秒杀数据
        $seckill = SeckillActiveModel::getActive();
        if ($seckill) {
            $product_model = new SeckillProductModel;
            $seckill['product_list'] = $product_model->getProductList($seckill['seckill_activity_id'], $item['params']['showNum']);
        }
        return $seckill;
    }
    /**
     * 获取限时拼团
     */
    private function getAssembleList($item)
    {
        // 获取拼团数据
        $assemble = AssembleActiveModel::getActive();
        if ($assemble) {
            $assemble->visible(['assemble_activity_id', 'title', 'start_time', 'end_time']);
            $product_model = new AssembleProductModel;
            $assemble['product_list'] = $product_model->getProductList($assemble['assemble_activity_id'], $item['params']['showNum']);
        }
        return $assemble;
    }
    /**
     * 获取限时砍价
     */
    private function getBargainList($item)
    {
        // 获取拼团数据
        $bargain = BargainActiveModel::getActive();
        if ($bargain) {
            $bargain->visible(['bargain_activity_id', 'title', 'start_time', 'end_time']);
            $product_model = new BargainProductModel;
            $bargain['product_list'] = $product_model->getProductList($bargain['bargain_activity_id'], $item['params']['showNum']);
        }
        return $bargain;
    }
    /**
     * 直播
     */
    private function getLiveList($item)
    {
        // 获取直播数据
        $model = new RoomModel();
        $liveList = $model->getDiyList($item['params']['showNum']);
        return $liveList->isEmpty() ? [] : $liveList->toArray();
    }
    /**
     * 获取限时秒杀
     */
    private function getPreviewList($user, $item)
    {
        // 获取商品数据
        $model = new ProductModel;
        // 数据来源:自动
        $productList = $model->getList([
            'type' => 'preview',
            'list_rows' => $item['params']['showNum']
        ], $user);
        if ($productList->isEmpty()) return [];
        // 格式化商品列表
        $data = [];
        foreach ($productList as $product) {
            $show_sku = ProductModel::getShowSku($product);
            $data[] = [
                'product_id' => $product['product_id'],
                'product_name' => $product['product_name'],
                'selling_point' => $product['selling_point'],
                'image' => $product['image'][0]['file_path'],
                'product_image' => $product['image'][0]['file_path'],
                'product_price' => $show_sku['product_price'],
                'line_price' => $show_sku['line_price'],
                'product_sales' => $product['product_sales'],
                'preview_time' => $product['preview_time'],
                'is_preview' => $product['is_preview'],
            ];
        }
        return $data;
    }
}
admin/app/api/model/user/ConsumptionLog.php
New file
@@ -0,0 +1,23 @@
<?php
namespace app\api\model\user;
use app\common\model\user\ConsumptionLog as consumptionLogModel;
/**
 * 消费券明细模型
 */
class ConsumptionLog extends consumptionLogModel
{
    /**
     * 获取日志明细列表
     */
    public function getList($userId,$limit)
    {
        // 获取列表数据
        return $this->where('user_id', '=', $userId)
            ->order(['create_time' => 'desc'])
            ->paginate($limit);
    }
}
admin/app/api/service/consumption/ConsumptionDeductService.php
New file
@@ -0,0 +1,83 @@
<?php
namespace app\api\service\consumption;
use app\common\library\helper;
use app\api\model\settings\Setting as SettingModel;
/**
 * 消费券抵扣类
 */
class ConsumptionDeductService
{
    private $productList;
    public function __construct($productList)
    {
        $this->productList = $productList;
    }
    public function setProductConsumption($maxPointsNumCount, $actualPointsNum)
    {
        // 计算实际消费券抵扣数量
        $this->setproductListPointsNum($maxPointsNumCount, $actualPointsNum);
        // 总抵扣数量
        $totalPointsNum = helper::getArrayColumnSum($this->productList, 'consumption_num');
        // 填充余数
        $this->setproductListPointsNumFill($actualPointsNum, $totalPointsNum);
        $this->setproductListPointsNumDiff($actualPointsNum, $totalPointsNum);
        // 计算实际消费券抵扣金额
        $this->setproductListPointsMoney();
        return true;
    }
    /**
     * 计算实际消费券抵扣数量
     */
    private function setproductListPointsNum($maxPointsNumCount, $actualPointsNum)
    {
        foreach ($this->productList as &$product) {
            if (!$product['is_consumption_discount']) continue;
            $product['consumption_num'] = floor($product['max_consumption_num'] / $maxPointsNumCount * $actualPointsNum);
        }
    }
    /**
     * 计算实际积分抵扣金额
     */
    private function setproductListPointsMoney()
    {
        $setting = SettingModel::getItem('consumption');
        foreach ($this->productList as &$product) {
            if (!$product['is_consumption_discount']) continue;
            $product['consumption_money'] = helper::bcmul($product['consumption_num'], $setting['discount']['discount_ratio']);
        }
    }
    private function setproductListPointsNumFill($actualPointsNum, $totalPointsNum)
    {
        if ($totalPointsNum === 0) {
            $temReducedMoney = $actualPointsNum;
            foreach ($this->productList as &$product) {
                if (!$product['is_consumption_discount']) continue;
                if ($temReducedMoney === 0) break;
                $product['consumption_num'] = 1;
                $temReducedMoney--;
            }
        }
        return true;
    }
    private function setproductListPointsNumDiff($actualPointsNum, $totalPointsNum)
    {
        $tempDiff = $actualPointsNum - $totalPointsNum;
        foreach ($this->productList as &$product) {
            if (!$product['is_consumption_discount']) continue;
            if ($tempDiff < 1) break;
            $product['consumption_num'] = $product['consumption_num'] + 1;
            $tempDiff--;
        }
        return true;
    }
}
admin/app/api/service/order/settled/AdvanceSettledService.php
@@ -111,9 +111,9 @@
            // 设置默认配送方式
            if (!isset($this->params['supplier'])) {
                $this->orderData['delivery'] = $supplier['productList'][0]['is_virtual'] == 1 ? 30 : $this->orderData['delivery'];
                $this->orderData['delivery'] = $supplier['productList'][0]['is_virtual'] == 1 || $supplier['productList'][0]['is_virtual'] == 3 ? 30 : $this->orderData['delivery'];
            } else {
                if ($supplier['productList'][0]['is_virtual'] == 1) {
                if ($supplier['productList'][0]['is_virtual'] == 1 || $supplier['productList'][0]['is_virtual'] == 3) {
                    $this->orderData['delivery'] = 30;
                } else {
                    $this->orderData['delivery'] = $this->params['supplier'][$supplier['shop_supplier_id']]['delivery'];
admin/app/api/service/order/settled/BranchActivitySettledService.php
@@ -9,7 +9,7 @@
use app\common\enum\order\OrderSourceEnum;
use app\common\enum\order\OrderTypeEnum;
use app\common\model\settings\Setting as SettingModel;
use app\api\service\points\PointsDeductService;
use app\api\service\points\ConsumptionDeductService;
use app\api\model\store\Store as StoreModel;
use app\api\service\user\UserService;
use app\common\enum\settings\DeliveryTypeEnum;
@@ -131,9 +131,9 @@
                    $delivery = $deliveryType[0];
                }
                
                $this->orderData['delivery'] = $supplier['productList'][0]['is_virtual'] == 1 || $supplier['productList'][0]['is_virtual'] == 2 ? 30 : $delivery;
                $this->orderData['delivery'] = $supplier['productList'][0]['is_virtual'] == 1 || $supplier['productList'][0]['is_virtual'] == 2 || $supplier['productList'][0]['is_virtual'] == 3 ? 30 : $delivery;
            }else{
                if($supplier['productList'][0]['is_virtual'] == 1 || $supplier['productList'][0]['is_virtual'] == 2){
                if($supplier['productList'][0]['is_virtual'] == 1 || $supplier['productList'][0]['is_virtual'] == 2 || $supplier['productList'][0]['is_virtual'] == 3){
                    $this->orderData['delivery'] = 30;
                }else {
                    $this->orderData['delivery'] = $this->params['supplier'][$supplier['shop_supplier_id']]['delivery'];
@@ -198,6 +198,7 @@
            'points_money' => $totalPointsMoney,
            'points_num' => $totalPoints,
            'is_real_use_points' => $this->params['is_use_points'],
            'is_real_use_consumption' => $this->params['is_use_consumption'],
            'product_reduce_money' => $totalProductReduce,
            'verify_data' => $verify_data,
            'booking_data' => $booking_data,
@@ -233,6 +234,10 @@
            'is_allow_points' => true,
            // 是否使用积分抵扣
            'is_use_points' => $this->params['is_use_points'],
            // 是否允许使用消费抵扣
            'is_allow_consumption' => true,
            // 是否使用消费券抵扣
            'is_use_consumption' => $this->params['is_use_consumption'],
            // 是否使用计次卡
            'counting_id' => isset($this->params['counting_id']) ? $this->params['counting_id'] : '',
            // 支付方式
@@ -369,7 +374,7 @@
            }
        }
        if(!empty($productList) && $productList[0]['is_virtual'] == 1){
        if(!empty($productList) && ($productList[0]['is_virtual'] == 1 || $productList[0]['is_virtual'] == 3)){
            //虚拟商品核销 by yj
            $verify_data = [
                'is_verify' => $productList[0]['is_verify'] && empty($productList[0]['virtual_auto']) ? 1 : 0, //必须是手动发货并且支持核销
@@ -412,6 +417,8 @@
            'extract_store' => [],
            // 是否允许使用积分抵扣
            'is_allow_points' => false,
            // 是否允许使用消费券抵扣
            'is_allow_consumption' => false,
            // 是否使用积分抵扣
            'is_use_points' => $this->params['is_use_points'],
            // 支付方式
@@ -563,6 +570,10 @@
            if ($commomOrder['is_allow_points'] && $commomOrder['is_real_use_points'] && $commomOrder['points_num'] > 0) {
                $describe = "用户消费:{$this->model['order_no']}";
                $this->user->setIncPoints(-$commomOrder['points_num'], $describe,0,true,$status);
            }
            if ($commomOrder['is_allow_consumption'] && $commomOrder['is_real_use_consumption'] && $commomOrder['consumption_num'] > 0) {
                $describe = "用户消费:{$this->model['order_no']}";
                $this->user->setIncConsumption(-$commomOrder['consumptions_num'], $describe,0,true,$status);
            }
        }
        return $status;
@@ -822,7 +833,7 @@
            return false;
        }
        // 计算订单商品实际抵扣的积分数量和金额
        $ProductDeduct = new PointsDeductService($productList);
        $ProductDeduct = new ConsumptionDeductService($productList);
        $ProductDeduct->setProductPoints($maxPointsNumCount, $actualPointsNum);
        // 积分抵扣总金额
        $orderPointsMoney = helper::getArrayColumnSum($productList, 'points_money');
admin/app/api/service/order/settled/MasterOrderSettledService.php
@@ -31,7 +31,9 @@
    public function validateProductList()
    {
        $newcomerNum =(new OrderModel())
            ->where('user_id', $this->user['user_id'])
            ->where('is_newcomer', 1)->count();
        foreach ($this->supplierData as $supplier) {
            foreach ($supplier['productList'] as $product) {
                // 判断商品是否下架
@@ -48,6 +50,10 @@
                    $this->error = "很抱歉,您已购买过新人专区商品,不能购买新人专区商品";
                    return false;
                }
                if ($this->user['purchase_count'] <= 0 && $product['is_repurchase'] == 1 ) {
                    $this->error = "很抱歉,还不是会员,不能购买复购专区商品,请到先到vip专区购买";
                    return false;
                }
                // 判断商品库存
                if ($product['total_num'] > $product['product_sku']['stock_num']) {
                    $this->error = "很抱歉,商品 [{$product['product_name']}] 库存不足";
admin/app/api/service/order/settled/OrderSettledService.php
@@ -7,11 +7,11 @@
use app\api\model\order\OrderAddress as OrderAddress;
use app\api\model\plus\coupon\UserCoupon as UserCouponModel;
use app\api\model\product\Category;
use app\api\service\consumption\ConsumptionDeductService;
use app\common\enum\order\OrderPayTypeEnum;
use app\common\enum\order\OrderSourceEnum;
use app\common\enum\order\OrderTypeEnum;
use app\common\model\settings\Setting as SettingModel;
use app\api\service\points\PointsDeductService;
use app\api\service\coupon\ProductDeductService;
use app\common\model\store\Store as StoreModel;
use app\api\service\user\UserService;
@@ -54,6 +54,7 @@
        'is_user_grade' => true,     // 会员等级折扣
        'is_agent' => true,     // 商品是否开启分销,最终还是支付成功后判断分销活动是否开启
        'is_reduce' => true, //是否满减
        'is_use_consumption' => true, // 是否使用消费券抵扣
    ];
    /**
@@ -94,6 +95,8 @@
        $expressPrice = 0;
        $totalPointsMoney = 0;
        $totalPoints = 0;
        $totalConsumptionMoney = 0;
        $totalConsumption = 0;
        $totalProductReduce = 0;
        $this->commonOrderData = $this->getCommonOrderData();
        // 供应商
@@ -141,6 +144,10 @@
            $this->setOrderPoints($supplier['productList']);
            $totalPointsMoney += $this->orderData['points_money'];
            $totalPoints += $this->orderData['points_num'];
            // 计算可用消费券抵扣
            $this->setOrderConsumption($supplier['productList']);
            $totalConsumptionMoney += $this->orderData['consumption_money'];
            $totalConsumption += $this->orderData['consumption_num'];
            // 计算订单商品的实际付款金额
            $this->setOrderProductPayPrice($supplier['productList']);
@@ -158,9 +165,9 @@
                    $delivery = $deliveryType[0];
                }
                
                $this->orderData['delivery'] = $supplier['productList'][0]['is_virtual'] == 1 || $supplier['productList'][0]['is_virtual'] == 2 ?30:$delivery;
                $this->orderData['delivery'] = $supplier['productList'][0]['is_virtual'] == 1 || $supplier['productList'][0]['is_virtual'] == 2||$supplier['productList'][0]['is_virtual'] == 3 ?30:$delivery;
            }else{
                if($supplier['productList'][0]['is_virtual'] == 1 || $supplier['productList'][0]['is_virtual'] == 2){
                if($supplier['productList'][0]['is_virtual'] == 1 || $supplier['productList'][0]['is_virtual'] == 2||$supplier['productList'][0]['is_virtual'] == 3){
                    $this->orderData['delivery'] = 30;
                }else {
                    $this->orderData['delivery'] = $this->params['supplier'][$supplier['shop_supplier_id']]['delivery'];
@@ -207,6 +214,8 @@
        $orderPayPrice = $this->setOrderFinalPrice();
        // 计算订单积分赠送数量
        $this->setOrderPointsBonus();
        // 计算订单消费券赠送数量
        $this->setOrderConsumptionBonus();
        //订单数据
        $this->commonOrderData = array_merge([
            'order_total_num' => $orderTotalNum,        // 商品总数量
@@ -217,7 +226,10 @@
            'coupon_money_sys' => 0,
            'points_money' => $totalPointsMoney,
            'points_num' => $totalPoints,
            'consumption_money' => $totalConsumptionMoney,
            'consumption_num' => $totalConsumption,
            'is_real_use_points' => $this->params['is_use_points'],
            'is_real_use_consumption' => $this->params['is_use_consumption'],
            'product_reduce_money' => $totalProductReduce,
            'verify_data' => $verify_data,
            'last_extract' => UserService::getLastExtract($this->user['user_id']),
@@ -247,6 +259,10 @@
            'is_allow_points' => true,
            // 是否使用积分抵扣
            'is_use_points' => $this->params['is_use_points'],
            // 是否使用消费券抵扣
            'is_use_consumption' => $this->params['is_use_consumption'],
            // 是否允许使用消费券抵扣
            'is_allow_consumption' => true,
            // 支付方式
            'pay_type' => isset($this->params['pay_type']) ? $this->params['pay_type'] : OrderPayTypeEnum::WECHAT,
            'pay_source' => isset($this->params['pay_source']) ? $this->params['pay_source'] : '',
@@ -395,6 +411,10 @@
            if ($this->orderData['is_allow_points'] && $this->commonOrderData['is_use_points'] && !$this->settledRule['force_points']) {
                $value = helper::bcsub($value, $product['points_money']);
            }
            // 减去积分抵扣金额
            if ($this->orderData['is_allow_consumption'] && $this->commonOrderData['is_use_consumption'] && !$this->settledRule['force_points']) {
                $value = helper::bcsub($value, $product['consumption_money']);
            }
            // 减去满减金额
            if($this->settledRule['is_reduce'] && $this->orderData['reduce']){
                $value = helper::bcsub($value, $product['fullreduce_money']);
@@ -428,7 +448,7 @@
            }
        }
        if(!empty($productList) && $productList[0]['is_virtual'] == 1){
        if(!empty($productList) && ($productList[0]['is_virtual'] == 1 || $productList[0]['is_virtual'] == 3)){
            //虚拟商品核销 by yj
            $verify_data = [
                'is_verify' => $productList[0]['is_verify'] && empty($productList[0]['virtual_auto']) ? 1 : 0, //必须是手动发货并且支持核销
@@ -597,6 +617,11 @@
                $describe = "用户消费:{$this->model['order_no']}";
                $this->user->setIncPoints(-$commomOrder['points_num'], $describe);
            }
            // 积分抵扣情况下扣除用户积分
            if ($commomOrder['is_allow_consumption'] && $commomOrder['is_real_use_consumption'] && $commomOrder['consumption_num'] > 0) {
                $describe = "用户消费:{$this->model['order_no']}";
                $this->user->setIncConsumption(-$commomOrder['consumption_num'], $describe);
            }
        }
        return $status;
    }
@@ -619,6 +644,8 @@
            'coupon_money_sys'=>$supplier['orderData']['coupon_money_sys'],
            'points_money' => $commomOrder['is_real_use_points'] == 1?abs($supplier['orderData']['points_money']):0,
            'points_num' => $commomOrder['is_real_use_points'] == 1?$supplier['orderData']['points_num']:0,
            'consumption_money' => $commomOrder['is_real_use_consumption'] == 1?abs($supplier['orderData']['consumption_money']):0,
            'consumption_num' => $commomOrder['is_real_use_consumption'] == 1?$supplier['orderData']['consumption_num']:0,
            'pay_price' => $order['order_pay_price'],
            'delivery_type' => $supplier['orderData']['delivery'],
            'pay_type' => $commomOrder['pay_type'],
@@ -626,6 +653,7 @@
            'buyer_remark' => $this->params['supplier'][$supplier['shop_supplier_id']]['remark'],
            'order_source' => $this->orderSource['source'],
            'points_bonus' => $supplier['orderData']['points_bonus'],
            'consumption_bonus' => $supplier['orderData']['consumption_bonus'],
            'is_agent' => $this->settledRule['is_agent']? 1:0,
            'shop_supplier_id' => ($supplier['productList'][0]['is_newcomer'] == 0||$supplier['productList'][0]['belonging_shop_supplier_id'] == 0)?$supplier['shop_supplier_id']:$supplier['productList'][0]['belonging_shop_supplier_id'],
            'supplier_money' => $order['supplier_money'],
@@ -745,6 +773,9 @@
                'points_money' => isset($product['points_money']) && $commomOrder['is_real_use_points']?abs($product['points_money']):0,
                'points_num' => isset($product['points_num']) && $commomOrder['is_real_use_points']?$product['points_num']:0,
                'points_bonus' => isset($product['points_bonus'])?$product['points_bonus']:0,
                'consumption_money' => isset($product['consumption_money']) && $commomOrder['is_real_use_consumption']?abs($product['consumption_money']):0,
                'consumption_num' => isset($product['consumption_num']) && $commomOrder['is_real_use_consumption']?$product['consumption_num']:0,
                'consumption_bonus' => isset($product['consumption_bonus'])?$product['consumption_bonus']:0,
                'total_num' => $product['total_num'],
                'total_price' => $product['total_price'],
                'total_pay_price' => $product['total_pay_price'],
@@ -758,6 +789,7 @@
                'third_money' => $product['third_money'],
                'fullreduce_money' => isset($product['fullreduce_money'])?$product['fullreduce_money']:0,
                'virtual_content' => $product['virtual_content'],
                'service_content' => $product['service_content'],
                'is_alone_team' => $product['is_alone_team'],
                'alone_team_equity' => $product['alone_team_equity'],
                'product_reduce_money' => $product['product_reduce_money'],
@@ -765,6 +797,7 @@
                'verify_type' => $product['verify_type'],
                'verify_day' => $product['verify_day'],
                'is_newcomer' => $product['is_newcomer'],
                'is_vip' => $product['is_vip'],
                'is_repurchase' => $product['is_repurchase'],
                'is_viewpoint_money' => $product['is_viewpoint_money'],
                'viewpoint_money' => $product['viewpoint_money'],
@@ -834,7 +867,7 @@
            return false;
        }
        // 计算订单商品实际抵扣的积分数量和金额
        $ProductDeduct = new PointsDeductService($productList);
        $ProductDeduct = new ConsumptionDeductService($productList);
        $ProductDeduct->setProductPoints($maxPointsNumCount, $actualPointsNum);
        // 积分抵扣总金额
        $orderPointsMoney = helper::getArrayColumnSum($productList, 'points_money');
@@ -910,6 +943,111 @@
    }
    /**
     * 计算订单可用消费券抵扣
     */
    private function setOrderConsumption($productList)
    {
        $this->orderData['consumption_money'] = 0;
        // 消费券抵扣总数量
        $this->orderData['consumption_num'] = 0;
        // 允许消费券抵扣
        $this->orderData['is_allow_consumption'] = false;
        // 消费券设置
        $setting = SettingModel::getItem('consumption');
        // 条件:后台开启下单使用消费券抵扣
        if (!$setting['is_shopping_discount']) {
            return false;
        }
        // 条件:订单金额满足[?]元
        if (helper::bccomp($setting['discount']['full_order_price'], $this->orderData['order_total_price']) === 1) {
            return false;
        }
        // 计算订单商品最多可抵扣的消费券数量
        $this->setOrderConsumptionMaxPointsNum($productList);
        // 订单最多可抵扣的消费券总数量
        $maxConsumptionNumCount = helper::getArrayColumnSum($productList, 'max_consumption_num');
        // 实际可抵扣的消费券数量
        $actualConsumptionNum = min($maxConsumptionNumCount, $this->user['consumer_coupon']);
        if ($actualConsumptionNum < 1) {
            $this->orderData['consumption_money'] = 0;
            // 消费券抵扣总数量
            $this->orderData['consumption_num'] = 0;
            // 允许消费券抵扣
            $this->orderData['is_allow_consumption'] = true;
            return false;
        }
        // 计算订单商品实际抵扣的消费券数量和金额
        $ProductDeduct = new ConsumptionDeductService($productList);
        $ProductDeduct->setProductConsumption($maxConsumptionNumCount, $actualConsumptionNum);
        // 消费券抵扣总金额
        $orderConsumptionMoney = helper::getArrayColumnSum($productList, 'consumption_money');
        $this->orderData['consumption_money'] = helper::number2($orderConsumptionMoney);
        // 消费券抵扣总数量
        $this->orderData['consumption_num'] = $actualConsumptionNum;
        // 允许消费券抵扣
        $this->orderData['is_allow_consumption'] = true;
        return true;
    }
    /**
     * 计算订单商品最多可抵扣的消费券数量
     */
    private function setOrderConsumptionMaxPointsNum($productList)
    {
        // 消费券设置
        $setting = SettingModel::getItem('consumption');
        foreach ($productList as &$product) {
                // 商品不允许消费券抵扣
                if (!$product['is_consumption_discount']||$product['is_repurchase']||$product['is_newcomer']||$product['is_vip']) continue;
                // 消费券抵扣比例
                $deductionRatio = helper::bcdiv($setting['discount']['max_money_ratio'], 100);
                // 最多可抵扣的金额
                $maxPointsMoney = helper::bcmul($product['total_price'], $deductionRatio);
                // 最多可抵扣的消费券数量
                $product['max_consumption_num'] = helper::bcdiv($maxPointsMoney, $setting['discount']['discount_ratio'], 0);
                // 如果超过商品最大抵扣数量
                if($product['max_consumption_discount'] > 0 && $product['max_consumption_num'] > $product['max_consumption_discount'] * $product['total_num']){
                    $product['max_consumption_num'] = $product['max_consumption_discount'] * $product['total_num'];
                }
        }
        return true;
    }
    /**
     * 计算订单消费券赠送数量
     */
    private function setOrderConsumptionBonus()
    {
        // 初始化商品消费券赠送数量
        foreach ($this->supplierData as &$supplier){
            foreach ($supplier['productList'] as $product){
                $product['consumption_bonus'] = 0;
            }
            $supplier['orderData']['consumption_bonus'] = 0;
        }
        // 消费券设置
        $setting = SettingModel::getItem('consumption');
        // 条件:后台开启开启购物送消费券
        if (!$setting['is_shopping_gift']) {
            return false;
        }
        // 设置商品消费券赠送数量
        foreach ($this->supplierData as &$supplier) {
            foreach ($supplier['productList'] as &$product) {
                // 消费券赠送比例
                $ratio = $setting['gift_ratio'] / 100;
                // 计算抵扣的消费券数量
                $product['consumption_bonus'] = !$product['is_consumption_gift'] ? 0 : helper::bcmul($product['total_pay_price'], $ratio, 0);
            }
            //  订单消费券赠送数量
            $supplier['orderData']['consumption_bonus'] = helper::getArrayColumnSum($supplier['productList'], 'consumption_bonus');
        }
        return true;
    }
    /**
     * 设置订单商品会员折扣价
     */
    private function setOrderGrade($productList)
admin/app/common/enum/settings/SettingEnum.php
@@ -81,6 +81,8 @@
    const DELIVER = 'deliver';
    // 外卖设置
    const TAKEOUT = 'takeout';
    // 消费券设置
    const CONSUMTION = 'consumption';
    /**
     * 获取订单类型值
@@ -232,6 +234,10 @@
                'value' => self::TAKEOUT,
                'describe' => '外卖设置',
            ],
            self::CONSUMTION => [
                'value' => self::CONSUMTION,
                'describe' => '消费券设置',
            ],
        ];
    }
admin/app/common/model/plus/shareholder/Apply.php
@@ -151,9 +151,9 @@
        if ($config['become'] == '110'){
            $subordinateUserId=(new TeamRefereeModel())->where(['heads_id'=>$userId])->column('user_id');
            $vipNum=(new \app\common\model\user\User)->getRefereeGradeCount($subordinateUserId,$config['referee_grade_ids']);
            $supplierNum=(new \app\common\model\supplier\User)->getSubordinateNum($subordinateUserId);
            $supplierNum=(new \app\common\model\supplier\Supplier())->getSubordinateNum($subordinateUserId);
            $user=(new \app\common\model\user\User)->where(['user_id'=>$userId,'is_delete'=>0])->find();
            if ($vipNum >= $config['total_vip_num'] && $supplierNum >= $config['totalsh_down']&&$user['purchase_count']>=$config['purchase_count']){
            if ($vipNum >= $config['totalvip_down'] && $supplierNum >= $config['totalsh_down']&&$user['purchase_count']>=$config['purchase_count']){
                $becomeShareholder = true;
            }
        }
admin/app/common/model/release/Capital.php
New file
@@ -0,0 +1,26 @@
<?php
namespace app\common\model\plus\release;
use app\common\model\BaseModel;
/**
 * 资金明细模型
 */
class Capital extends BaseModel
{
    protected $name = 'release_capital';
    protected $pk = 'id';
    /**
     * 分销商资金明细
     * @param $data
     */
    public static function add($data)
    {
        $model = new static;
        $model->save(array_merge([
            'app_id' => $model::$app_id
        ], $data));
    }
}
admin/app/common/model/release/Cart.php
New file
@@ -0,0 +1,231 @@
<?php
namespace app\api\model\plus\repair;
use app\api\model\order\Order as OrderModel;
use think\facade\Cache;
use app\api\model\plus\repair\Project as ProjectModel;
use app\common\model\supplier\Supplier as SupplierModel;
use app\common\library\helper;
use app\common\model\plus\repair\Cart as CartModel;
/**
 * 购物车管理
 */
class Cart extends CartModel
{
    // 错误信息
    public $error = '';
    /**
     * 购物车列表 (含商品信息)
     */
    public function getList($user, $cart_ids = [])
    {
        // 获取购物车商品列表
        return $this->getOrderProjectList($user, $cart_ids);
    }
    /**
     * 获取购物车列表
     */
    public function getCartList($cartIds = null)
    {
        if (empty($cartIds)) return static::$cart;
        $cartList = [];
        $indexArr = (strpos($cartIds, ',') !== false) ? explode(',', $cartIds) : [$cartIds];
        foreach ($indexArr as $index) {
            isset(static::$cart[$index]) && $cartList[$index] = static::$cart[$index];
        }
        return $cartList;
    }
    /**
     * 获取购物车中的商品列表
     */
    public function getOrderProjectList($user, $cart_ids = [])
    {
        // 购物车列表
        $projectList = [];
        // 获取购物车列表
        $model = $this;
        if ($cart_ids) {
            $model = $model->where('cart_id', 'in', explode(',', $cart_ids));
        }
        $cartList = $model->where('user_id', '=', $user['user_id'])->select();
        if (empty($cartList)) {
            $this->setError('当前购物车没有项目');
            return $projectList;
        }
        // 购物车中所有商品id集
        $projectIds = array_unique(helper::getArrayColumn($cartList, 'project_id'));
        // 获取并格式化商品数据
        $sourceData = (new ProjectModel)->getListByIds($projectIds);
        $sourceData = helper::arrayColumn2Key($sourceData, 'project_id');
        // 供应商信息
        $supplierData = [];
        // 格式化购物车数据列表
        foreach ($cartList as $key => $item) {
            // 判断商品不存在则自动删除
            if (!isset($sourceData[$item['project_id']])) {
                $this->delete($key);
                continue;
            }
            // 项目信息
            $project = clone $sourceData[$item['project_id']];
            // 判断商品是否已删除
            if (empty($project)) {
                $this->delete($key);
                continue;
            }
            // 购买数量
            $project['total_num'] = $item['total_num'];
            // 总价
            $project['total_price'] = bcmul($project['price'], $item['total_num'], 2);
            // 总佣金
            $project['total_money'] = bcmul($project['money'], $item['total_num'], 2);
            // 供应商
            $project['shop_supplier_id'] = $item['shop_supplier_id'];
            //购物车id
            $project['cart_id'] = $item['cart_id'];
            $projectList[] = $project;
        }
        $supplierIds = array_unique(helper::getArrayColumn($projectList, 'shop_supplier_id'));
        foreach($supplierIds as $supplierId){
            $supplierData[] = [
                'shop_supplier_id' => $supplierId,
                'supplier' => SupplierModel::detail($supplierId),
                'projectList' => $this->getProjectBySupplier($supplierId, $projectList)
            ];
        }
        return $supplierData;
    }
    private function getProjectBySupplier($supplierId, $projectList)
    {
        $result = [];
        foreach ($projectList as $project){
            if($project['shop_supplier_id'] == $supplierId){
                array_push($result, $project);
            }
        }
        return $result;
    }
    /**
     * 加入购物车
     */
    public function add($user, $projectId, $projectNum)
    {
        $model = $this;
        // 获取信息
        $project = ProjectModel::detail($projectId);
        // 获取商品购物车信息
        $cartDetail = $model->where('user_id', '=', $user['user_id'])
            ->where('project_id', '=', $projectId)
            ->find();
        // 验证能否加入
        if (!$project_price = $this->checkProject($project)) {
            return false;
        }
        // 记录到购物车列表
        if ($cartDetail) {
            return $cartDetail->save(['total_num' => $cartDetail['total_num'] + $projectNum]);
        } else {
            return $this->save([
                'user_id' => $user['user_id'],
                'project_id' => $projectId,
                'total_num' => $projectNum,
                'join_price' => $project_price,
                'shop_supplier_id' => $project['shop_supplier_id'],
                'app_id' => self::$app_id,
            ]);
        }
    }
    /**
     * 验证是否可以下单
     */
    private function checkProject($project)
    {
        // 判断项目
        if (!$project) {
            $this->setError('很抱歉,信息不存在');
            return false;
        }
        return $project['price'];
    }
    /**
     * 减少购物车中某商品数量
     */
    public function sub($user, $projectId)
    {
        $cartDetail = $this->where('user_id', '=', $user['user_id'])
            ->where('project_id', '=', $projectId)
            ->find();
        if ($cartDetail['total_num'] <= 1) {
            return $cartDetail->delete();
        } else {
            $cartDetail->save(['total_num' => $cartDetail['total_num'] - 1]);
        }
    }
    /**
     * 删除购物车中指定商品
     * @param string $cartIds (支持字符串ID集)
     */
    public function setDelete($user, $cart_id)
    {
        return $this->where('user_id', '=', $user['user_id'])->where('cart_id', 'in', explode(',', $cart_id))->delete();
    }
    /**
     * 获取当前用户购物车商品总数量(含件数)
     */
    public function getTotalNum($user)
    {
        $num = $this->where('user_id', '=', $user['user_id'])->sum('total_num');
        return $num ? $num : 0;
    }
    /**
     * 获取当前用户购物车商品总数量(不含件数)
     */
    public function getProductNum($user)
    {
        return $this->where('user_id', '=', $user['user_id'])->count();
    }
    /**
     * 清空当前用户购物车
     */
    public function clearAll($user, $cartIds)
    {
        return $this->where('user_id', '=', $user['user_id'])
            ->where('cart_id', 'in', explode(',', $cartIds))
            ->delete();
    }
    /**
     * 设置错误信息
     */
    private function setError($error)
    {
        empty($this->error) && $this->error = $error;
    }
    /**
     * 获取错误信息
     */
    public function getError()
    {
        return $this->error;
    }
}
admin/app/common/model/release/Cash.php
New file
@@ -0,0 +1,64 @@
<?php
namespace app\common\model\plus\release;
use app\common\model\BaseModel;
/**
 * 分销商提现明细模型
 */
class Cash extends BaseModel
{
    protected $name = 'release_cash';
    protected $pk = 'id';
    /**
     * 打款方式
     * @var array
     */
    public $payType = [
        10 => '微信',
        20 => '支付宝',
        30 => '银行卡',
    ];
    /**
     * 申请状态
     * @var array
     */
    public $applyStatus = [
        10 => '待审核',
        20 => '审核通过',
        30 => '驳回',
        40 => '已打款',
    ];
    /**
     * 关联用户表
     * @return \think\model\relation\BelongsTo
     */
    public function user()
    {
        return $this->belongsTo('SupplyUser');
    }
    /**
     * 提现详情
     */
    public static function detail($id)
    {
        return (new static())->find($id);
    }
    /**
     * 审核状态
     * @param $value
     * @return array
     */
    public function getApplyStatusAttr($value)
    {
        $method = [10 => '待审核', 20 => '审核通过', 30 => '驳回', 40 => '已打款'];
        return ['text' => $method[$value], 'value' => $value];
    }
}
admin/app/common/model/release/DemandApply.php
New file
@@ -0,0 +1,82 @@
<?php
namespace app\common\model\plus\release;
use app\common\model\BaseModel;
use app\common\model\user\User as UserModel;
/**
 * 分销商申请模型
 */
class DemandApply extends BaseModel
{
    protected $name = 'release_demand_apply';
    protected $pk = 'apply_id';
    /**
     * 申请状态
     * @var array
     */
    public $applyStatus = [
        10 => '待审核',
        20 => '审核通过',
        30 => '驳回',
    ];
    /**
     * 申请时间
     * @param $value
     * @return false|string
     */
    public function getApplyTimeAttr($value)
    {
        return date('Y-m-d H:i:s', $value);
    }
    /**
     * 审核时间
     * @param $value
     * @return false|int|string
     */
    public function getAuditTimeAttr($value)
    {
        return $value > 0 ? date('Y-m-d H:i:s', $value) : 0;
    }
    /**
     * 销商申请记录详情
     * @param $where
     * @return array|\think\Model|null
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public static function detail($where)
    {
        $filter = is_array($where) ? $where : ['apply_id' => $where];
        return (new static())->where($filter)->find();
    }
    /**
     * 审核状态
     * @param $value
     * @return array
     */
    public function getApplyStatusAttr($value)
    {
        $method = [10 => '待审核', 20 => '审核通过', '30' => '驳回'];
        return ['text' => $method[$value], 'value' => $value];
    }
    /**
     * 审核方式
     * @param $value
     * @return array
     */
    public function getApplyTypeAttr($value)
    {
        $method = [10 => '后台审核', 20 => '无需审核'];
        return ['text' => $method[$value], 'value' => $value];
    }
}
admin/app/common/model/release/DemandProject.php
New file
@@ -0,0 +1,157 @@
<?php
namespace app\api\model\plus\release;
use app\common\model\plus\release\Project as ProjectModel;
use app\common\model\plus\release\ReleaseProjectImage as ReleaseProjectImageModel;
/**
 * 模型
 */
class DemandProject extends ProjectModel
{
    /**
     * 获取提现明细
     */
    public function getList($user_id, $postdata)
    {
        $model = $this;
        if(!empty($postdata["keyword"])){
            $model = $model->where('name', 'like', '%'.$postdata["keyword"].'%');
        }
        return $model->where('is_delete', '=', 0)
            ->where('project_type', '=', 0)
            ->where('user_id', '=', $user_id)
            ->order(['create_time' => 'desc'])
            ->paginate($postdata);
    }
    /**
     * 新增记录
     */
    public function add($postdata,$demand)
    {
        $data = json_decode($postdata["formData"],true);
        if (empty($data['name'])) {
                $this->error = '请输入标题';
                return false;
         }
        if (empty($data['category_id'])) {
                $this->error = '请选择分类';
                return false;
         }
        if (empty($data['price'])) {
                $this->error = '请输入您的预算';
                return false;
        }
       if (empty($data['content'])) {
                $this->error = '请输入您的详细需求';
                return false;
        }
        $save_data =[
            'user_id'=>$demand["user_id"],
            'name'=>$data["name"],
            'category_id'=>$data["category_id"],
            'price'=>$data["price"],
            'content'=>$data["content"],
            'detail'=>$data["detail"],
            'show_phone'=>$data["show_phone"],
            'is_show'=>$data["is_show"],
            'app_id'=>self::$app_id,
        ];
        if(!empty($data["finish_time"]) && $data["finish_time"] != '请选择日期'){
            $save_data["finish_time"] = strtotime($data["finish_time"]);
        }else{
            $save_data["finish_time"] = '';
        }
          return $this->transaction(function () use ($data, $save_data) {
            // 记录内容
            $this->save($save_data);
            // 记录图片
            $this->saveAllImages($this['project_id'],$data);
            return $this['project_id'];
        });
    }
    /**
     * 更新记录
     */
    public function edit($postdata)
    {
        $data = json_decode($postdata["formData"],true);
        if (empty($data['name'])) {
                $this->error = '请输入标题';
                return false;
         }
        if (empty($data['category_id'])) {
                $this->error = '请选择分类';
                return false;
         }
        if (empty($data['price'])) {
                $this->error = '请输入您的预算';
                return false;
        }
       if (empty($data['content'])) {
                $this->error = '请输入您的详细需求';
                return false;
        }
         $save_data =[
            'name'=>$data["name"],
            'category_id'=>$data["category_id"],
            'price'=>$data["price"],
            'content'=>$data["content"],
            'detail'=>$data["detail"],
            'show_phone'=>$data["show_phone"],
            'is_show'=>$data["is_show"],
            'status'=>0,
        ];
        if(!empty($data["finish_time"]) && $data["finish_time"] != '请选择日期'){
            $save_data["finish_time"] = strtotime($data["finish_time"]);
        }else{
            $save_data["finish_time"] = '';
        }
        return $this->transaction(function () use ($data, $save_data) {
            // 记录内容
            $this->where("project_id","=",$data["project_id"])->save($save_data);
            // 记录图片
            $this->saveAllImages($data["project_id"],$data);
            return true;
        });
    }
     /**
     * 记录图片
     */
    private function saveAllImages($id,$formData)
    {
        (new ReleaseProjectImageModel())->where("project_id","=",$id)->delete();
        // 生成图片数据
        if(!empty($formData['image_list'])){
            $imageData = [];
            foreach ($formData['image_list'] as $imageId) {
                $imageData[] = [
                    'project_id' => $id,
                    'image_id' => !empty($imageId['image_id']) ? $imageId['image_id'] : $imageId['file_id'],
                    'app_id' => self::$app_id
                ];
            }
            $model = new ReleaseProjectImageModel;
            return !empty($imageData) && $model->saveAll($imageData);
        }
        return true;
    }
    /**
     * 软删除
     */
    public function setDelete($id)
    {
        return $this->where("project_id","=",$id)->save(['is_delete' => 1]);
    }
}
admin/app/common/model/release/DemandUser.php
New file
@@ -0,0 +1,67 @@
<?php
namespace app\common\model\plus\release;
use app\common\model\BaseModel;
/**
 * 用户模型
 */
class DemandUser extends BaseModel
{
    protected $name = 'release_demand_user';
    protected $pk = 'user_id';
    /**
     * 关联会员记录表
     * @return \think\model\relation\BelongsTo
     */
    public function user()
    {
        return $this->belongsTo('app\\common\\model\\user\\User');
    }
    /**
     * 详情
     */
    public static function detail($user_id, $with = ['user'])
    {
        return (new static())->with($with)->find($user_id);
    }
    /**
     * 详情
     */
    public static function getAll()
    {
        return (new static())->where("is_delete","=",0)->select();
    }
    /**
     * 是否为需求方
     */
    public static function isDemandUser($user_id)
    {
        $demand = self::detail($user_id);
        return !!$demand && !$demand['is_delete'];
    }
    /**
     * 新增记录
     * @param $user_id
     * @param $data
     * @return bool
     */
    public static function add($user_id, $data)
    {
        $model = static::detail($user_id) ?: new static;
         $model->save(array_merge([
            'user_id' => $user_id,
            'is_delete' => 0,
            'app_id' => $model::$app_id,
        ], $data));
        return true;
    }
}
admin/app/common/model/release/Order.php
New file
@@ -0,0 +1,109 @@
<?php
namespace app\common\model\plus\release;
use app\common\enum\order\OrderPayTypeEnum;
use app\common\model\BaseModel;
/**
 * 订单模型
 */
class Order extends BaseModel
{
    protected $name = 'release_order';
    protected $pk = 'id';
    /**
     * 追加字段
     * @var string[]
     */
    protected $append = [
        'state_text',
    ];
    /**
     * 需求用户
     * @return \think\model\relation\BelongsTo
     */
    public function demanduser()
    {
        return $this->belongsTo('app\common\model\user\User','demand_user_id','user_id');
    }
     /**
     * 供应用户
     * @return \think\model\relation\BelongsTo
     */
    public function supplyuser()
    {
        return $this->belongsTo('app\common\model\user\User','supply_user_id','user_id');
    }
    /**
     * 关联项目
     * @return \think\model\relation\hasMany
     */
    public function project()
    {
        return $this->belongsTo('app\common\model\plus\release\Project','project_id','project_id');
    }
    /**
     * 订单状态文字描述
     * @param $value
     * @param $data
     * @return string
     */
    public function getStateTextAttr($value, $data)
    {
        if($data['order_status'] == 20){
            return '已取消';
        }
        // 订单状态
        if ($data['pay_status'] == 10 && $data['pay_type'] == 40) {
            return '待确认支付';
        }else if ($data['pay_status'] == 10 && $data['pay_type'] != 40) {
            return '未付款';
        }else if($data['pay_status'] == 20 && $data['order_status'] == 10){
            return '进行中';
        }else if($data['pay_status'] == 20 && $data['order_status'] == 30){
            return '已完成';
        }
        return "";
    }
    /**
     * 付款状态
     * @param $value
     * @return array
     */
    public function getPayTypeAttr($value)
    {
        if(empty($value)){
            return ['text' => '', 'value' => 0];
        }
        return ['text' => OrderPayTypeEnum::data()[$value]['name'], 'value' => $value];
    }
    /**
     * 详情
     */
    public static function detail($id)
    {
        $model = new static();
        return $model->with(['demanduser','supplyuser',"project"])->find($id);
    }
    /**
     * 详情
     */
    public static function getDetail($order_no)
    {
        $model = new static();
        return $model->with(["project"])->where("order_no",'=',$order_no)->find();
    }
}
admin/app/common/model/release/Project.php
New file
@@ -0,0 +1,70 @@
<?php
namespace app\common\model\plus\release;
use app\common\model\BaseModel;
/**
 * 项目模型
 */
class Project extends BaseModel
{
    protected $name = 'release_project';
    protected $pk = 'project_id';
    /**
     * 关联上传图片表
     */
    public function image()
    {
        return $this->hasMany('app\\common\\model\\plus\\release\\ReleaseProjectImage', 'project_id', 'id')->order(['id' => 'asc']);
    }
    /**
     * 关联分类
     * @return \think\model\relation\BelongsTo
     */
    public function category()
    {
        return $this->belongsTo('app\\common\\model\\plus\\release\\ReleaseCategory','category_id','category_id');
    }
     /**
     * 关联
     * @return \think\model\relation\BelongsTo
     */
    public function user()
    {
        return $this->belongsTo('app\\common\\model\\user\\User','user_id','user_id');
    }
    /**
     * 关联多标签表
     */
    public function tag()
    {
        return $this->hasMany('app\\common\\model\\plus\\release\\Tag', 'tag_id', 'tag_id');
    }
    /**
     * 获取详情
     */
    public static function detail($project_id)
    {
        return (new static())->with(['image'])->find($project_id);
    }
    /**
     * 获取列表记录
     */
    public function getAll()
    {
        return $this->where('is_delete', '=', 0)
            ->field('project_id,name')
            ->order(['sort' => 'asc', 'create_time' => 'asc'])
            ->select();
    }
}
admin/app/common/model/release/ReleaseCategory.php
New file
@@ -0,0 +1,41 @@
<?php
namespace app\common\model\plus\release;
use think\facade\Cache;
use app\common\model\BaseModel;
/**
 * 分类模型
 */
class ReleaseCategory extends BaseModel
{
    protected $pk = 'category_id';
    protected $name = 'release_category';
    /**
     * 详情
     */
    public static function detail($category_id)
    {
        return (new static())->find($category_id);
    }
    /**
     * 所有分类
     */
    public static function getALL()
    {
        $model = new static;
        $data = $model->order(['sort' => 'asc', 'create_time' => 'asc'])->select();
        return $data;
    }
    public function getListByIds($ids)
    {
        return $this->field(['category_id', 'name'])->where('category_id', 'in', $ids)->select();
    }
}
admin/app/common/model/release/ReleaseProjectImage.php
New file
@@ -0,0 +1,33 @@
<?php
namespace app\common\model\plus\release;
use app\common\model\BaseModel;
/**
 * 图片模型
 */
class ReleaseProjectImage extends BaseModel
{
    protected $name = 'release_project_image';
    protected $pk = 'id';
    protected $updateTime = false;
    /**
     * 关联文件库
     */
    public function file()
    {
        return $this->belongsTo('app\\common\\model\\file\\UploadFile', 'image_id', 'file_id')
            ->bind(['file_path', 'file_name', 'file_url']);
    }
    public static function getImage($project_id)
    {
        $model = new static;
        return $model->with(['file'])
            ->where('project_id', '=', $project_id)
            ->select();
    }
}
admin/app/common/model/release/ReleaseProjectTag.php
New file
@@ -0,0 +1,47 @@
<?php
namespace app\common\model\plus\release;
use app\common\model\BaseModel;
/**
 * 图片模型
 */
class ReleaseProjectTag extends BaseModel
{
    protected $name = 'release_project_tag';
    protected $pk = 'id';
    protected $updateTime = false;
    /**
     * 关联
     */
    public function tag()
    {
        return $this->belongsTo('app\\common\\model\\plus\\release\\Tag', 'tag_id', 'tag_id')
            ->bind(['name']);
    }
    public static function getTagId($project_id)
    {
        $model = new static;
        return $model
            ->where('project_id', '=', $project_id)
            ->column("tag_id");
    }
    public static function getTagName($project_id)
    {
        $model = new static;
        return $model->with('tag')
            ->where('project_id', '=', $project_id)
            ->select();
    }
    public static function getTagList($project_id)
    {
        $model = new static;
        return $model->with(['tag'])
            ->where('project_id', '=', $project_id)
            ->select();
    }
}
admin/app/common/model/release/Setting.php
New file
@@ -0,0 +1,398 @@
<?php
namespace app\common\model\plus\release;
use app\common\model\BaseModel;
use think\facade\Cache;
/**
 * 设置模型
 */
class Setting extends BaseModel
{
    protected $name = 'release_setting';
    protected $createTime = false;
    /**
     * 转义数组格式
     * @param $value
     * @return mixed
     */
    public function getValuesAttr($value)
    {
        return json_decode($value, true);
    }
    /**
     * 转义成json格式
     * @param $value
     * @return false|string
     */
    public function setValuesAttr($value)
    {
        return json_encode($value);
    }
    /**
     * 获取指定项设置
     * @param $key
     * @param null $app_id
     * @return array|mixed
     */
    public static function getItem($key, $app_id = null)
    {
        $data = static::getAll($app_id);
        return isset($data[$key]) ? $data[$key]['values'] : [];
    }
    /**
     * 获取分销商设置
     */
    public static function getAll($app_id = null)
    {
        $self = new static;
        is_null($app_id) && $app_id = $self::$app_id;
        if (!$data = Cache::get('release_setting_' . $app_id)) {
            $data = array_column($self->select()->toArray(), null, 'key');
            Cache::tag('cache')->set('release_setting_' . $app_id, $data);
        }
        return array_merge_multiple($self->defaultData(), $data);
    }
    /**
     * 获取设置项信息
     */
    public static function detail($key)
    {
        return (new static())->find(compact('key'));
    }
    /**
     * 是否开启功能
     */
    public static function isOpen($app_id = null)
    {
        return static::getItem('basic', $app_id)['is_open'];
    }
    /**
     * 页面名称
     */
    public static function getAgentTitle($app_id = null)
    {
        return static::getItem('words', $app_id)['index']['title']['value'];
    }
    /**
     * 默认配置
     * @return array[]
     */
    public function defaultData()
    {
        return [
            'basic' => [
                'key' => 'basic',
                'describe' => '基础设置',
                'values' => [
                    // 是否开启分销功能
                    'is_open' => '0',   // 参数值:1开启 0关闭
                    // 分销层级
                    'level' => '3', // 参数值:1一级 2二级 3三级
                    // 分销商内购
                    'self_buy' => '0',   // 参数值:1开启 0关闭
                    'commission_type' => '0', // 佣金计算方式 0固定 1循环
                    'loop_num' => 3, // 循环长度
                    'buy_again' => '1' // 重复购买是否参与分销
                ],
            ],
            'condition' => [
                'key' => 'condition',
                'describe' => '分销商条件',
                'values' => [
                    // 成为分销商条件
                    'become' => '10',   // 参数值:10填写申请信息(需后台审核) 20填写申请信息(无需审核) 30单次消费 40累计消费 50购买指定商品
                    // 购买指定商品成为分销商 0关闭 1开启
                    'become__buy_product' => '0',
                    // 购买指定商品的id集
                    'become__buy_product_ids' => [],
                    // 成为下线条件
                    'downline' => '10',  // 参数值:10首次点击分享链接 20首次下单 30首次付款
                    //单次消费金额
                    'one_money' => '0',
                    //累计消费金额
                    'total_money' => '0',
                ]
            ],
            'commission' => [
                'key' => 'commission',
                'describe' => '佣金设置',
                'values' => [
                    // 一级佣金
                    'first_money' => '0',
                    // 一级佣金
                    'second_money' => '0',
                    // 一级佣金
                    'third_money' => '0',
                    'first_loop_money' => [] //循环比例
                ]
            ],
            'settlement' => [
                'key' => 'settlement',
                'describe' => '结算',
                'values' => [
                    // 提现方式
                    'pay_type' => [],   // 参数值:10微信支付 20支付宝支付 30银行卡支付
                    // 微信支付自动打款
                    'wechat_pay_auto' => '0',       // 微信支付自动打款:1开启 0关闭
                    // 最低提现额度
                    'min_money' => '10.00',
                    // 佣金结算天数
                    'settle_days' => '10',
                    // 微信打款方式
                    'wechat_type' => '0',
                    'fee_rate' => '0',
                    'order_rate' => '0',
                    'explain' => ''
                ]
            ],
            'words' => [
                'key' => 'words',
                'describe' => '自定义文字',
                'values' => [
                    'index' => [
                        'title' => [
                            'default' => '分销中心',
                            'value' => '分销中心'
                        ],
                        'words' => [
                            'agent' => [
                                'default' => '分销商',
                                'value' => '分销商'
                            ],
                            'not_agent' => [
                                'default' => '您还不是分销商',
                                'value' => '您还不是分销商'
                            ],
                            'apply_now' => [
                                'default' => '立即加入',
                                'value' => '立即加入'
                            ],
                            'referee' => [
                                'default' => '推荐人',
                                'value' => '推荐人'
                            ],
                            'money' => [
                                'default' => '可提现佣金',
                                'value' => '可提现'
                            ],
                            'freeze_money' => [
                                'default' => '待提现佣金',
                                'value' => '待提现'
                            ],
                            'total_money' => [
                                'default' => '已提现金额',
                                'value' => '已提现金额'
                            ],
                            'cash' => [
                                'default' => '去提现',
                                'value' => '去提现'
                            ],
                            'referee_code' => [
                                'default' => '邀请码',
                                'value' => '邀请码'
                            ],
                        ]
                    ],
                    'apply' => [
                        'title' => [
                            'default' => '申请成为分销商',
                            'value' => '申请成为分销商'
                        ],
                        'words' => [
                            'title' => [
                                'default' => '请填写申请信息',
                                'value' => '请填写申请信息'
                            ],
                            'license' => [
                                'default' => '分销商申请协议',
                                'value' => '分销商申请协议'
                            ],
                            'submit' => [
                                'default' => '申请成为经销商',
                                'value' => '申请成为经销商'
                            ],
                            'wait_audit' => [
                                'default' => '您的申请已受理,正在进行信息核验,请耐心等待。',
                                'value' => '您的申请已受理,正在进行信息核验,请耐心等待。'
                            ],
                            'goto_mall' => [
                                'default' => '去商城逛逛',
                                'value' => '去商城逛逛'
                            ],
                        ]
                    ],
                    'order' => [
                        'title' => [
                            'default' => '分销订单',
                            'value' => '分销订单'
                        ],
                        'words' => [
                            'all' => [
                                'default' => '全部',
                                'value' => '全部'
                            ],
                            'unsettled' => [
                                'default' => '未结算',
                                'value' => '未结算'
                            ],
                            'settled' => [
                                'default' => '已结算',
                                'value' => '已结算'
                            ],
                        ]
                    ],
                    'team' => [
                        'title' => [
                            'default' => '我的团队',
                            'value' => '我的团队'
                        ],
                        'words' => [
                            'total_team' => [
                                'default' => '团队总人数',
                                'value' => '团队总人数'
                            ],
                            'first' => [
                                'default' => '一级团队',
                                'value' => '一级团队'
                            ],
                            'second' => [
                                'default' => '二级团队',
                                'value' => '二级团队'
                            ],
                            'third' => [
                                'default' => '三级团队',
                                'value' => '三级团队'
                            ],
                        ]
                    ],
                    'cash_list' => [
                        'title' => [
                            'default' => '提现明细',
                            'value' => '提现明细'
                        ],
                        'words' => [
                            'all' => [
                                'default' => '全部',
                                'value' => '全部'
                            ],
                            'apply_10' => [
                                'default' => '审核中',
                                'value' => '审核中'
                            ],
                            'apply_20' => [
                                'default' => '审核通过',
                                'value' => '审核通过'
                            ],
                            'apply_40' => [
                                'default' => '已打款',
                                'value' => '已打款'
                            ],
                            'apply_30' => [
                                'default' => '驳回',
                                'value' => '驳回'
                            ],
                        ]
                    ],
                    'cash_apply' => [
                        'title' => [
                            'default' => '申请提现',
                            'value' => '申请提现'
                        ],
                        'words' => [
                            'capital' => [
                                'default' => '可提现佣金',
                                'value' => '可提现佣金'
                            ],
                            'money' => [
                                'default' => '提现金额',
                                'value' => '提现金额'
                            ],
                            'money_placeholder' => [
                                'default' => '请输入要提取的金额',
                                'value' => '请输入要提取的金额'
                            ],
                            'min_money' => [
                                'default' => '最低提现佣金',
                                'value' => '最低提现佣金'
                            ],
                            'submit' => [
                                'default' => '提交申请',
                                'value' => '提交申请'
                            ],
                        ]
                    ],
                    'qrcode' => [
                        'title' => [
                            'default' => '推广二维码',
                            'value' => '推广二维码'
                        ]
                    ],
                ]
            ],
            'license' => [
                'key' => 'license',
                'describe' => '申请协议',
                'values' => [
                    'license' => ''
                ]
            ],
            'background' => [
                'key' => 'background',
                'describe' => '页面背景图',
                'values' => [
                    // 分销中心首页
                    'index' => self::$base_url . 'image/agent/agent-bg.jpg',
                    // 申请成为分销商页
                    'apply' => self::$base_url . 'image/agent/agent-bg.jpg',
                    // 申请提现页
                    'cash_apply' => self::$base_url . 'image/agent/agent-bg.jpg',
                ],
            ],
            'template_msg' => [
                'key' => 'template_msg',
                'describe' => '模板消息',
                'values' => [
                    'apply_tpl' => '',    // 分销商审核通知
                    'cash_tpl' => '',    // 提现状态通知
                ]
            ],
            'qrcode' => [
                'key' => 'template_msg',
                'describe' => '分销海报',
                'values' => [
                    'backdrop' => [
                        'src' => self::$base_url . 'image/agent/backdrop.jpg',
                    ],
                    'nickName' => [
                        'fontSize' => 14,
                        'color' => '#000000',
                        'left' => 150,
                        'top' => 99
                    ],
                    'avatar' => [
                        'width' => 70,
                        'style' => 'circle',
                        'left' => 150,
                        'top' => 18
                    ],
                    'qrcode' => [
                        'width' => 100,
                        'style' => 'circle',
                        'left' => 136,
                        'top' => 128
                    ]
                ],
            ]
        ];
    }
}
admin/app/common/model/release/SupplyApply.php
New file
@@ -0,0 +1,82 @@
<?php
namespace app\common\model\plus\release;
use app\common\model\BaseModel;
use app\common\model\user\User as UserModel;
/**
 * 申请模型
 */
class SupplyApply extends BaseModel
{
    protected $name = 'release_supply_apply';
    protected $pk = 'apply_id';
    /**
     * 申请状态
     * @var array
     */
    public $applyStatus = [
        10 => '待审核',
        20 => '审核通过',
        30 => '驳回',
    ];
    /**
     * 申请时间
     * @param $value
     * @return false|string
     */
    public function getApplyTimeAttr($value)
    {
        return date('Y-m-d H:i:s', $value);
    }
    /**
     * 审核时间
     * @param $value
     * @return false|int|string
     */
    public function getAuditTimeAttr($value)
    {
        return $value > 0 ? date('Y-m-d H:i:s', $value) : 0;
    }
    /**
     * 销商申请记录详情
     * @param $where
     * @return array|\think\Model|null
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public static function detail($where)
    {
        $filter = is_array($where) ? $where : ['apply_id' => $where];
        return (new static())->where($filter)->find();
    }
    /**
     * 审核状态
     * @param $value
     * @return array
     */
    public function getApplyStatusAttr($value)
    {
        $method = [10 => '待审核', 20 => '审核通过', '30' => '驳回'];
        return ['text' => $method[$value], 'value' => $value];
    }
    /**
     * 审核方式
     * @param $value
     * @return array
     */
    public function getApplyTypeAttr($value)
    {
        $method = [10 => '后台审核', 20 => '无需审核'];
        return ['text' => $method[$value], 'value' => $value];
    }
}
admin/app/common/model/release/SupplyProject.php
New file
@@ -0,0 +1,186 @@
<?php
namespace app\api\model\plus\release;
use app\common\model\plus\release\Project as ProjectModel;
use app\common\model\plus\release\ReleaseProjectImage as ReleaseProjectImageModel;
use app\common\model\plus\release\Tag as TagModel;
use app\common\model\plus\release\ReleaseProjectTag as ReleaseProjectTagModel;
/**
 * 模型
 */
class SupplyProject extends ProjectModel
{
    /**
     * 获取提现明细
     */
    public function getList($user_id, $postdata)
    {
        $model = $this;
        if(!empty($postdata["keyword"])){
            $model = $model->where('name', 'like', '%'.$postdata["keyword"].'%');
        }
        return $model->where('is_delete', '=', 0)
            ->where('project_type', '=', 1)
            ->where('user_id', '=', $user_id)
            ->order(['create_time' => 'desc'])
            ->paginate($postdata);
    }
    /**
     * 新增记录
     */
    public function add($postdata,$supply)
    {
        $data = json_decode($postdata["formData"],true);
        if (empty($data['name'])) {
                $this->error = '请输入标题';
                return false;
         }
        if (empty($data['category_id'])) {
                $this->error = '请选择分类';
                return false;
         }
        if (empty($data['price'])) {
                $this->error = '请输入您的价格';
                return false;
        }
       if (empty($data['content'])) {
                $this->error = '请输入您的详细描述';
                return false;
        }
        $save_data =[
            'user_id'=>$supply["user_id"],
            'name'=>$data["name"],
            'category_id'=>$data["category_id"],
            'price'=>$data["price"],
            'content'=>$data["content"],
            'detail'=>$data["detail"],
            'project_type'=>1,
            'is_show'=>$data["is_show"],
            'app_id'=>self::$app_id,
        ];
        if(!empty($data["finish_time"]) && $data["finish_time"] != '请选择日期'){
            $save_data["finish_time"] = strtotime($data["finish_time"]);
        }else{
            $save_data["finish_time"] = '';
        }
          return $this->transaction(function () use ($data, $save_data) {
            // 记录内容
            $this->save($save_data);
            // 记录图片
            $this->saveAllImages($this['project_id'],$data);
            // 记录标签
            $this->saveTag($this['project_id'],$data);
            return $this['project_id'];
        });
    }
    /**
     * 更新记录
     */
    public function edit($postdata)
    {
        $data = json_decode($postdata["formData"],true);
        if (empty($data['name'])) {
                $this->error = '请输入标题';
                return false;
         }
        if (empty($data['category_id'])) {
                $this->error = '请选择分类';
                return false;
         }
        if (empty($data['price'])) {
                $this->error = '请输入您的价格';
                return false;
        }
       if (empty($data['content'])) {
                $this->error = '请输入您的详细描述';
                return false;
        }
         $save_data =[
            'name'=>$data["name"],
            'category_id'=>$data["category_id"],
            'price'=>$data["price"],
            'content'=>$data["content"],
            'detail'=>$data["detail"],
            'is_show'=>$data["is_show"],
            'status'=>0,
        ];
        if(!empty($data["finish_time"]) && $data["finish_time"] != '请选择日期'){
            $save_data["finish_time"] = strtotime($data["finish_time"]);
        }else{
            $save_data["finish_time"] = '';
        }
        return $this->transaction(function () use ($data, $save_data) {
            // 记录内容
            $this->where("project_id","=",$data["project_id"])->save($save_data);
            // 记录图片
            $this->saveAllImages($data['project_id'],$data);
            // 记录标签
            $this->saveTag($data['project_id'],$data);
            return true;
        });
    }
     /**
     * 记录图片
     */
    private function saveAllImages($id,$formData)
    {
        (new ReleaseProjectImageModel())->where("project_id","=",$id)->delete();
        // 生成图片数据
        if(!empty($formData['image_list'])){
            $imageData = [];
            foreach ($formData['image_list'] as $imageId) {
                $imageData[] = [
                    'project_id' => $id,
                    'image_id' => !empty($imageId['image_id']) ? $imageId['image_id'] : $imageId['file_id'],
                    'app_id' => self::$app_id
                ];
            }
            $model = new ReleaseProjectImageModel;
            return !empty($imageData) && $model->saveAll($imageData);
        }
        return true;
    }
    /**
     * 记录标签
     */
    private function saveTag($id,$formData)
    {
        (new ReleaseProjectTagModel())->where("project_id","=",$id)->delete();
        // 生成数据
        if(!empty($formData['tag_list'])){
            $tagData = [];
            foreach ($formData['tag_list'] as $val) {
                $tagData[] = [
                    'project_id' => $id,
                    'tag_id' => $val,
                    'app_id' => self::$app_id
                ];
            }
            $model = new ReleaseProjectTagModel;
            return !empty($tagData) && $model->saveAll($tagData);
        }
        return true;
    }
    /**
     * 软删除
     */
    public function setDelete($id)
    {
        return $this->where("project_id","=",$id)->save(['is_delete' => 1]);
    }
}
admin/app/common/model/release/SupplyUser.php
New file
@@ -0,0 +1,67 @@
<?php
namespace app\common\model\plus\release;
use app\common\model\BaseModel;
/**
 * 用户模型
 */
class SupplyUser extends BaseModel
{
    protected $name = 'release_supply_user';
    protected $pk = 'user_id';
    /**
     * 关联会员记录表
     * @return \think\model\relation\BelongsTo
     */
    public function user()
    {
        return $this->belongsTo('app\\common\\model\\user\\User');
    }
    /**
     * 详情
     */
    public static function detail($user_id, $with = ['user'])
    {
        return (new static())->with($with)->find($user_id);
    }
    /**
     * 详情
     */
    public static function getAll()
    {
        return (new static())->where("is_delete","=",0)->select();
    }
    /**
     * 是否为供应方
     */
    public static function isSupplyUser($user_id)
    {
        $supply = self::detail($user_id);
        return !!$supply && !$supply['is_delete'];
    }
    /**
     * 新增记录
     * @param $user_id
     * @param $data
     * @return bool
     */
    public static function add($user_id, $data)
    {
        $model = static::detail($user_id) ?: new static;
         $model->save(array_merge([
            'user_id' => $user_id,
            'is_delete' => 0,
            'app_id' => $model::$app_id,
        ], $data));
        return true;
    }
}
admin/app/common/model/release/Tag.php
New file
@@ -0,0 +1,35 @@
<?php
namespace app\common\model\plus\release;
use app\common\model\BaseModel;
/**
 * 项目标签模型
 */
class Tag extends BaseModel
{
    protected $name = 'release_tag';
    protected $pk = 'tag_id';
    /**
     * 获取详情
     */
    public static function detail($tag_id)
    {
        return (new static())->find($tag_id);
    }
    /**
     * 获取列表记录
     */
    public static function getAll()
    {
        return (new static())->where('is_delete', '=', 0)
            ->field('tag_id,name')
            ->order(['sort' => 'asc', 'create_time' => 'asc'])
            ->select();
    }
}
admin/app/common/model/settings/Setting.php
@@ -363,6 +363,27 @@
                        "d) 买家在完成该笔交易(订单状态为“已签收”)后才能得到此笔交易的相应积分,如购买商品参加店铺其他优惠,则优惠的金额部分不享受积分获取;",
                ],
            ],
            'consumption' => [
                'key' => 'consumption',
                'describe' => '消费券设置',
                'values' => [
                    'consumption_name' => '消费券',         // 消费券名称自定义
                    'is_shopping_gift' => '0',      // 是否开启购物送消费券
                    'gift_ratio' => '100',            // 是否开启购物送消费券
                    'is_shopping_discount' => '0',    // 是否允许下单使用消费券抵扣
                    'is_trans_balance' => '0',    // 是否允许转换余额
                    'discount' => [     // 消费券抵扣
                        'discount_ratio' => '0.01',       // 消费券抵扣比例
                        'full_order_price' => '100.00',       // 订单满[?]元
                        'max_money_ratio' => '10',             // 最高可抵扣订单额百分比
                    ],
                    // 消费券说明
                    'describe' => "a) 消费券不可兑现、不可转让,仅可在本平台使用;\n" .
                        "b) 您在本平台参加特定活动也可使用消费券,详细使用规则以具体活动时的规则为准;\n" .
                        "c) 消费券的数值精确到个位(小数点后全部舍弃,不进行四舍五入)\n" .
                        "d) 买家在完成该笔交易(订单状态为“已签收”)后才能得到此笔交易的相应消费券,如购买商品参加店铺其他优惠,则优惠的金额部分不享受消费券获取;",
                ],
            ],
            'officia' => [
                'key' => 'officia',
                'describe' => '公众号关注',
admin/app/common/model/supplier/Supplier.php
@@ -263,4 +263,16 @@
        return $count;
    }
    /**
     * 下级商户数量
     * @param $user_id
     * @return int
     */
    public function getSubordinateNum($user_id)
    {
        return (new static())->where('is_delete', '=', 0)
            ->where('referee_id', 'in', $user_id)
            ->count();
    }
}
admin/app/common/model/supplier/User.php
@@ -91,16 +91,6 @@
        session('jjjshop_supplier', $session);
    }
    /**
     * 下级商户数量
     * @param $user_id
     * @return int
     */
    public function getSubordinateNum($user_id)
    {
        return (new static())->where('is_delete', '=', 0)
            ->where('referee_id', 'in', $user_id)
            ->count();
    }
}
admin/app/common/model/supplier/page/Page.php
New file
@@ -0,0 +1,809 @@
<?php
namespace app\common\model\supplier\page;
use app\common\model\BaseModel;
/**
 * diy页面模型
 */
class Page extends BaseModel
{
    protected $pk = 'page_id';
    protected $name = 'supplier_page';
    /**
     * 页面标题栏默认数据
     * @return array
     */
    public function getDefaultPage()
    {
        static $defaultPage = [];
        if (!empty($defaultPage)) return $defaultPage;
        return [
            'type' => 'page',
            'name' => '页面设置',
            'params' => [
                'name' => '页面名称',
                'title' => '页面标题',
                'share_title' => '分享标题'
            ],
            'style' => [
                'titleTextColor' => 'black',
                'titleBackgroundColor' => '#ffffff',
                'toplogo' => self::$base_url . 'image/diy/toplogo.png'
            ],
            'category' => [
                'open' => 0,
                'color' => '#000000',
            ]
        ];
    }
    /**
     * 页面diy元素默认数据
     * @return array[]
     */
    public function getDefaultItems()
    {
        return [
            'banner' => [
                'name' => '图片轮播',
                'type' => 'banner',
                'group' => 'media',
                'style' => [
                    'btnColor' => '#ffffff',
                    'background' => '', // 可以透明 by lyzflash
                    'btnShape' => 'round',//rectangle 长方形,round圆形, square正方形
                    'imgShape' => 'round', //square 正方形,round圆形
                    'height' => 200,
                ],
                'params' => [
                    'interval' => '2800'
                ],
                'data' => [
                    [
                        'imgUrl' => self::$base_url . 'image/diy/banner/01.png',
                        'linkUrl' => ''
                    ],
                    [
                        'imgUrl' => self::$base_url . 'image/diy/banner/01.png',
                        'linkUrl' => ''
                    ]
                ]
            ],
            'imageSingle' => [
                'name' => '单图组',
                'type' => 'imageSingle',
                'group' => 'media',
                'style' => [
                    'paddingTop' => 0,
                    'paddingLeft' => 0,
                    'background' => '#ffffff'
                ],
                'data' => [
                    [
                        'imgUrl' => self::$base_url . 'image/diy/banner/01.png',
                        'imgName' => 'image-1.jpg',
                        'linkUrl' => ''
                    ],
                    [
                        'imgUrl' => self::$base_url . 'image/diy/banner/01.png',
                        'imgName' => 'banner-2.jpg',
                        'linkUrl' => ''
                    ]
                ]
            ],
            'navBar' => [
                'name' => '导航组',
                'type' => 'navBar',
                'group' => 'media',
                'style' => ['background' => '#ffffff', 'rowsNum' => '4'],
                'data' => [
                    [
                        'imgUrl' => self::$base_url . 'image/diy/navbar/01.png',
                        'imgName' => 'icon-1.png',
                        'linkUrl' => '',
                        'text' => '按钮文字1',
                        'color' => '#666666'
                    ],
                    [
                        'imgUrl' => self::$base_url . 'image/diy/navbar/02.png',
                        'imgName' => 'icon-2.jpg',
                        'linkUrl' => '',
                        'text' => '按钮文字2',
                        'color' => '#666666'
                    ],
                    [
                        'imgUrl' => self::$base_url . 'image/diy/navbar/03.png',
                        'imgName' => 'icon-3.jpg',
                        'linkUrl' => '',
                        'text' => '按钮文字3',
                        'color' => '#666666'
                    ],
                    [
                        'imgUrl' => self::$base_url . 'image/diy/navbar/04.png',
                        'imgName' => 'icon-4.jpg',
                        'linkUrl' => '',
                        'text' => '按钮文字4',
                        'color' => '#666666'
                    ]
                ]
            ],
            'blank' => [
                'name' => '辅助空白',
                'type' => 'blank',
                'group' => 'tools',
                'style' => [
                    'height' => 20,
                    'background' => '#ffffff'
                ]
            ],
            'guide' => [
                'name' => '辅助线',
                'type' => 'guide',
                'group' => 'tools',
                'style' => [
                    'background' => '#ffffff',
                    'lineStyle' => 'solid',
                    'lineHeight' => '1',
                    'lineColor' => "#000000",
                    'paddingTop' => 10
                ]
            ],
            'video' => [
                'name' => '视频组',
                'type' => 'video',
                'group' => 'media',
                'params' => [
                    'videoUrl' => 'http://wxsnsdy.tc.qq.com/105/20210/snsdyvideodownload?filekey=30280201010421301f0201690402534804102ca905ce620b1241b726bc41dcff44e00204012882540400',
                    'poster' => self::$base_url . 'image/diy/video_poster.png',
                    'autoplay' => 0
                ],
                'style' => [
                    'paddingTop' => 0,
                    'height' => 190
                ]
            ],
            'article' => [
                'name' => '文章组',
                'type' => 'article',
                'group' => 'media',
                'params' => [
                    'source' => 'auto', // choice; auto
                    'auto' => [
                        'category' => '0',
                        'showNum' => 6
                    ]
                ],
                'style' => [
                    'display' => '10'
                ],
                // '自动获取' => 默认数据
                'defaultData' => [
                    [
                        'article_title' => '此处显示文章标题',
                        'show_type' => 10,
                        'image' => self::$base_url . 'image/diy/article/01.png',
                        'views_num' => 309
                    ],
                    [
                        'article_title' => '此处显示文章标题',
                        'show_type' => 10,
                        'image' => self::$base_url . 'image/diy/article/01.png',
                        'views_num' => 309
                    ]
                ],
                // '手动选择' => 默认数据
                'data' => []
            ],
            'special' => [
                'name' => '头条快报',
                'type' => 'special',
                'group' => 'media',
                'params' => [
                    'source' => 'auto', // choice; auto
                    'auto' => [
                        'category' => 0,
                        'showNum' => 6
                    ]
                ],
                'style' => [
                    'display' => 1,
                    'image' => self::$base_url . 'image/diy/special.png'
                ],
                // '自动获取' => 默认数据
                'defaultData' => [
                    [
                        'article_title' => '此处显示头条快报标题'
                    ]
                ],
                // '手动选择' => 默认数据
                'data' => []
            ],
            'notice' => [
                'name' => '公告组',
                'type' => 'notice',
                'group' => 'media',
                'params' => [
                    'text' => '这里是第一条自定义公告的标题',
                    'icon' => self::$base_url . 'image/diy/notice.png'
                ],
                'style' => [
                    'paddingTop' => 4,
                    'background' => '#ffffff',
                    'textColor' => '#000000'
                ]
            ],
            'richText' => [
                'name' => '富文本',
                'type' => 'richText',
                'group' => 'tools',
                'params' => [
                    'content' => '<p>这里是文本的内容</p>'
                ],
                'style' => [
                    'paddingTop' => 0,
                    'paddingLeft' => 0,
                    'background' => '#ffffff'
                ]
            ],
            'window' => [
                'name' => '图片橱窗',
                'type' => 'window',
                'group' => 'media',
                'style' => [
                    'paddingTop' => 0,
                    'paddingLeft' => 0,
                    'background' => '#ffffff',
                    'layout' => '2'
                ],
                'data' => [
                    [
                        'imgUrl' => self::$base_url . 'image/diy/window/01.jpg',
                        'linkUrl' => ''
                    ],
                    [
                        'imgUrl' => self::$base_url . 'image/diy/window/02.jpg',
                        'linkUrl' => ''
                    ],
                    [
                        'imgUrl' => self::$base_url . 'image/diy/window/03.jpg',
                        'linkUrl' => ''
                    ],
                    [
                        'imgUrl' => self::$base_url . 'image/diy/window/04.jpg',
                        'linkUrl' => ''
                    ]
                ],
                'dataNum' => 4
            ],
            'product' => [
                'name' => '商品组',
                'type' => 'product',
                'group' => 'shop',
                'params' => [
                    'source' => 'auto', // choice; auto
                    'auto' => [
                        'category' => 0,
                        'productSort' => 'all', // all; sales; price
                        'showNum' => 6
                    ]
                ],
                'style' => [
                    'background' => '#F6F6F6',
                    'display' => 'list', // list; slide
                    'column' => '2',
                    'show' => [
                        'productName' => 1,
                        'productPrice' => 1,
                        'linePrice' => 1,
                        'sellingPoint' => 0,
                        'productSales' => 0,
                    ]
                ],
                // '自动获取' => 默认数据
                'defaultData' => [
                    [
                        'product_name' => '此处显示商品名称',
                        'image' => self::$base_url . 'image/diy/product/01.png',
                        'product_price' => '99.00',
                        'line_price' => '139.00',
                        'selling_point' => '此款商品美观大方 不容错过',
                        'product_sales' => '100',
                    ],
                    [
                        'product_name' => '此处显示商品名称',
                        'image' => self::$base_url . 'image/diy/product/01.png',
                        'product_price' => '99.00',
                        'line_price' => '139.00',
                        'selling_point' => '此款商品美观大方 不容错过',
                        'product_sales' => '100',
                    ],
                    [
                        'product_name' => '此处显示商品名称',
                        'image' => self::$base_url . 'image/diy/product/01.png',
                        'product_price' => '99.00',
                        'line_price' => '139.00',
                        'selling_point' => '此款商品美观大方 不容错过',
                        'product_sales' => '100',
                    ],
                    [
                        'product_name' => '此处显示商品名称',
                        'image' => self::$base_url . 'image/diy/product/01.png',
                        'product_price' => '99.00',
                        'line_price' => '139.00',
                        'selling_point' => '此款商品美观大方 不容错过',
                        'product_sales' => '100',
                    ]
                ],
                // '手动选择' => 默认数据
                'data' => [
                    [
                        'product_name' => '此处显示商品名称',
                        'image' => self::$base_url . 'image/diy/product/01.png',
                        'product_price' => '99.00',
                        'line_price' => '139.00',
                        'selling_point' => '此款商品美观大方 不容错过',
                        'product_sales' => '100',
                        'is_default' => true
                    ],
                    [
                        'product_name' => '此处显示商品名称',
                        'image' => self::$base_url . 'image/diy/product/01.png',
                        'product_price' => '99.00',
                        'line_price' => '139.00',
                        'selling_point' => '此款商品美观大方 不容错过',
                        'product_sales' => '100',
                        'is_default' => true
                    ]
                ]
            ],
            'coupon' => [
                'name' => '优惠券组',
                'type' => 'coupon',
                'group' => 'shop',
                'style' => [
                    'paddingTop' => 10,
                    'background' => '#ffffff'
                ],
                'params' => [
                    'limit' => 5
                ],
                'data' => [
                    [
                        'color' => 'red',
                        'reduce_price' => '10',
                        'min_price' => '100.00'
                    ],
                    [
                        'color' => 'violet',
                        'reduce_price' => '10',
                        'min_price' => '100.00'
                    ]
                ]
            ],
            'assembleProduct' => [
                'name' => '拼团商品组',
                'type' => 'assembleProduct',
                'group' => 'shop',
                'params' => [
                    'source' => 'auto', // choice; auto
                    'showNum' => 6,
                    'auto' => [
                        'category' => 0,
                        'productSort' => 'all', // all; sales; price
                    ]
                ],
                'style' => [
                    'color' => '#C9C9C9',
                    'background_image' => self::$base_url . 'image/diy/active/assemble.png',
                    'column' => 1,
                    'show' => [
                        'productName' => true,
                        'sellingPoint' => true,
                        'assemblePrice' => true,
                        'linePrice' => true
                    ]
                ],
                // '自动获取' => 默认数据
                'defaultData' => [
                    [
                        'product_name' => '此处是拼团商品',
                        'image' => self::$base_url . 'image/diy/product/01.png',
                        'selling_point' => '此款商品美观大方 性价比较高 不容错过',
                        'assemble_price' => '99.00',
                        'line_price' => '139.00',
                    ],
                    [
                        'product_name' => '此处是拼团商品',
                        'image' => self::$base_url . 'image/diy/product/01.png',
                        'selling_point' => '此款商品美观大方 性价比较高 不容错过',
                        'assemble_price' => '99.00',
                        'line_price' => '139.00',
                    ],
                    [
                        'product_name' => '此处是拼团商品',
                        'image' => self::$base_url . 'image/diy/product/01.png',
                        'selling_point' => '此款商品美观大方 性价比较高 不容错过',
                        'assemble_price' => '99.00',
                        'line_price' => '139.00',
                    ],
                    [
                        'product_name' => '此处是拼团商品',
                        'image' => self::$base_url . 'image/diy/product/01.png',
                        'selling_point' => '此款商品美观大方 性价比较高 不容错过',
                        'assemble_price' => '99.00',
                        'line_price' => '139.00',
                    ]
                ],
                // '手动选择' => 默认数据
                'data' => [
                    [
                        'product_name' => '此处是拼团商品',
                        'image' => self::$base_url . 'image/diy/product/01.png',
                        'selling_point' => '此款商品美观大方 性价比较高 不容错过',
                        'assemble_price' => '99.00',
                        'line_price' => '139.00',
                        'is_default' => true
                    ],
                    [
                        'product_name' => '此处是拼团商品',
                        'image' => self::$base_url . 'image/diy/product/01.png',
                        'selling_point' => '此款商品美观大方 性价比较高 不容错过',
                        'assemble_price' => '99.00',
                        'line_price' => '139.00',
                        'is_default' => true
                    ]
                ]
            ],
            'bargainProduct' => [
                'name' => '砍价商品组',
                'type' => 'bargainProduct',
                'group' => 'shop',
                'params' => [
                    'source' => 'auto', // choice; auto
                    'showNum' => 6,
                    'auto' => [
                        'category' => 0,
                        'productSort' => 'all', // all; sales; price
                        'showNum' => 6
                    ]
                ],
                'style' => [
                    'color' => '#ffffff',
                    'countdown_color' => '#FF02A8',
                    'countdown_back_color' => '#FEE24F',
                    'background_image' => self::$base_url . 'image/diy/active/bargain.png',
                    'column' => 1,
                    'show' => [
                        'productName' => 1,
                        'peoples' => 1,
                        'floorPrice' => 1,
                        'originalPrice' => 1
                    ]
                ],
                'demo' => [
                    'helps_count' => 2,
                    'helps' => [
                        ['avatarUrl' => 'http://tva1.sinaimg.cn/large/0060lm7Tly1g4c7zrytvvj30dw0dwwes.jpg'],
                        ['avatarUrl' => 'http://tva1.sinaimg.cn/large/0060lm7Tly1g4c7zs2u5ej30b40b4dfx.jpg'],
                    ]
                ],
                // '自动获取' => 默认数据
                'defaultData' => [
                    [
                        'product_name' => '此处是砍价商品',
                        'product_image' => self::$base_url . 'image/diy/product/01.png',
                        'floor_price' => '0.01',
                        'original_price' => '139.00',
                    ],
                    [
                        'product_name' => '此处是砍价商品',
                        'product_image' => self::$base_url . 'image/diy/product/01.png',
                        'floor_price' => '0.01',
                        'original_price' => '139.00',
                    ],
                ],
                // '手动选择' => 默认数据
                'data' => [
                    [
                        'product_name' => '此处是砍价商品',
                        'product_image' => self::$base_url . 'image/diy/product/01.png',
                        'floor_price' => '0.01',
                        'original_price' => '139.00',
                    ],
                    [
                        'product_name' => '此处是砍价商品',
                        'product_image' => self::$base_url . 'image/diy/product/01.png',
                        'floor_price' => '0.01',
                        'original_price' => '139.00',
                    ],
                ]
            ],
            'seckillProduct' => [
                'name' => '秒杀商品组',
                'type' => 'seckillProduct',
                'group' => 'shop',
                'params' => [
                    'showNum' => 6
                ],
                'style' => [
                    'color' => '#ffffff',
                    'countdown_color' => '#FF302F',
                    'countdown_back_color' => '#FEE250',
                    'background_image' => self::$base_url . 'image/diy/active/seckill.png',
                    'column' => 3,
                    'show' => [
                        'productName' => true,
                        'seckillPrice' => true,
                        'linePrice' => true
                    ]
                ],
                // '手动选择' => 默认数据
                'data' => [
                    [
                        'product_name' => '此处是秒杀商品',
                        'product_image' => self::$base_url . 'image/diy/product/01.png',
                        'seckill_price' => '69.00',
                        'original_price' => '139.00',
                    ],
                    [
                        'product_name' => '此处是秒杀商品',
                        'product_image' => self::$base_url . 'image/diy/product/01.png',
                        'seckill_price' => '69.00',
                        'original_price' => '139.00',
                    ],
                    [
                        'product_name' => '此处是秒杀商品',
                        'product_image' => self::$base_url . 'image/diy/product/01.png',
                        'seckill_price' => '69.00',
                        'original_price' => '139.00',
                    ],
                ]
            ],
            'previewProduct' => [
                'name' => '预告商品组',
                'type' => 'previewProduct',
                'group' => 'shop',
                'params' => [
                    'showNum' => 6
                ],
                'style' => [
                    'color' => '#ff4c01',
                    'countdown_color' => '#ff4c01',
                    'countdown_back_color' => '#fef7e4',
                    'background_color' => '#ff4c01',
                    'top_image' => self::$base_url . 'image/diy/active/preview_top.png',
                    'background_image' => self::$base_url . 'image/diy/active/preview.png',
                ],
                // 默认数据
                'data' => [
                    [
                        'product_name' => '此处是预告商品',
                        'product_image' => self::$base_url . 'image/diy/product/01.png',
                        'product_price' => '69.00',
                        'original_price' => '139.00',
                    ],
                    [
                        'product_name' => '此处是预告商品',
                        'product_image' => self::$base_url . 'image/diy/product/01.png',
                        'product_price' => '69.00',
                        'original_price' => '139.00',
                    ],
                    [
                        'product_name' => '此处是预告商品',
                        'product_image' => self::$base_url . 'image/diy/product/01.png',
                        'product_price' => '69.00',
                        'original_price' => '139.00',
                    ],
                ]
            ],
            'live' => [
                'name' => '热门直播',
                'type' => 'live',
                'group' => 'shop',
                'params' => [
                    'source' => 'auto', // choice; auto
                    'showNum' => 6
                ],
                'style' => [
                    'background_image' => self::$base_url . 'image/diy/active/live.png',
                    'color' => '#000000'
                ],
                // '自动获取' => 默认数据
                'defaultData' => [
                    [
                        'shop_name' => '直播间名称',
                        'logo_image' => self::$base_url . 'image/diy/circular.png',
                        'name' => '主播昵称',
                    ],
                    [
                        'shop_name' => '直播间名称',
                        'logo_image' => self::$base_url . 'image/diy/circular.png',
                        'name' => '主播昵称',
                    ],
                ],
                // '手动选择' => 默认数据
                'data' => [
                    [
                        'name' => '直播间名称',
                        'logo_image' => self::$base_url . 'image/diy/circular.png',
                        'anchor_name' => '主播昵称',
                    ],
                    [
                        'name' => '直播间名称',
                        'logo_image' => self::$base_url . 'image/diy/circular.png',
                        'anchor_name' => '主播昵称',
                    ],
                ]
            ],
            'service' => [
                'name' => '在线客服',
                'type' => 'service',
                'group' => 'tools',
                'params' => [
                    'type' => 'chat',     // '客服类型' => chat在线聊天,phone拨打电话
                    'image' => self::$base_url . 'image/diy/service.png',
                    'phone_num' => ''
                ],
                'style' => [
                    'right' => '1',
                    'bottom' => '10',
                    'opacity' => '100'
                ]
            ],
            'title' => [
                'name' => '标题',
                'type' => 'title',
                'group' => 'media',
                'style' => [
                    'paddingTop' => 0,
                    'background' => '#F5F5F5',
                    'textColor' => '#FF0000'
                ],
                'params' => [
                    'title' => '标题名称',
                    'show_icon' => 'yes',
                    'icon' => ''
                ]
            ],
            'button' => [
                'name' => '按钮组',
                'type' => 'button',
                'group' => 'media',
                'style' => ['background' => '#ffffff', 'rowsNum' => '2'],
                'data' => [
                    [
                        'linkUrl' => '',
                        'text' => '按钮文字1',
                        'color' => '#666666'
                    ],
                    [
                        'linkUrl' => '',
                        'text' => '按钮文字2',
                        'color' => '#666666'
                    ],
                    [
                        'linkUrl' => '',
                        'text' => '按钮文字3',
                        'color' => '#666666'
                    ],
                ]
            ],
            'tab' => [
                'name' => '选项卡组',
                'type' => 'tab',
                'group' => 'media',
                'style' => ['background' => '#ffffff', 'background_active' => '#ffffff', 'text_active' => '#ef4f4f', 'show_type' => '2'],
                'data' => [
                    [
                        'linkUrl' => '',
                        'text' => '选项卡1',
                        'color' => '#666666'
                    ],
                    [
                        'linkUrl' => '',
                        'text' => '选项卡2',
                        'color' => '#666666'
                    ],
                    [
                        'linkUrl' => '',
                        'text' => '选项卡3',
                        'color' => '#666666'
                    ],
                ]
            ],
        ];
    }
    /**
     * 格式化页面数据
     * @param $json
     * @return mixed
     */
    public function getPageDataAttr($json)
    {
        // 旧版数据转义
        $array = $this->_transferToNewData($json);
        // 合并默认数据
        return $this->_mergeDefaultData($array);
    }
    /**
     * 自动转换data为json格式
     * @param $value
     * @return false|string
     */
    public function setPageDataAttr($value)
    {
        return json_encode($value ?: ['items' => []]);
    }
    /**
     * diy页面详情
     */
    public static function detail($page_id)
    {
        return (new static())->find($page_id);
    }
    /**
     * diy页面详情
     */
    public static function getHomePage($shop_supplier_id)
    {
        $data=(new static())->where('shop_supplier_id', $shop_supplier_id)->where('page_type', '10')->find();
        if (!$data){
            $data=(new static())->where('shop_supplier_id', 0)->where('page_type', '10')->find();
        }
        return $data;
    }
    /**
     * 旧版数据转义为新版格式
     */
    private function _transferToNewData($json)
    {
        $array = json_decode($json, true);
        $items = $array['items'];
        if (isset($items['page'])) {
            unset($items['page']);
        }
        foreach ($items as &$item) {
            isset($item['data']) && $item['data'] = array_values($item['data']);
        }
        return [
            'page' => isset($array['page']) ? $array['page'] : $array['items']['page'],
            'items' => array_values(array_filter($items))
        ];
    }
    /**
     * 合并默认数据
     */
    private function _mergeDefaultData($array)
    {
        $array['page'] = array_merge_multiple($this->getDefaultPage(), $array['page']);
        $defaultItems = $this->getDefaultItems();
        foreach ($array['items'] as &$item) {
            if (isset($defaultItems[$item['type']])) {
                array_key_exists('data', $item) && $defaultItems[$item['type']]['data'] = [];
                $item = array_merge_multiple($defaultItems[$item['type']], $item);
            }
        }
        return $array;
    }
    /**
     * 首页默认设置
     */
    public static function getDefault($shop_supplier_id)
    {
        $data=(new static())->where('shop_supplier_id', $shop_supplier_id)->where('page_type', '10')->order('is_default desc,page_id desc')->find();
        if (!$data){
            $data=(new static())->where('shop_supplier_id', 0)->where('page_type', '10')->order('is_default desc,page_id desc')->find();
        }
        return $data;
    }
}
admin/app/common/model/user/ConsumptionLog.php
New file
@@ -0,0 +1,41 @@
<?php
namespace app\common\model\user;
use app\common\model\BaseModel;
/**
 * 会员消费券记录模型
 */
class ConsumptionLog extends BaseModel
{
    protected $name = 'user_consumption_log';
    protected $pk = 'log_id';
    protected $updateTime = false;
    /**
     * 关联会员记录表
     */
    public function user()
    {
        $module = self::getCalledModule() ?: 'common';
        return $this->belongsTo("app\\{$module}\\model\\user\\User");
    }
    /**
     * 新增记录
     */
    public static function add($data)
    {
        $static = new static;
        $static->save(array_merge(['app_id' => $static::$app_id], $data));
    }
    /**
     * 新增记录 (批量)
     */
    public function onBatchAdd($saveData)
    {
        return $this->saveAll($saveData);
    }
}
admin/app/common/model/user/User.php
@@ -13,6 +13,7 @@
use app\common\model\user\User as UserModel;
use think\facade\Db; // by lyzflash
use app\common\model\plus\bonus\User as BonusUserModel;
use app\common\model\user\ConsumptionLog as ConsumptionLogModel;
/**
 * 用户模型
 */
@@ -155,6 +156,20 @@
        }
        return true;
    }
    /**
     * 累积用户的可用消费券数量 (批量)
     */
    public function onBatchIncConsumption($data)
    {
        foreach ($data as $userId => $expendPoints) {
            $this->where(['user_id' => $userId])
                ->inc('consumer_coupon', $expendPoints)
                ->inc('total_expend_money', $expendPoints)
                ->update();
            event('UserGrade', $this['user_id']);
        }
        return true;
    }
    /**
     * 累积用户的可用积分
@@ -174,6 +189,31 @@
        // 用户总积分
        if ($points > 0) {
            $data['total_points'] = $this['total_points'] + $points;
        }
        $this->where('user_id', '=', $this['user_id'])->update($data);
        if($upgrade) {
            event('UserGrade', $this['user_id']);
        }
        return true;
    }
    /**
     * 累积用户的可用消费券
     */
    public function setIncConsumption($consumption, $describe, $decConsumption = 0, $upgrade = true)
    {
        // 新增消费券变动明细
        ConsumptionLogModel::add([
            'user_id' => $this['user_id'],
            'value' => $consumption,
            'describe' => $describe,
            'app_id' => $this['app_id'],
        ]);
        // 更新用户可用消费券
        $data['consumer_coupon'] = ($this['consumer_coupon'] + $consumption + $decConsumption <= 0) ? 0 : $this['consumer_coupon'] + $consumption + $decConsumption;
        // 用户总消费券
        if ($consumption > 0) {
            $data['total_expend_money'] = $this['total_expend_money'] + $consumption;
        }
        $this->where('user_id', '=', $this['user_id'])->update($data);
        if($upgrade) {
@@ -271,9 +311,15 @@
    {
        $user= self::detail($user_id);
        $purchase_count=$user['purchase_count']+1;
        if ($purchase_count>11){
            return false;
        if ($purchase_count==1&&$user['referee_id']){
            $referee= self::detail($user['referee_id']);
            if ($referee){
                $referee->setIncConsumption(10, '直推首单礼包');
            }
        }
        /*if ($purchase_count>11){
            return false;
        }*/
        self::where('user_id',$user_id)->update([
            'purchase_count'=>$purchase_count
        ]);
admin/app/common/service/delivery/ExpressService.php
@@ -39,7 +39,7 @@
    {
        if ($this->cityId) {
            foreach ($this->productList as &$product) {
                if($product['is_virtual'] == 1){
                if($product['is_virtual'] == 1||$product['is_virtual'] == 3){
                    continue;
                }
                if($product['delivery_id'] == 0){
@@ -65,7 +65,7 @@
        $orderTotalPrice = helper::getArrayColumnSum($this->productList, 'total_price');
        foreach ($this->productList as &$product) {
            // 如果是虚拟物品,则为0
            if($product['is_virtual'] == 1){
            if($product['is_virtual'] == 1 || $product['is_virtual'] == 3){
                $product['express_price'] = 0;
            }else if($product['delivery_id'] == 0){
                // 包邮
admin/app/common/service/order/OrderCompleteService.php
@@ -12,6 +12,7 @@
use app\common\model\plus\agent\Order as AgentOrderModel;
use app\common\model\plus\team\Order as TeamOrderModel;
use app\common\model\user\PointsLog as PointsLogModel;
use app\common\model\user\ConsumptionLog as ConsumptionLogModel;
use app\common\enum\order\OrderTypeEnum;
use app\common\model\order\OrderSettled as OrderSettledModel;
use app\supplier\model\store\Order as StoreOrderModel;
@@ -119,6 +120,8 @@
        $this->setIncUserExpend($orderList);
        // 处理订单赠送的积分
        $this->setGiftPointsBonus($orderList);
        // 处理订单赠送的消费券
        $this->setGiftConsumptionBonus($orderList);
        // 将订单设置为已结算
        $this->model->onBatchUpdate($orderIds, ['is_settled' => 1,'settled_time' => time(),'is_settled_team' => 1]);
        // 供应商结算
@@ -298,6 +301,47 @@
        }
        return true;
    }
    /**
     * 处理订单赠送的消费券
    */
    private function setGiftConsumptionBonus($orderList)
    {
        // 计算用户所得消费券
        $userData = [];
        $logData = [];
        foreach ($orderList as $order) {
            // 计算用户所得消费券
            $pointsBonus = $order['consumption_bonus'];
            if ($pointsBonus <= 0) continue;
            // 减去订单退款的积分
            foreach ($order['product'] as $product) {
                if (
                    !empty($product['refund'])
                    && $product['refund']['type']['value'] == 10      // 售后类型:退货退款
                    && $product['refund']['is_agree']['value'] == 10  // 商家审核:已同意
                ) {
                    $pointsBonus -= $product['consumption_bonus'];
                }
            }
            // 计算用户所得积分
            !isset($userData[$order['user_id']]) && $userData[$order['user_id']] = 0;
            $userData[$order['user_id']] += $pointsBonus;
            // 整理用户积分变动明细
            $logData[] = [
                'user_id' => $order['user_id'],
                'value' => $pointsBonus,
                'describe' => "订单赠送:{$order['order_no']}",
                'app_id' => $order['app_id'],
            ];
        }
        if (!empty($userData)) {
            // 累积到会员表记录
            $this->UserModel->onBatchIncConsumption($userData);
            // 批量新增积分明细记录
            (new ConsumptionLogModel)->onBatchAdd($logData);
        }
        return true;
    }
    /**
     * 累积用户实际消费金额
admin/app/job/event/VipUserGrade.php
@@ -33,6 +33,9 @@
        log_write('VIP用户升级$user_id='.$userId);
        // 用户模型
        $user = vipUserModel::detail($userId);
        if (empty($user)) {
            return false;
        }
        // 获取所有等级
        $list = GradeModel::getUsableList($user['app_id']);
        if ($list->isEmpty()) {
admin/app/shop/controller/product/Product.php
@@ -84,7 +84,12 @@
        if (isset($data['product_id'])) {
            $data['product_id'] = 0;
        }
        if (!empty($data['shop_supplier_id'])){
            $shop_supplier=SupplierModel::detail($data['shop_supplier_id']);
            $data['is_newcomer'] = $shop_supplier['is_newcomer'];
            $data['is_repurchase'] = $shop_supplier['is_repurchase'];
            $data['is_vip'] = $shop_supplier['is_vip'];
        }
        if ($model->add($data)) {
            return $this->renderSuccess('添加成功');
        }
@@ -122,8 +127,15 @@
        }
        // 商品详情
        $model = ProductModel::detail($product_id);
        $data = json_decode($this->postData()['params'], true);
        if(!empty($data['shop_supplier_id'])){
            $shop_supplier=SupplierModel::detail($data['shop_supplier_id']);
            $data['is_newcomer'] = $shop_supplier['is_newcomer'];
            $data['is_repurchase'] = $shop_supplier['is_repurchase'];
            $data['is_vip'] = $shop_supplier['is_vip'];
        }
        // 更新记录
        if ($model->edit(json_decode($this->postData()['params'], true))) {
        if ($model->edit($data, true)) {
            return $this->renderSuccess('更新成功');
        }
        return $this->renderError($model->getError() ?: '更新失败');
admin/app/shop/controller/user/Consumption.php
New file
@@ -0,0 +1,40 @@
<?php
namespace app\shop\controller\user;
use app\shop\controller\Controller;
use app\shop\model\settings\Setting as SettingModel;
use app\shop\model\user\ConsumptionLog as ConsumptionLogModel;
/**
 * 消费券控制器
 */
class Consumption extends Controller
{
    /**
     * 消费券设置
     */
    public function setting()
    {
        if ($this->request->isGet()) {
            $values = SettingModel::getItem('consumption');
            return $this->renderSuccess('', compact('values'));
        }
        $model = new SettingModel;
        if ($model->edit('consumption', $this->postData())) {
            return $this->renderSuccess('操作成功');
        }
        return $this->renderError($model->getError() ?: '操作失败');
    }
    /**
     * 消费券明细
     */
    public function log()
    {
        // 消费券明细列表
        $model = new ConsumptionLogModel;
        $list = $model->getList($this->request->param());
        return $this->renderSuccess('', compact('list'));
    }
}
admin/app/shop/model/product/Comment.php
@@ -49,7 +49,7 @@
            ->field('round(avg(express_score),1) as score')->find();
        $server = $this->where(['shop_supplier_id' => $shop_supplier_id, 'status'=>1,'is_delete'=>0])
            ->field('round(avg(server_score),1) as score')->find();
        $describe = $this->where(['shop_supplier_id '=> $shop_supplier_id,'status'=>1,'is_delete'=>0])
        $describe = $this->where(['shop_supplier_id'=> $shop_supplier_id,'status'=>1,'is_delete'=>0])
            ->field('round(avg(describe_score),1) as score')->find();
        //更新店铺分数
        $SupplierModel->where('shop_supplier_id','=', $shop_supplier_id)
admin/app/shop/model/user/ConsumptionLog.php
New file
@@ -0,0 +1,37 @@
<?php
namespace app\shop\model\user;
use app\common\model\user\ConsumptionLog as consumptionModel;
/**
 * 用户消费券变动明细模型
 */
class ConsumptionLog extends consumptionModel
{
    /**
     * 获取消费券变动明细列表
     */
    public function getList($query = [])
    {
        $model = $this;
        //搜索订单号
        if (isset($query['search']) && $query['search'] != '') {
            $model = $model->where('user.nickName', 'like', '%' . trim($query['search']) . '%');
        }
        //搜索时间段
        if (isset($query['value1']) && $query['value1'] != '') {
            $sta_time = array_shift($query['value1']);
            $end_time = array_pop($query['value1']);
            $model = $model->whereBetweenTime('log.create_time', $sta_time, date('Y-m-d 23:59:59', strtotime($end_time)));
        }
        // 获取列表数据
        return $model->with(['user'])
            ->alias('log')
            ->field('log.*')
            ->join('user', 'user.user_id = log.user_id')
            ->order(['log.create_time' => 'desc'])
            ->paginate($query);
    }
}
admin/app/supplier/controller/product/Product.php
@@ -52,6 +52,7 @@
        $data = json_decode($this->postData()['params'], true);
        $data['is_newcomer'] = $supplier['is_newcomer'];
        $data['is_repurchase'] = $supplier['is_repurchase'];
        $data['is_vip'] = $supplier['is_vip'];
        // 添加商品
        if($scene == 'copy'){
            unset($data['create_time']);
@@ -91,7 +92,7 @@
     */
    public function getBaseData($supplier)
    {
        return $this->renderSuccess('', array_merge(ProductService::getEditData(null, 'add', $this->getSupplierId()),['is_newcomer'=>$supplier['is_newcomer'],'is_repurchase'=>$supplier['is_repurchase']]));
        return $this->renderSuccess('', array_merge(ProductService::getEditData(null, 'add', $this->getSupplierId()),['is_newcomer'=>$supplier['is_newcomer'],'is_repurchase'=>$supplier['is_repurchase'],'is_vip'=>$supplier['is_vip']]));
    }
    /**
@@ -113,12 +114,13 @@
            $model = ProductModel::detail($product_id);
            $is_newcomer = $supplier['is_newcomer'];
            $is_repurchase = $supplier['is_repurchase'];
            $is_vip = $supplier['is_vip'];
            $supplierName='';
            if($model['belonging_shop_supplier_id']){
                $belonging_shop_supplier= SupplierModel::detail($model['belonging_shop_supplier_id']);
                $supplierName=$belonging_shop_supplier['name'];
            }
            return $this->renderSuccess('', array_merge(ProductService::getEditData($model, $scene, $this->getSupplierId()), compact('model','is_newcomer','is_repurchase','supplierName')));
            return $this->renderSuccess('', array_merge(ProductService::getEditData($model, $scene, $this->getSupplierId()), compact('model','is_newcomer','is_repurchase','is_vip','supplierName')));
        }
        if ($scene == 'copy') {
            return $this->add($scene);
@@ -128,6 +130,7 @@
        $data = json_decode($this->postData()['params'], true);
        $data['is_newcomer'] = $supplier['is_newcomer'];
        $data['is_repurchase'] = $supplier['is_repurchase'];
        $data['is_vip'] = $supplier['is_vip'];
        // 更新记录
        if ($model->edit($data,$this->getSupplierId())) {
            return $this->renderSuccess('更新成功');
admin/app/supplier/controller/supplier/Page.php
New file
@@ -0,0 +1,254 @@
<?php
namespace app\supplier\controller\supplier;
use app\common\enum\settings\SettingEnum;
use app\supplier\controller\Controller;
use app\supplier\model\supplier\page\Page as PageModel;
use app\supplier\model\settings\Setting as SettingModel;
/**
 * 供应商diy页面管理
 */
class Page extends Controller
{
    /**
     * 页面列表
     */
    public function list()
    {
        $model = new PageModel;
        $data = $this->postData();
        $data['shop_supplier_id'] = $this->getSupplierId();
        $list = $model->getList($data, 10);
        //查找默认
        $default = $model::getDefault($this->getSupplierId());
        return $this->renderSuccess('', compact('list', 'default'));
    }
    /**
     * 页面列表
     */
    public function index()
    {
        $model = new PageModel;
        $list = $model->getList($this->postData());
        return $this->renderSuccess('', compact('list'));
    }
    /**
     * 新增页面
     */
    public function add()
    {
        $model = new PageModel;
        if ($this->request->isGet()) {
            return $this->renderSuccess('', [
                'defaultData' => $model->getDefaultItems(),
                'jsonData' => ['page' => $model->getDefaultPage(), 'items' => []],
                'opts' => [
                    'catgory' => [],
                ]
            ]);
        }
        // 接收post数据
        $post = $this->postData();
        $params=json_decode($post['params'], true);
        $params['shop_supplier_id'] = $this->getSupplierId();
        if (!$model->add($params)) {
            return $this->renderError($model->getError() ?: '添加失败');
        }
        return $this->renderSuccess('添加成功');
    }
    /**
     * 首页编辑
     * @return \think\response\Json
     */
    public function home()
    {
        return $this->edit();
    }
    /**
     * 编辑页面
     */
    public function edit($page_id = null)
    {
        $model = $page_id > 0 ? PageModel::detail($page_id) : PageModel::getHomePage();
        if ($this->request->isGet()) {
            $jsonData = $model['page_data'];
            jsonRecursive($jsonData);
            return $this->renderSuccess('', [
                'defaultData' => $model->getDefaultItems(),
                'jsonData' => $jsonData,
                'opts' => [
                    'catgory' => [],
                ]
            ]);
        }
        // 接收post数据
        $post = $this->postData();
        $params=json_decode($post['params'], true);
        $params['shop_supplier_id'] = $this->getSupplierId();
        if (!$model->edit($params)) {
            return $this->renderError($model->getError() ?:'更新失败');
        }
        return $this->renderSuccess('更新成功');
    }
    /**
     * 删除页面
     */
    public function delete($page_id)
    {
        // 帮助详情
        $model = PageModel::detail($page_id);
        if (!$model->setDelete()) {
            return $this->renderError($model->getError() ?:'删除失败');
        }
        return $this->renderSuccess('删除成功');
    }
    /**
     * 分类模板
     */
    public function category()
    {
        $model = PageCategoryModel::detail();
        if($this->request->isGet()){
            return $this->renderSuccess('', compact('model'));
        }
        if ($model->edit($this->postData())) {
            return $this->renderSuccess('更新成功');
        }
        return $this->renderError($model->getError() ?: '更新失败');
    }
    /**
     * 新增页面
     */
    public function addPage()
    {
        $model = new PageModel;
        if ($this->request->isGet()) {
            return $this->renderSuccess('', [
                'defaultData' => $model->getDefaultItems(),
                'jsonData' => ['page' => $model->getDefaultPage(), 'items' => []],
                'opts' => [
                    'catgory' => [],
                ]
            ]);
        }
        // 接收post数据
        $post = $this->postData();
        $params=json_decode($post['params'], true);
        $params['shop_supplier_id'] = $this->getSupplierId();
        if (!$model->add($params, 10)) {
            return $this->renderError($model->getError() ?: '添加失败');
        }
        return $this->renderSuccess('添加成功');
    }
    /**
     * 编辑页面
     */
    public function editPage($page_id)
    {
        $model = PageModel::detail($page_id);
        if ($this->request->isGet()) {
            $jsonData = $model['page_data'];
            jsonRecursive($jsonData);
            return $this->renderSuccess('', [
                'defaultData' => $model->getDefaultItems(),
                'jsonData' => $jsonData,
                'opts' => [
                    'catgory' => [],
                ]
            ]);
        }
        // 接收post数据
        $post = $this->postData();
        $params=json_decode($post['params'], true);
        $params['shop_supplier_id'] = $this->getSupplierId();
        if (!$model->edit($params)) {
            return $this->renderError($model->getError() ?: '更新失败');
        }
        return $this->renderSuccess('更新成功');
    }
    /**
     * 删除页面
     */
    public function deletePage($page_id)
    {
        // 详情
        $model = PageModel::detail($page_id);
        if (!$model->setDelete()) {
            return $this->renderError($model->getError() ?: '删除失败');
        }
        return $this->renderSuccess('删除成功');
    }
    /**
     * 设置默认
     */
    public function setPage($page_id)
    {
        // 页面详情
        $model = PageModel::detail($page_id);
        if (!$model->setDefault()) {
            return $this->renderError($model->getError() ?: '设置失败');
        }
        return $this->renderSuccess('设置成功');
    }
    /**
     * 商城设置
     */
    public function nav()
    {
        if($this->request->isGet()){
            $data = SettingModel::getItem('nav');
            return $this->renderSuccess('', compact('data'));
        }
        $model = new SettingModel;
        $data = $this->postData();
        if ($model->edit('nav', $data)) {
            return $this->renderSuccess('操作成功');
        }
        return $this->renderError($model->getError() ?: '操作失败');
    }
    /**
     * 底部菜单
     */
    public function bottomnav()
    {
        $vars = SettingModel::getItem(SettingEnum::NAV);
        return $this->renderSuccess('', compact('vars'));
    }
    /**
     * 底部菜单设置
     */
    public function bottomedit()
    {
        $model = new SettingModel;
        $data = $this->postData();
        if ($model->edit('nav', $data)) {
            return $this->renderSuccess('操作成功');
        }
        return $this->renderError($model->getError() ?: '操作失败');
    }
    public function setHome($page_id) {
        //取消原来的首页
        PageModel::getHomePage()->setPageType(20);
        $model = PageModel::detail($page_id);
        if (!$model->setPageType(10)) {
            return $this->renderError($model->getError() ?:'设置失败');
        }
        return $this->renderSuccess('设置成功');
    }
}
admin/app/supplier/model/supplier/page/Page.php
New file
@@ -0,0 +1,89 @@
<?php
namespace app\supplier\model\supplier\page;
use app\common\model\supplier\page\Page as PageModel;
/**
 * 供应商diy页面模型
 */
class Page extends PageModel
{
    /**
     * 获取列表
     */
    public function getList($params, $page_type = 20)
    {
        $model = new $this;
        return $model->where(['is_delete' => 0])
            ->where(['shop_supplier_id'=>$params['shop_supplier_id']])
            ->where(['page_type' => $page_type])
            ->order(['create_time' => 'desc'])
            ->hidden(['page_data'])
            ->paginate($params);
    }
    /**
     * 获取所有自定义页面
     */
    public function getLists()
    {
        return $this->where(['is_delete' => 0])
            ->where(['page_type' => 20])
            ->hidden(['page_data'])
            ->order(['create_time' => 'desc'])
            ->select();
    }
    /**
     * 新增页面
     */
    public function add($data, $page_type = 20)
    {
        return $this->save([
            'page_type' => $page_type,
            'shop_supplier_id' => $data['shop_supplier_id'],
            'page_name' => $data['page']['params']['name'],
            'page_data' => $data,
            'app_id' => self::$app_id
        ]);
    }
    /**
     * 更新页面
     */
    public function edit($data)
    {;
        // 保存数据
        return $this->save([
                'page_name' => $data['page']['params']['name'],
                'shop_supplier_id' => $data['shop_supplier_id'],
                'page_data' => $data
            ]) !== false;
    }
    /**
     * 删除
     */
    public function setDelete()
    {
        return $this->save(['is_delete' => 1]);
    }
    /**
     * 设置默认页
     */
    public function setDefault()
    {
        $this->save(['is_default' => 1]);
        $this->where('page_id', '<>', $this['page_id'])->update(['is_default' => 0]);
        return true;
    }
    /**
     * 设置默认页
     */
    public function setPageType($num){
        return $this->save(['page_type' => $num]);
    }
}
mobile/main.js
@@ -69,7 +69,15 @@
    }
    
}
Vue.prototype.consumption_name = function(e) {
    if(!e){
        return store.state.consumption_name;
    }else{
        let re = new RegExp("消费券","g");
        return e.replace(re, store.state.consumption_name);
    }
}
//#ifdef H5
app.$router.afterEach((to, from) => {
    const u = navigator.userAgent.toLowerCase();
mobile/pages.json
@@ -1158,7 +1158,14 @@
                        //#endif
                    }
                }
            }]
            },
            {
                "path": "consumer/consumer",
                "style": {
                    "navigationBarTitleText": "消费券"
                }
            }
        ]
        },
        {
            "root": "pages/store",
mobile/pages/order/confirm-order.vue
@@ -50,7 +50,7 @@
                        </view>
                    </view>
                    
                    <Verifystoreinfo v-if="supplier_item.orderData.delivery==30 && supplier_item.productList[0].is_virtual == 1" ref="getShopinfoData" :extract_store="extract_store"
                    <Verifystoreinfo v-if="supplier_item.orderData.delivery==30 && (supplier_item.productList[0].is_virtual == 1||supplier_item.productList[0].is_virtual == 3)" ref="getShopinfoData" :extract_store="extract_store"
                     :last_extract="last_extract" :verify_data="verify_data"></Verifystoreinfo>
                    <view class="d-f-c">
@@ -143,6 +143,12 @@
                                <view class="theme-price f24">-¥{{supplier_item.orderData.points_money}}</view>
                            </view>
                        </view>
                        <view v-if="is_use_consumption==1&&!OrderData.force_points&&supplier_item.orderData.consumption_money>0">
                            <view class="d-f-c">
                                <view>{{consumption_name()}}抵扣金额</view>
                                <view class="theme-price f24">-¥{{supplier_item.orderData.consumption_money}}</view>
                            </view>
                        </view>
                        <view class="d-f-c">
                            <view class="ww100">
                                <view class="mb20">订单备注</view>
@@ -206,6 +212,14 @@
                <view class="">
                    <text class="theme-price f24">-¥{{toDecimal2(OrderData.points_money)}}</text>
                    <switch style="transform: scale(0.7); margin-right: -10rpx;" checked=true @change="onShowPoints" />
                </view>
            </view>
            <view class="item"
                v-if="OrderData.is_allow_consumption && OrderData.force_points == false &&OrderData.consumption_money != 0">
                <text class="key">可用{{consumption_name()}}抵扣:</text>
                <view class="">
                    <text class="theme-price f24">-¥{{toDecimal2(OrderData.consumption_money)}}</text>
                    <switch style="transform: scale(0.7); margin-right: -10rpx;" checked=true @change="onShowConsumption" />
                </view>
            </view>
        </view>
@@ -292,6 +306,8 @@
                coupon_id: -1,
                /*是否使用积分,默认使用*/
                is_use_points: 1,
                /*是否使用消费券,默认使用*/
                is_use_consumption: 1,
                remark: '',
                /*支付方式*/
                pay_type: 20,
@@ -430,6 +446,16 @@
                }
                self.getData();
            },
            /*是否使用消费券选择*/
            onShowConsumption: function(e) {
                let self = this;
                if (e.target.value == true) {
                    self.is_use_consumption = 1;
                } else {
                    self.is_use_consumption = 0;
                }
                self.getData();
            },
            /*选择优惠卷*/
            onTogglePopupCoupon(e, id) {
                let self = this;
@@ -526,6 +552,7 @@
                    store_id: self.store_id,
                    coupon_id: self.coupon_id,
                    is_use_points: self.is_use_points,
                    is_use_consumption: self.is_use_consumption,
                    // pay_source: self.getPlatform()
                    pay_source: 'android'
                };
@@ -834,6 +861,7 @@
                        room_id: self.room_id,
                        coupon_id: self.coupon_id,
                        is_use_points: self.is_use_points,
                        is_use_consumption: self.is_use_consumption,
                        // pay_source: self.getPlatform()
                    };
mobile/pages/order/pay-success/pay-success.vue
@@ -13,6 +13,12 @@
                <text class="gray3">{{detail.points_bonus}}</text>
            </view>
        </view>
        <view class="order-info mt30 f28" v-if="detail.consumption_bonus > 0">
            <view class="d-b-c p20 border-b">
                <text class="gray9">{{consumption_name()}}赠送</text>
                <text class="gray3">{{detail.consumption_bonus}}</text>
            </view>
        </view>
        <view class="success-btns d-b-c">
            <button type="default" class="flex-1 mr10" @click="goHome()">返回首页</button>
            <button type="primary" class="flex-1 ml10" @click="goMyorder">我的订单</button>
mobile/pages/shop/shop.vue
@@ -1,7 +1,7 @@
<template>
    <view>
        <!-- #ifdef MP-WEIXIN || APP-PLUS -->
        <view class="shop_top" :class="{'topbg':scrollViewTop>10}">
        <view class="shop_top" :class="{'topbg':scrollViewTop>10}" :style="'background-color: '+bgcolor+';'">
            <view class="ww100" :style="'height:'+topBarTop()+'px;'"></view>
            <view class="tc d-s-c head_top_box" :style="topBarHeight() == 0 ? '': 'height:'+topBarHeight()+'px;'">
                <view class="reg180" @click="goback"><text class="icon iconfont icon-jiantou"></text></view>
@@ -13,413 +13,40 @@
                <view class="wx-top-right"></view>
            </view>
        </view>
        <view class="top_head pr" :style="'background-color: '+bgcolor+';'">
            <!-- #ifndef MP-WEIXIN-->
            <view class="state_top"></view>
            <!-- #endif -->
            <view class="head_top" :style="'height:'+topBarTop()+'px;'"></view>
            <view class="d-b-c" :class="index_open_city==1?'open_city':''" :style="topBarHeight() == 0 ? '': 'height:'+topBarHeight()+'px;'">
            </view>
            <view class="nuter" v-if="openCategory.open">
                <navBar style="width: 100%;" :color='openCategory.color' @currentIndex="setIndex" :currentI="thisindex"
                    :navList="category_list">
                </navBar>
            </view>
            <view style="height: 20rpx;" v-else></view>
        </view>
        <view class="top_bg" :style="'background-color: '+bgcolor+';'">
        </view>
        <!-- #endif -->
        <scroll-view v-if="" scroll-y="true" :style="'height:' + scrollviewHigh + 'px;'" class="scroll-Y pr bg-f2"
            lower-threshold="50" @scrolltolower="scrolltolowerFunc" @scroll="scrollChnage">
            <view class="shop_head">
                <!-- #ifdef MP-WEIXIN || APP-PLUS -->
                <view class="ww100" :style="'height:'+topBarTop()+'px;'"></view>
                <view class="ww100" :style="'height:'+topBarHeight()+'px;'"></view>
                <!-- #endif -->
                <image class="bg_topimg" src="../../static/background_top.png" mode=""></image>
                <view class="shop_head_info">
                    <view class="shop_list_body_item_shop">
                        <view class="shop_list_body_item_shop_logo">
                            <image :src="shop_info.logos" mode=""></image>
                        </view>
                        <view class="shop_list_body_item_shop_info">
                            <view class="f34 white fb title">{{shop_info.store_name}}</view>
                            <view class="f24 white d-s-c">
                                <!-- <view>主营:{{shop_info.category_name}}</view> -->
                                <view class="pr20">
                                    <text class="icon iconfont icon-htmal5icon24"></text> {{shop_info.server_score}}分
                                </view>
                                <view v-if="shop_info.fav_count>0">{{shop_info.fav_count}}人关注</view>
                            </view>
                            <!-- <view class="f26 d-s-c">
                                <view class="flex-1">
                                    <text class="icon iconfont icon-dizhi"></text>
                                    {{shop_info.address}}
                                </view>
                            </view> -->
                        </view>
                        <view class="shop_list_body_item_shop_others">
                            <view v-if="isfollow == 0" class="collect_btn" @click="guanzhu()"><text
                                    class="icon iconfont icon-guanzhu1 mr10"></text>关注</view>
                            <view v-if="isfollow == 1" class="collect_btn collected" @click="guanzhu()">已关注</view>
                        </view>
                    </view>
                    <view class="shop-notice gray mt10 text-ellipsis">公告:{{shop_info.notice}}</view>
                </view>
            </view>
            <view :class="{'tab-fixed':isFixed}" :style="isFixed?'top:' + topHeight + 'px;':''">
                <!-- 导航栏 -->
                <view class="inner-tab tab-top">
                    <view :class="nav_type==4?'item active':'item'" @click="changeNavType(4)">
                        <view class="box">简介</view>
                    </view>
                    <!-- <view :class="nav_type==99?'item active':'item'" @click="changeNavType(99)">
                        <view class="box">精选</view>
                    </view> -->
                    <view :class="nav_type==0?'item active':'item'" @click="changeNavType(0)">
                        <view class="box">商品</view>
                    </view>
                    <view :class="nav_type==5?'item active':'item'" @click="changeNavType(5)">
                        <view class="box">活动列表</view>
                    </view>
                    <!-- <view :class="nav_type==2?'item active':'item'" @click="changeNavType(2)">
                        <view class="box">优惠券</view>
                    </view> -->
                    <view :class="nav_type==1?'item active':'item'" @click="changeNavType(1)"
                        v-if="is_record==1&&is_open==1">
                        <view class="box">直播</view>
                    </view>
                    <view :class="nav_type==6?'item active':'item'" @click="changeNavType(6)">
                        <view class="box">案例</view>
                    </view>
                    <!-- <view :class="nav_type==3?'item active':'item'" @click="changeNavType(3)">
                        <view class="box">商家</view>
                    </view> -->
                </view>
                <!-- 导航栏 -->
            </view>
            <view class="ww100" style="height: 80rpx;" v-if="isFixed"></view>
            <view class="shop" :class="nav_type==0?'shop-product':''" v-if="shop_info!=''"
                :style="'min-height:' + scrollviewHigh + 'px;'">
                <view class="shop_head_banner pr bg-white" v-if="adList!= ''">
                    <swiper :indicator-dots="true" :autoplay="true" :interval="3000" :duration="1000">
                        <swiper-item class="swiper-item" v-for="(item,index) in adList" :key="index">
                            <image :src="item.image.file_path" mode=""></image>
                        </swiper-item>
                    </swiper>
                </view>
                <view v-if="nav_type==4">
                    <view class="shop_info_description" v-html="shop_info.description">
                    </view>
                </view>
                <view v-if="nav_type==6">
                    <scroll-view scroll-y="true" class="scroll-Y" lower-threshold="50"
                        @scrolltolower="scrolltolowerFunc">
                        <view class="article-list">
                            <view class="item" v-for="(item, index) in articlelistData" :key="index"
                                @click="gotoDetail(item.article_id)">
                                <view class="info">
                                    <view class="title">{{ item.article_title }}</view>
                                    <view class="summary">{{ item.dec }}</view>
                                    <view class="datatime d-s-c">
                                        <text>{{ item.create_time }}</text>
                                        <text class="icon iconfont icon-chakan ml30"></text>
                                        <text class="ml10">{{ item.actual_views }}</text>
                                    </view>
                                </view>
                                <view class="pic" v-if="item.image != null">
                                    <image :src="item.image.file_path" mode="aspectFill"></image>
                                </view>
                            </view>
                        </view>
                        <!-- 没有记录 -->
                        <view class="d-c-c p30" v-if="listData.length == 0 && !loading">
                            <text class="iconfont icon-wushuju"></text>
                            <text class="cont">亲,暂无相关记录哦</text>
                        </view>
                        <uni-load-more v-else :loadingType="loadingType"></uni-load-more>
                    </scroll-view>
                </view>
                <!-- 精选 -->
                <view v-if="nav_type==99">
                    <!-- <view class="bg-white pt30">
                        <view class="card-box d-b-c" v-if="card_num" @click.stop="gotoPage('/pages/user/card/list')">
                            <view class="d-s-c"><image class="v-log" src="/static/icon/log-vip.png" mode=""></image>领取会员卡,各种优惠享不停</view>
                            <view class="btn-card-box">立即领取<text class="icon iconfont icon-jiantou"></text></view>
                        </view>
                    </view> -->
                    <view class="shop-coupon bg-white" v-if="listData.length > 0">
                        <scroll-view scroll-x="true">
                            <view class="swiper swiper-list">
                                <view class="" v-for="(item, index) in listData" :key="index" v-if="index<=5">
                                    <view class="coupon-item" :class="'bg-' + item.color.text">
                                        <view class="side-line left-side-line"><text class="round"
                                                v-for="(round, num) in 8" :key="num"></text></view>
                                        <view class="side-line right-side-line"><text class="round"
                                                v-for="(round, num) in 8" :key="num"></text></view>
                                        <view class="left-type d-s-c">
                                            <template v-if="item.coupon_type.value == 10">
                                                <text class="f20">¥</text>
                                                <text class="f26 fb">{{ item.reduce_price }}</text>
                                            </template>
                                            <template v-if="item.coupon_type.value == 20">
                                                <text class="f24 fb">{{ item.discount }}</text>
                                                <text class="f20">折</text>
                                            </template>
                                        </view>
                                        <view class="center-content pr">
                                            <view class="content-top">
                                                <text class="f22 text-ellipsis">{{ item.name }}</text>
                                            </view>
                                            <view class="content-bottom f20">
                                                {{item.price_text}}
                                            </view>
                                        </view>
                                        <!--领取-->
                                        <view v-if="item.is_get == 0" class="right-receive d-c-c"
                                            @click="receiveCoupon(index)">
                                            领
                                        </view>
                                        <view v-else class="right-receive no-receive d-c-c">
                                            已领
                                        </view>
                                    </view>
                                </view>
                            </view>
                        </scroll-view>
                    </view>
                    <!-- 商品导航栏 -->
                    <view class="inner-tab tab-product tab-index"
                        :style="tabIndexFixed?'position:fixed;width:100%;top:' + (topHeight*1+34) + 'px;':''">
                        <view :class="type_active=='all'?'item active':'item'" @click="tabTypeFunc('all')">
                            <view class="box">推荐</view>
                        </view>
                        <view :class="type_active=='sales'?'item active':'item'" @click="tabTypeFunc('sales')">
                            <view class="box">销量</view>
                        </view>
                        <view :class="type_active=='new'?'item active':'item'" @click="tabTypeFunc('new')">
                            <view class="box">新品</view>
                        </view>
                        <view :class="type_active=='price'?'item active':'item'" @click="tabTypeFunc('price')">
                            <view class="box">
                                <text>价格</text>
                            </view>
                        </view>
                    </view>
                    <view class="ww100" style="height: 80rpx;" v-if="tabIndexFixed"></view>
                    <!-- 商品导航栏 -->
                    <view class="shop_body2">
                        <view class="shop_body_t_item" v-for="(item,index) in product_list" :key="index"
                            @click="goto_product(item.product_id)">
                            <image :src="item.product_image" mode=""></image>
                            <view class="shop_body_t_item_info">
                                <view class="shop_body_t_item_info_title h1">{{item.product_name}}</view>
                                <view class="shop_body_t_item_info_price">
                                    <view class="f24 redF6">¥<text class="h1">{{item.product_price}}</text></view>
                                    <view class="f24 huaxianjia">¥<text class="h3">{{item.line_price}}</text></view>
                                </view>
                                <view class="shop_body_t_item_info_others h3">
                                    <view class="shop_body_t_item_info_others_sales">累计成交:{{item.product_sales}}笔</view>
                                </view>
                            </view>
                        </view>
                    </view>
                </view>
                <!-- 商品导航栏 -->
                <view class="inner-tab tab-product tab-product-list" v-if="nav_type==0"
                    :style="tabProductFixed?'position:fixed;width:100%;top:' + (topHeight*1+34) + 'px;':''">
                    <view :class="type_active=='all'?'item active':'item'" @click="tabTypeFunc('all')">
                        <view class="box">综合</view>
                    </view>
                    <view :class="type_active=='sales'?'item active':'item'" @click="tabTypeFunc('sales')">
                        <view class="box">销量</view>
                    </view>
                    <view :class="type_active=='price'?'item active':'item'" @click="tabTypeFunc('price')">
                        <view class="box">
                            <text>价格</text>
                        </view>
                    </view>
                    <view class="item">
                        <view class="box">
                            <image @click="select_type()"
                                :src="isLieBiao == true?'/static/shop/liebiao.png':'/static/shop/tubiao.png'"></image>
                        </view>
                    </view>
                </view>
                <view class="ww100" style="height: 80rpx;" v-if="tabProductFixed"></view>
                <!-- 商品导航栏 -->
                <view class="shop_body" v-if="isLieBiao ==true&&nav_type==0">
                    <view class="shop_body_l_item" :class="index==listData.length-1?'noborder':''"
                        v-for="(item,index) in product_list" :key="index" @click="goto_product(item.product_id)">
                        <view>
                            <image :src="item.product_image" mode=""></image>
                        </view>
                        <view class="shop_body_l_item_info">
                            <view class="shop_body_l_item_info_title gray3 f32">{{item.product_name}}</view>
                            <view class="d-b-c pb10">
                                <view class="shop_body_l_item_info_price">
                                    <view class="f24 shop_red">¥<text class="f32 fb">{{item.product_price}}</text>
                                    </view>
                                    <!-- <view class="h4 huaxianjia">¥<text class="h3">{{item.line_price}}</text></view> -->
                                </view>
                                <view class="shop_body_l_item_info_others f22">
                                    <!-- <view class="shop_body_l_item_info_others_sales">累计成交:{{item.product_sales}}笔</view> -->
                                </view>
                            </view>
                        </view>
                    </view>
                </view>
                <view class="shop_body2" v-if="isLieBiao ==false&&nav_type==0">
                    <view class="shop_body_t_item" v-for="(item,index) in product_list" :key="index"
                        @click="goto_product(item.product_id)">
                        <image :src="item.product_image" mode=""></image>
                        <view class="shop_body_t_item_info">
                            <view class="shop_body_t_item_info_title h1">{{item.product_name}}</view>
                            <view class="shop_body_t_item_info_price">
                                <view class="f24 redF6">¥<text class="h1">{{item.product_price}}</text></view>
                                <view class="f24 huaxianjia">¥<text class="h3">{{item.line_price}}</text></view>
                            </view>
                            <view class="shop_body_t_item_info_others h3">
                                <view class="shop_body_t_item_info_others_sales">累计成交:{{item.product_sales}}笔</view>
                            </view>
                        </view>
                    </view>
                </view>
                <!-- 直播 -->
                <view v-if="nav_type==1">
                    <view class="live_list" v-if="liveList.length>0">
                        <view v-for="(liveitem,liveindex) in liveList" :key="liveindex" class="live_item"
                            @click="toRoom(liveitem)">
                            <view v-if="liveitem.record_url!=''" class="record">可回放</view>
                            <view v-if="liveitem.record_url==''" class="record_off">回放生成中</view>
                            <view class="live_img">
                                <image :src="liveitem.share.file_path" mode=""></image>
                            </view>
                        </view>
                    </view>
                    <view class="ww100" v-else>
                        <view class="f30 gray6 tc mt50 pt20">暂无直播间</view>
                    </view>
                </view>
                <!-- 客服 -->
                <view v-if="nav_type==3">
                    <view class="d-s-s d-c p-0-30 mt20 mpservice-wrap" v-if="!isloding">
                        <view class="noDatamodel"
                            v-if="dataModel==null||(dataModel.qq==''&&dataModel.wechat==''&&dataModel.phone=='')">
                            该商家尚未设置客服</view>
                        <template v-if="dataModel!=null">
                            <view v-if="dataModel.qq!=''" class="d-b-c p-20-0 f30 ww100 border-b"
                                @click="copyQQ(dataModel.qq)">
                                <text class="gray9" style="width: 140rpx;"><text
                                        class='icon iconfont icon-qq'></text></text>
                                <text class="p-0-30 flex-1">{{dataModel.qq}}</text>
                                <text class="blue">复制</text>
                            </view>
                            <view v-if="dataModel.wechat!=''" class="d-b-c p-20-0 f30 ww100 border-b"
                                @click="copyQQ(dataModel.qq)">
                                <text class="gray9" style="width: 140rpx;"><text
                                        class='icon iconfont icon-weixin'></text></text>
                                <text class="p-0-30 flex-1">{{dataModel.wechat}}</text>
                                <text class="blue">复制</text>
                            </view>
                            <view v-if="dataModel.phone!=''" class="d-b-c p-20-0 f30 ww100"
                                @click="callPhone(dataModel.phone)">
                                <text class="gray9" style="width: 140rpx;"><text
                                        class='icon iconfont icon-002dianhua'></text></text>
                                <text class="p-0-30 flex-1">{{dataModel.phone}}</text>
                                <text class="blue">拨打</text>
                            </view>
                        </template>
                    </view>
                </view>
                <!-- 优惠券 -->
                <view class="coupon" v-if="listData.length>=1&&nav_type==2">
                    <view class="diy-coupon">
                        <view class=" mt20 mb20" v-for="(item, index) in listData" :key="index">
                            <view class="coupon-item" :class="'bg-' + item.color.text">
                                <view class="side-line left-side-line"><text class="round" v-for="(round, num) in 8"
                                        :key="num"></text></view>
                                <view class="side-line right-side-line"><text class="round" v-for="(round, num) in 8"
                                        :key="num"></text></view>
                                <view class="left-type d-c-c">{{ item.coupon_type.text }}</view>
                                <view class="center-content pr">
                                    <view class="content-top">
                                        <template v-if="item.coupon_type.value == 10">
                                            <text class="f22">¥</text>
                                            <text class="f50 fb">{{ item.reduce_price }}</text>
                                            <template v-if="item.total_num >= 0">
                                                <text class="ml10">仅剩{{ item.total_num }}张</text>
                                            </template>
                                            <template v-else>
                                                <text class="ml10">不限数量</text>
                                            </template>
                                        </template>
                                        <template v-if="item.coupon_type.value == 20">
                                            <text class="f50 fb">{{ item.discount }}</text>
                                            <text>折</text>
                                        </template>
                                    </view>
                                    <view class="content-bottom">
                                        <text class="f24">{{ item.name }}</text>
                                    </view>
                                    <view class="content-datatime">
                                        <template v-if="item.expire_type == 20">
                                            有效期:{{ item.start_time.text }} 至 {{ item.end_time.text }}
                                        </template>
                                        <template v-if="item.expire_type == 10">
                                            有效期:领取后{{ item.expire_day }}天有效
                                        </template>
                                    </view>
                                </view>
                                <!--领取-->
                                <view v-if="item.is_get == 0" class="right-receive d-c-c" @click="receiveCoupon(index)">
                                    立即领取
                                </view>
                                <view v-else class="right-receive no-receive d-c-c">
                                    已领取
                                </view>
                            </view>
                            <view class="range_item d-b-c" v-if="item.apply_range == 20"
                                @click.stop="gotoPage('/pages/coupon/detail?coupon_id='+ item.coupon_id)">
                                <view>限购店铺部分商品</view>
                                <view><text class="icon iconfont icon-jiantou"
                                        style="color: #999999; font-size: 24rpx;"></text></view>
                            </view>
                        </view>
                    </view>
                </view>
                <!-- 优惠券 -->
            </view>
            <!-- 商品列表 -->
            <view v-if="nav_type==0 || nav_type==99">
                <view class="d-c-c p30" v-if="product_list.length==0 && !loading">
                    <text class="iconfont icon-wushuju"></text>
                    <text class="cont">亲,暂无相关记录哦</text>
                </view>
                <uni-load-more v-else :loadingType="loadingType"></uni-load-more>
                <view class="" style="width: 100%;height: 100rpx;">
                </view>
            </view>
        </scroll-view>
        <!-- 底部导航 -->
        <!-- <view class="d-a-c nav_bottom">
            <view :class="nav_type==0?'active':''" @click="nav_type=0">
                <view class="icon iconfont icon-Homehomepagemenu"></view>
                <view>首页</view>
            </view>
            <view v-if="is_record==1&&is_open==1" :class="nav_type==1?'active':''" @click="nav_type=1">
                <view class="icon iconfont icon-dianpu1"></view>
                <view>直播</view>
            </view>
            <view v-if="listData.length>0" :class="nav_type==2?'active':''" @click="nav_type=2">
                <view class="icon iconfont icon-quan"></view>
                <view>优惠券</view>
            </view>
            <view v-if="service_open" :class="nav_type==3?'active':''" @click="toSevice">
                <view class="icon iconfont icon-kefu2"></view>
                <view>客服</view>
            </view>
        </view> -->
        <diy style="position: relative;" :diyItems="items" :city_supplier_ids="city_supplier_ids"
            :index_open_city="index_open_city"></diy>
    </view>
</template>
<script>
    import uniLoadMore from "@/components/uni-load-more.vue";
    import diy from '@/components/diy/diy.vue';
    export default {
        components: {
            uniLoadMore
        },
        data() {
            return {
                bgcolor:'',
                longitude:'',
                latitude:'',
                isLieBiao: true,
                shop_info: '', //店铺信息
                articlelistData: [],
@@ -486,7 +113,15 @@
                tabProductTop: 0,
                tabProductFixed: false,
                card_num: 0,
                store_id: ''
                store_id: '',
                category_list: [],
                product_list: [],
                city_supplier_ids:[],
                index_cityname:'',
                index_open_city:0,
                items: [],
                url:'',
                toplogo:''
            }
        },
        computed: {
@@ -507,6 +142,11 @@
            let self = this;
            self.GetStatusBarHeight();
            self.shop_supplier_id = option.shop_supplier_id;
            //#ifdef H5
            if (this.isWeixin()) {
                this.url = window.location.href;
            }
            //#endif
        },
        onShow() {
            if (this.store_id > 0) {
@@ -526,10 +166,10 @@
        methods: {
            changeNavType(e) {
                this.nav_type = e;
                    this.page=1;
                this.page = 1;
                if (e == 0) {
                    this.initTabProduct();
                }else if(e==6){
                } else if (e == 6) {
                    this.articleGetData();
                }
            },
@@ -659,7 +299,7 @@
            },
            //获取数据列表
            getData() {
            /* getData() {
                let self = this;
                self.loading = true;
                self._post('supplier.index/index', {
@@ -694,7 +334,7 @@
                    })
                    self.getservice();
                })
            },
            }, */
            //选择图标模式或者列表模式    true 为列表模式  false 为图表模式
            select_type() {
@@ -856,7 +496,80 @@
            /*跳转文章详情*/
            gotoDetail(e) {
                this.gotoPage('/pages/article/detail/detail?article_id=' + e);
            }
            },
            /*获取首页分类*/
            getData() {
                let self = this;
                uni.showLoading({
                    title: '加载中'
                });
                self._get('supplier.page/index', {
                    url: self.url,
                    longitude:self.longitude,
                    latitude:self.latitude,
                    shop_supplier_id: self.shop_supplier_id,
                }, function(res) {
                    self.listData = res.data.list;
                    self.background = res.data.background;
                    self.items = res.data.items;
                    self.title_name = res.data.page.params.title;
                    self.bgcolor = res.data.page.style.titleBackgroundColor;
                    self.msgNum = res.data.msgNum;
                    self.toplogo = res.data.page.style.toplogo;
                    self.setPage(res.data.page);
                    self.title_type = res.data.page.params.title_type;
                    self.titleTextColor = res.data.page.style.titleTextColor;
                    self.openCategory = res.data.page.category;
                    self.index_open_city=res.data.setting.store.index_open_city;
                    self.underline_price_show=res.data.setting.store.underline_price_show;
                    if(res.data.setting.store.index_open_city==1){
                        self.getAddress();
                    }
                    //弹出收藏
                    // #ifdef  MP-WEIXIN
                    let isFirst = uni.getStorageSync('isFirst');
                    if (isFirst == '' && res.data.setting.collection.status == '1') {
                        self.is_collection = true;
                        uni.setStorageSync('isFirst', 1);
                    }
                    self.is_follow = res.data.setting.officia.status;
                    // #endif
                    // 首页推送
                    let homepush_name = uni.getStorageSync('homepush_name');
                    if (res.data.setting.homepush.is_open && homepush_name != res.data.setting.homepush.name) {
                        self.homepush_data = res.data.setting.homepush;
                        self.is_homepush = true;
                        self.is_homepush = true;
                    }
                    // 配置微信扫一扫参数
                    //#ifdef H5
                    if (self.url != '') {
                        self.jweixin = self.configWxScan(res.data.signPackage);
                    }
                    //#endif
                    uni.hideLoading();
                    self.loadding = false;
                    uni.stopPullDownRefresh();
                });
            },
            /*设置页面*/
            setPage(page) {
                uni.setNavigationBarTitle({
                    title: page.params.name
                });
                let colors = '#000000';
                if (page.style.titleTextColor == 'white') {
                    //字母要小写
                    colors = '#ffffff'
                }
                uni.setNavigationBarColor({
                    frontColor: colors,
                    backgroundColor: page.style.titleBackgroundColor
                })
                uni.setStorageSync('page',page);
            },
        }
    }
</script>
@@ -1840,7 +1553,7 @@
        font-size: 28rpx;
        line-height: 2;
    }
    .article-list-wrap .type-list .tab-item {
        padding: 0 30rpx;
        font-size: 34rpx;
@@ -1849,16 +1562,17 @@
        white-space: nowrap;
        border-bottom: 4rpx solid #FFFFFF;
    }
    .article-list-wrap .type-list .tab-item.active{
    .article-list-wrap .type-list .tab-item.active {
        border-bottom: 4rpx solid;
        @include border_color('border_color');
        margin-bottom: 0;
    }
    .article-list {
        background: #ffffff;
    }
    .article-list .item {
        padding: 30rpx;
        display: flex;
@@ -1866,22 +1580,22 @@
        align-items: center;
        border-bottom: 1px solid #e3e3e3;
    }
    .article-list .item .info {
        flex: 1;
        overflow: hidden;
    }
    .article-list .item .title {
        font-size: 36rpx;
    }
    .article-list .item .summary {
        margin-top: 20rpx;
        font-size: 28rpx;
        color: #999999;
    }
    .article-list .item .title,
    .article-list .item .summary {
        display: -webkit-box;
@@ -1889,17 +1603,17 @@
        -webkit-line-clamp: 2;
        -webkit-box-orient: vertical;
    }
    .article-list .item .pic {
        padding-left: 30rpx;
    }
    .article-list .item .pic,
    .article-list .item .pic image {
        width: 160rpx;
        height: 160rpx;
    }
    .article-list .item .datatime {
        margin-top: 20rpx;
        font-size: 24rpx;
mobile/pages/shop/shop_list.vue
@@ -48,15 +48,15 @@
                            </view>
                            <view class="shop_list_body_item_shop_info">
                                <view class="h1 title">{{item.name}}</view>
                                <view class="h3 brand address-row">主营:{{item.category_name}}</view>
                                <!-- <view class="h3 brand address-row">主营:{{item.category_name}}</view> -->
                                <view class="h3 address-row">
                                    <text class="address-text">地址:{{item.address}}</text>
                                </view>
                                <!-- <view class="h3 sales">销量{{item.product_sales}}件<text class="ml10 mr10">|</text>{{item.fav_count}}人关注</view> -->
                            </view>
                            <view class="shop_list_body_item_shop_others">
                                <view class="f26 gray3 collect">店铺评分</view>
                                <view><text class="redEe f32 fb">{{item.server_score}}</text></view>
                                <!-- <view class="f26 gray3 collect">店铺评分</view>
                                <view><text class="redEe f32 fb">{{item.server_score}}</text></view> -->
                                <view class="action-buttons">
                                    <view @click.stop="contactShop(item)">
                                        <text class="iconfont icon icon-002dianhua action-btn contact-btn"></text>
@@ -607,7 +607,6 @@
        width: 100%;
        min-height: 150rpx;
        display: flex;
        align-items: center;
        justify-content: space-between;
        margin-bottom: 10rpx;
    }
mobile/pages/tabBar/user/index.vue
@@ -52,10 +52,14 @@
                            <view class=" red_mini">{{ detail.points }}</view>
                            <text class="pt16 f24 gray3">{{points_name()}}</text>
                        </view>
                        <view class="item d-c-c d-c" @click="jumpPage('/pages/user/my-coupon/my-coupon')">
                        <view class="item d-c-c d-c" @click="jumpPage('/pages/user/consumer/consumer')">
                            <view class="red_mini">{{ detail.consumer_coupon }}</view>
                            <text class="pt16 f24 gray3">消费券</text>
                        </view>
                        <!-- <view class="item d-c-c d-c" @click="jumpPage('/pages/user/my-coupon/my-coupon')">
                            <view class="red_mini">{{ coupon }}</view>
                            <text class="pt16 f24 gray3">优惠券</text>
                        </view>
                        </view> -->
                        <view class="item d-c-c d-c" @click="jumpPage('/pages/user/my-wallet/my-wallet')" v-if="setting.balance_open==1">
                            <view class="icon-box"><span class="icon iconfont icon-qianbao"></span></view>
                            <text>我的钱包</text>
mobile/pages/user/index/index.vue
@@ -52,9 +52,13 @@
                            <view class=" red_mini">{{ detail.points }}</view>
                            <text class="pt16 f24 gray3">{{points_name()}}</text>
                        </view>
                        <view class="item d-c-c d-c" @click="jumpPage('/pages/user/my-coupon/my-coupon')">
                        <!-- <view class="item d-c-c d-c" @click="jumpPage('/pages/user/my-coupon/my-coupon')">
                            <view class="red_mini">{{ coupon }}</view>
                            <text class="pt16 f24 gray3">优惠券</text>
                        </view> -->
                        <view class="item d-c-c d-c" @click="jumpPage('/pages/user/my-coupon/my-coupon')">
                            <view class="red_mini">{{ detail.consumer_coupon }}</view>
                            <text class="pt16 f24 gray3">消费券</text>
                        </view>
                        <view v-if="setting.balance_open==1">
                            <view class="item d-c-c d-c" @click="jumpPage('/pages/user/my-wallet/my-wallet')">
mobile/store/index.js
@@ -7,7 +7,8 @@
    state: { // state的作用是定义属性变量。定义一个参数
        theme: '',
        footTab:'',
        points_name:'积分'
        points_name:'积分',
        consumption_name:'消费券'
    },
    // 全局同步方法,在methods{this.$store.commit("changeTheme")}
    mutations: {
@@ -19,6 +20,9 @@
        },
        changePoints(state, value) {
            state.points_name = value;
        },
        changeConsumption(state, value) {
            state.consumption_name = value;
        }
    },
    getters: {
shop_vue/src/api/consumption.js
New file
@@ -0,0 +1,17 @@
import request from '@/utils/request'
let ConsumptionApi = {
    /*积分设置*/
    setConsumption(data, errorback) {
        return request._post('/shop/user.consumption/setting', data, errorback);
    },
    /*获取设置*/
    getConsumption(data, errorback) {
        return request._get('/shop/user.consumption/setting', data, errorback);
    },
    /*获取积分列表*/
    GetUserList(data, errorback) {
        return request._get('/shop/user.consumption/log', data, errorback);
    },
}
export default ConsumptionApi;
shop_vue/src/views/product/product/add.vue
@@ -114,6 +114,14 @@
            is_preview: 0,
            /*商品预告时间*/
            preview_time: '',
            /*是否开启消费券赠送,默认1为开启,0为关闭*/
            is_consumption_gift: 0,
            /*是否允许使用消费券抵扣,默认1为允许,0为不允许*/
            is_consumption_discount: 1,
            /*最大抵扣消费券数量*/
            max_consumption_discount: 0,
            /*服务内容*/
            service_content: '',
          },
          /*商品分类*/
          catgory: [],
shop_vue/src/views/product/product/edit.vue
@@ -113,7 +113,7 @@
            product_weight: 0,
            /*商品编码*/
            product_no: '',
          product_sku_id: ''
            settlement_price: 0,
          },
          /*多规格类别*/
          spec_many: {
@@ -174,6 +174,15 @@
          is_preview: 0,
          /*商品预告时间*/
          preview_time: '',
          /*是否开启消费券赠送,默认1为开启,0为关闭*/
          is_consumption_gift: 0,
          /*是否允许使用消费券抵扣,默认1为允许,0为不允许*/
          is_consumption_discount: 1,
          /*最大抵扣消费券数量*/
          max_consumption_discount: 0,
          service_content:'',
          shop_supplier_id: 0
      }
    };
  },
@@ -267,6 +276,7 @@
            self.save_loading = true;
            PorductApi.editProduct({
                product_id: self.product_id,
                scene: self.scene,
                params: JSON.stringify(params)
              }, true)
              .then(data => {
shop_vue/src/views/product/product/index.vue
@@ -72,6 +72,7 @@
                <el-button v-if="scope.row.audit_status==10" @click="editClick(scope.row)" type="text" size="small" v-auth="'/product/product/edit'">编辑商品</el-button>
                <el-button v-if="scope.row.audit_status==0" @click="editClick(scope.row)" type="text" size="small" v-auth="'/product/product/edit'">审核商品</el-button>
                <el-button v-if="activeName == 'recovery'" @click="changeStatus(scope.row, 20)" type="text" size="small" v-auth="'/product/product/state'">恢复</el-button>
                <el-button @click="copyClick(scope.row)" type="text" size="small" v-auth="'/product/product/copy'">一键复制</el-button>
                <el-button @click="delClick(scope.row)" type="text" size="small" v-auth="'/product/product/delete'">删除商品</el-button>
              </div>
            </template>
@@ -186,6 +187,17 @@
        }
      });
    },
    /*打开复制*/
    copyClick(row) {
      this.$router.push({
        path: '/product/product/edit',
        query: {
          product_id: row.product_id,
          scene: 'copy'
        }
      });
    },
    /*删除*/
    delClick: function(row) {
      let self = this;
shop_vue/src/views/product/product/part/Basic.vue
@@ -23,6 +23,16 @@
        </template>
      </el-select>
    </el-form-item>
    <el-form-item label="所属供应商:">
      <el-select v-model="form.model.shop_supplier_id" clearable placeholder="请选择供应商">
        <el-option
          v-for="supplier in supplierList"
          :key="supplier.shop_supplier_id"
          :label="supplier.name"
          :value="supplier.shop_supplier_id">
        </el-option>
      </el-select>
    </el-form-item>
    <el-form-item label="预告商品:">
      <el-radio-group v-model="form.model.is_preview">
        <el-radio :label="1">开启</el-radio>
@@ -84,7 +94,7 @@
</template>
<script>
import SupplierApi from '@/api/supplier.js';
import Upload from '@/components/file/Upload';
import draggable from 'vuedraggable';
export default {
@@ -96,14 +106,25 @@
    return {
      isProductUpload: false,
      config: {},
      file_name: 'image'
      file_name: 'image',
      supplierList: []
    };
  },
  inject: ['form'],
  created() {
    this.getSupplierList();
  },
  methods: {
    /*获取供应商列表*/
    getSupplierList() {
      SupplierApi.supplierList({}, true)
        .then(res => {
          this.supplierList = res.data.list.data || [];
        })
        .catch(error => {
          console.error('获取供应商列表失败:', error);
        });
    },
    /*打开上传图片*/
    openProductUpload: function(file_type, file_name) {
@@ -225,4 +246,4 @@
.draggable-list .img-select i {
  color: #409eff;
}
</style>
</style>
shop_vue/src/views/product/product/part/Buyset.vue
@@ -12,6 +12,7 @@
        <el-radio :label="0">实物商品</el-radio>
        <el-radio :label="1">虚拟商品(无需发货)</el-radio>
        <el-radio :label="2">计次商品(无需发货)</el-radio>
        <el-radio :label="3">服务商品(无需发货)</el-radio>
      </el-radio-group>
    </el-form-item>
    <el-form-item  label="运费模板:" prop="model.delivery_id" v-if="form.model.is_virtual==0">
@@ -33,7 +34,7 @@
      <el-input type="number" min="0" v-model="form.model.limit_num" class="max-w460"></el-input>
      <div class="gray9">每个会员购买的最大数量,0为不限购</div>
    </el-form-item>
    <el-form-item label="发货类型:" v-if="form.model.is_virtual==1">
    <el-form-item label="发货类型:" v-if="form.model.is_virtual==1||form.model.is_virtual==3">
      <el-radio-group v-model="form.model.virtual_auto">
        <el-radio :label="1">自动</el-radio>
        <el-radio :label="0">手动</el-radio>
@@ -42,6 +43,10 @@
    <el-form-item label="虚拟内容:" :rules="[{ required: true, message: '请填写虚拟内容' }]" prop="model.virtual_content" v-if="form.model.is_virtual==1">
      <el-input type="text" v-model="form.model.virtual_content" class="max-w460"></el-input>
      <div class="gray9">虚拟物品内容</div>
    </el-form-item>
    <el-form-item label="服务内容:" :rules="[{ required: true, message: '请填写服务内容' }]" prop="model.service_content" v-if="form.model.is_virtual==3">
      <el-input type="text" v-model="form.model.service_content" class="max-w460"></el-input>
      <div class="gray9">服务内容</div>
    </el-form-item>
    <el-form-item label="会员等级限制:">
      <el-select v-model="form.model.grade_ids" multiple placeholder="请选择" style="width: 460px;">
@@ -71,6 +76,22 @@
    <el-form-item v-if="form.model.is_points_discount == 1" label="最大抵扣积分数量:" :rules="[{ required: true, message: ' ' }]" prop="model.max_points_discount">
      <el-input type="number" min="0" v-model="form.model.max_points_discount" class="max-w460"></el-input>
    </el-form-item>
    <div class="common-form mt50">消费券设置</div>
    <el-form-item label="是否开启消费券赠送:">
      <el-radio-group v-model="form.model.is_consumption_gift">
        <el-radio :label="1">开启</el-radio>
        <el-radio :label="0">关闭</el-radio>
      </el-radio-group>
    </el-form-item>
    <el-form-item label="是否允许使用消费券抵扣:">
      <el-radio-group v-model="form.model.is_consumption_discount">
        <el-radio :label="1">允许</el-radio>
        <el-radio :label="0">不允许</el-radio>
      </el-radio-group>
    </el-form-item>
    <el-form-item v-if="form.model.is_consumption_discount == 1" label="最大抵扣消费券数量:" :rules="[{ required: true, message: ' ' }]" prop="model.max_consumption_discount">
      <el-input type="number" min="0" v-model="form.model.max_consumption_discount" class="max-w460"></el-input>
    </el-form-item>
    <!--会员折扣设置-->
    <div class="common-form mt50">会员折扣设置</div>
    <el-form-item label="是否开启会员折扣:">
shop_vue/src/views/product/product/part/spec/Single.vue
@@ -14,6 +14,9 @@
    <el-form-item label="产品划线价:" :rules="[{ required: true, message: '请填写产品划线价' }]" prop="model.sku.line_price">
      <el-input type="number" v-model="form.model.sku.line_price" class="max-w460"></el-input>
     </el-form-item>
    <el-form-item label="产品结算价:" :rules="[{ required: false, message: '请填写产品结算价' }]" prop="model.sku.settlement_price">
      <el-input type="number" v-model="form.model.sku.settlement_price" class="max-w460"></el-input>
    </el-form-item>
    <el-form-item label="库存数量:" :rules="[{ required: true, message: '请填写库存数量' }]" prop="model.sku.stock_num">
      <el-input type="number" v-model="form.model.sku.stock_num" class="max-w460"></el-input>
    </el-form-item>
shop_vue/src/views/product/product/part/spec/many/Table.vue
@@ -10,6 +10,7 @@
          批量设置
          <el-input size="small" v-model="batchData.product_price" placeholder="销售价" style="width: 160px;padding-left: 4px;"></el-input>
          <el-input size="small" v-model="batchData.line_price" placeholder="划线价" style="width: 160px;padding-left: 4px;"></el-input>
          <el-input size="small" v-model="batchData.settlement_price" placeholder="结算价" style="width: 160px;padding-left: 4px;"></el-input>
          <el-input size="small" v-model="batchData.stock_num" placeholder="库存" style="width: 160px;padding-left: 4px;"></el-input>
          <el-input size="small" v-model="batchData.product_weight" placeholder="重量" style="width: 160px;padding-left: 4px;"></el-input>
          <el-button size="small" @click="onSubmitBatchData">应用</el-button>
@@ -49,6 +50,11 @@
                <el-form-item label="" style="margin-bottom: 0;"><el-input size="small" prop="line_price" v-model="scope.row.spec_form.line_price"></el-input></el-form-item>
              </template>
            </el-table-column>
            <el-table-column label="结算价">
              <template slot-scope="scope">
                <el-form-item label="" style="margin-bottom: 0;"><el-input size="small" prop="settlement_price" v-model="scope.row.spec_form.settlement_price"></el-input></el-form-item>
              </template>
            </el-table-column>
            <el-table-column label="库存">
              <template slot-scope="scope">
                <el-form-item
shop_vue/src/views/user/consumption/index.vue
New file
@@ -0,0 +1,42 @@
<template>
  <!--
      作者 luoyiming
      时间:2020-06-09
      描述:会员-消费券管理
  -->
  <div class="common-seach-wrap">
    <el-tabs v-model="activeName">
      <el-tab-pane label="消费券设置" name="first"></el-tab-pane>
      <el-tab-pane label="消费券明细" name="second"></el-tab-pane>
    </el-tabs>
    <!--消费券设置-->
    <Setting v-if="activeName == 'first'"></Setting>
    <!--消费券明细-->
    <Log v-if="activeName == 'second'"></Log>
  </div>
</template>
<script>
import Setting from './part/Setting';
import Log from './part/Log';
export default {
  components: {
    Setting,
    Log
  },
  data() {
    return {
      form: {
        status: 0
      },
      activeName: 'first'
    };
  },
  methods: {}
};
</script>
<style>
</style>
shop_vue/src/views/user/consumption/part/Log.vue
New file
@@ -0,0 +1,134 @@
<template>
  <!--
      作者 luoyiming
      时间:2020-06-09
      描述:会员-消费券管理-消费券明细
  -->
  <div class="user">
    <!--搜索表单-->
    <div class="common-seach-wrap">
      <el-form size="small" :inline="true" :model="formInline" class="demo-form-inline">
        <el-form-item label="昵称">
          <el-input v-model="formInline.search" placeholder="请输入昵称"></el-input>
        </el-form-item>
        <el-form-item label="注册时间">
          <div class="block">
            <span class="demonstration"></span>
            <el-date-picker v-model="formInline.value1" type="daterange"  value-format="yyyy-MM-dd" range-separator="至" start-placeholder="开始日期"
              end-placeholder="结束日期">
            </el-date-picker>
          </div>
        </el-form-item>
        <el-form-item>
          <el-button type="primary" icon="el-icon-search" @click="onSubmit">查询</el-button>
        </el-form-item>
      </el-form>
    </div>
    <!--内容-->
    <div class="product-content">
      <div class="table-wrap">
        <el-table size="small" :data="tableData" border style="width: 100%" v-loading="loading">
          <el-table-column prop="log_id" label="ID" width="60"></el-table-column>
          <el-table-column prop="nickName" label="微信头像" width="70">
            <template slot-scope="scope">
              <img :src="scope.row.user.avatarUrl" width="30" height="30" />
            </template>
          </el-table-column>
          <el-table-column prop="" label="昵称">
            <template slot-scope="scope">
              <span>{{scope.row.user.nickName}}</span>
              <span class="gray9">(用户ID:{{scope.row.user.user_id}})</span>
            </template>
          </el-table-column>
          <el-table-column prop="value" label="变动数量"></el-table-column>
          <el-table-column prop="describe" label="描述/说明"></el-table-column>
          <el-table-column prop="remark" label="管理员备注">
            <template slot-scope="scope">
              <span v-if="scope.row.remark==''">--</span>
            </template>
          </el-table-column>
          <el-table-column prop="create_time" label="创建时间"></el-table-column>
        </el-table>
      </div>
      <!--分页-->
      <div class="pagination">
        <el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange" background :current-page="curPage"
          :page-size="pageSize" layout="total, prev, pager, next, jumper"
          :total="totalDataNumber">
        </el-pagination>
      </div>
    </div>
  </div>
</template>
<script>
  import ConsumptionApi from '@/api/consumption.js';
  export default {
    components: {},
    data() {
      return {
        /*是否加载完成*/
        loading: true,
        /*列表数据*/
        tableData: [],
        /*一页多少条*/
        pageSize: 10,
        /*一共多少条数据*/
        totalDataNumber: 0,
        /*当前是第几页*/
        curPage: 1,
        /*横向表单数据模型*/
        formInline: {
          search: '',
          value1: ''
        },
      };
    },
    created() {
      /*获取列表*/
      this.getTableList();
    },
    methods: {
      /*选择第几页*/
      handleCurrentChange(val) {
        let self = this;
        self.curPage = val;
        self.loading = true;
        self.getTableList();
      },
      /*每页多少条*/
      handleSizeChange(val) {
        this.curPage = 1;
        this.pageSize = val;
        this.getTableList();
      },
      /*获取列表*/
      getTableList() {
        let self = this;
        let Params = self.formInline;
        Params.page = self.curPage;
        Params.list_rows = self.pageSize;
        ConsumptionApi.GetUserList(Params, true).then(data => {
          self.loading = false;
          self.tableData = data.data.list.data;
          self.totalDataNumber = data.data.list.total;
        }).catch(error => {
        });
      },
      /*搜索查询*/
      onSubmit() {
        let self = this;
        self.loading = true;
        self.getTableList();
      },
    }
  };
</script>
<style></style>
shop_vue/src/views/user/consumption/part/Setting.vue
New file
@@ -0,0 +1,172 @@
<template>
  <!--
      作者 luoyiming
      时间:2020-06-09
      描述:会员-消费券管理-消费券设置
  -->
  <div class="pb50">
    <el-form ref="form" size="small" :model="form" label-width="200px">
      <div class="common-form">消费券设置</div>
      <el-form-item label="消费券名称 " prop="consumption_name" :rules="[{required: true,message: ' '}]">
        <el-input v-model="form.consumption_name" autocomplete="off" class="max-w460"></el-input>
        <div class="lh18 mt10 gray9">
          <p>注:修改消费券名称后,在买家端的所有页面里,看到的都是自定义的名称</p>
          <p>例:商家使用自定义的消费券名称来做品牌运营。如京东把消费券称为“京豆”,淘宝把消费券称为“淘金币”</p>
        </div>
      </el-form-item>
      <el-form-item label="消费券说明" :rules="[{required: true,message: ' '}]">
        <el-input type="textarea" rows="5" v-model="form.describe" autocomplete="off"></el-input>
      </el-form-item>
      <div class="common-form">消费券赠送</div>
      <el-form-item label="是否开启购物送消费券">
        <el-radio-group v-model="form.is_shopping_gift">
          <el-radio :label="1">开启</el-radio>
          <el-radio :label="0">关闭</el-radio>
        </el-radio-group>
        <div class="lh18 mt10 gray9">
          <p>注:如开启则订单完成后赠送用户消费券</p>
          <p>消费券赠送规则:1.订单确认收货已完成;2.已完成订单超出后台设置的申请售后期限</p>
        </div>
      </el-form-item>
      <el-form-item label="消费券赠送比例 " prop="gift_ratio" :rules="[{required: true,message: ' '}]">
        <el-input placeholder="请输入内容" v-model="form.gift_ratio" class="max-w460">
          <template slot="append">%</template>
        </el-input>
        <div class="lh18 mt10 gray9">
          <p> 注:赠送比例请填写数字0~100;订单的运费不参与消费券赠送</p>
          <p> 例:订单付款金额(100.00元) * 消费券赠送比例(100%) = 实际赠送的消费券(100消费券)</p>
        </div>
      </el-form-item>
      <!-- <el-form-item label="生日消费赠送 " prop="birthday_ratio" :rules="[{required: true,message: ' '}]">
        <el-input placeholder="请输入内容" v-model="form.birthday_ratio" class="max-w460">
          <template slot="append">倍</template>
        </el-input>
        <div class="lh18 mt10 gray9">
          <p> 注:赠送倍数请填写数字0~100;该倍数目前仅对会员等级的兑换比例生效,一般用于生日那天消费可得双倍消费券</p>
          <p> 例:蹭送消费券(100消费券) * 消费券倍数(2) = 实际赠送的消费券(200消费券)</p>
        </div>
      </el-form-item> -->
      <div class="common-form">消费券抵扣</div>
      <el-form-item label=" 是否允许下单使用消费券抵扣 ">
        <el-radio-group v-model="form.is_shopping_discount" class="max-w460">
          <el-radio :label="1">允许</el-radio>
          <el-radio :label="0">不允许</el-radio>
        </el-radio-group>
        <div class="lh18 mt10 gray9">
          <p>注:如开启则用户下单时可选择使用消费券抵扣订单金额</p>
        </div>
      </el-form-item>
      <el-form-item label=" 是否允许消费券转换余额 ">
        <el-radio-group v-model="form.is_trans_balance" class="max-w460">
          <el-radio :label="1">允许</el-radio>
          <el-radio :label="0">不允许</el-radio>
        </el-radio-group>
        <div class="lh18 mt10 gray9">
          <p>注:如开启则用户可将消费券转换成余额</p>
        </div>
      </el-form-item>
      <el-form-item label=" 消费券抵扣比例">
        <el-input placeholder="请输入内容" v-model="form.discount.discount_ratio" class="max-w460">
          <template slot="prepend">1个消费券可抵扣</template>
          <template slot="append">元</template>
        </el-input>
        <div class="lh18 mt10 gray9">
          <p>例如:1消费券可抵扣0.01元,100消费券则可抵扣1元,1000消费券则可抵扣10元</p>
        </div>
      </el-form-item>
      <el-form-item label=" 抵扣条件">
        <el-input placeholder="请输入内容" v-model="form.discount.full_order_price" class="max-w460">
          <template slot="prepend">订单满</template>
          <template slot="append">元</template>
        </el-input>
      </el-form-item>
      <el-form-item label=" ">
        <el-input placeholder="请输入内容" v-model="form.discount.max_money_ratio" class="max-w460">
          <template slot="prepend">最高可抵扣金额</template>
          <template slot="append">%</template>
        </el-input>
        <div class="lh18 mt10 gray9">
          <p>温馨提示:例如订单金额100元,最高可抵扣10%,此时用户可抵扣10元</p>
        </div>
      </el-form-item>
      <!--提交-->
      <div class="common-button-wrapper">
        <el-button type="primary" size="small" @click="onSubmit" :loading="loading">提交</el-button>
      </div>
    </el-form>
  </div>
</template>
<script>
  import ConsumptionApi from '@/api/consumption.js';
  export default {
    data() {
      return {
        form: {
          is_shopping_gift: 1,
          gift_ratio: 10,
          is_shopping_discount: 1,
          discount: {
            discount_ratio: 0,
            full_order_price: 0,
            max_money_ratio: 0,
          },
          is_trans_balance: 0,
         // birthday_ratio:0,
        },
        loading: false,
      };
    },
    created() {
      /*获取数据*/
      this.getData();
    },
    methods: {
      /*获取数据*/
      getData() {
        let self = this;
        let Params = {};
        ConsumptionApi.getConsumption(Params, true).then(data => {
          self.form = data.data.values;
          self.form.is_shopping_gift = parseInt(data.data.values.is_shopping_gift);
          self.form.is_shopping_discount = parseInt(data.data.values.is_shopping_discount);
          self.form.is_trans_balance = parseInt(data.data.values.is_trans_balance);
        }).catch(error => {
        });
      },
      /*保存*/
      onSubmit() {
        let self = this;
        let form = self.form;
        self.$refs.form.validate((valid) => {
          if (valid) {
            self.loading = true;
            ConsumptionApi.setConsumption(form, true)
              .then(data => {
                self.loading = false;
                if (data.code == 1) {
                  self.$message({
                    message: '恭喜你,保存成功',
                    type: 'success'
                  });
                } else {
                  self.loading = false;
                }
              })
              .catch(error => {
                self.loading = false;
              });
          }
        });
      },
    }
  };
</script>
<style>
</style>
supplier_vue/src/api/link.js
New file
@@ -0,0 +1,12 @@
import request from '@/utils/request'
let LinkApi = {
    /*获取数据列表*/
    getList(data, errorback) {
        return request._post('/supplier/link.link/index', data, errorback);
    },
    /*获取数据列表*/
    getPageList(data, errorback) {
        return request._post('/supplier/link.link/getPageList', data, errorback);
    },
}
export default LinkApi;
supplier_vue/src/api/page.js
New file
@@ -0,0 +1,119 @@
import request from '@/utils/request'
let PageApi = {
    /*获取数据*/
    detail(data, errorback) {
        return request._post('/supplier/supplier.page/detail', data, errorback);
    },
    /*上架样式*/
    toAddPage(data, errorback) {
        return request._get('/supplier/supplier.page/add', data, errorback);
    },
    /*上架样式*/
    addPage(data, errorback) {
        return request._post('/supplier/supplier.page/add', data, errorback);
    },
    /*页面列表*/
    PageList(data, errorback) {
        return request._post('/supplier/supplier.page/index', data, errorback);
    },
    /*删除页面*/
    deletePage(data, errorback) {
        return request._post('/supplier/supplier.page/delete', data, errorback);
    },
    /*设为首页*/
    setHome(data, errorback) {
        return request._post('/supplier/supplier.page/setHome', data, errorback);
    },
    /*编辑页面*/
    editHome(data, errorback) {
        return request._get('/supplier/supplier.page/home', data, errorback);
    },
    /*编辑页面*/
    editPage(data, errorback) {
        return request._get('/supplier/supplier.page/edit', data, errorback);
    },
    /*保存编辑页面*/
    SavePage(data, errorback) {
        return request._post('/supplier/supplier.page/edit', data, errorback);
    },
    /*获取分类*/
    getCategory(data, errorback) {
        return request._get('/supplier/supplier.page/category', data, errorback);
    },
    /*提交分类*/
    postCategory(data, errorback) {
        return request._post('/supplier/supplier.page/category', data, errorback);
    },
    /*获取导航*/
    getNav(data, errorback) {
        return request._get('/supplier/supplier.page/nav', data, errorback);
    },
    /*提交导航*/
    postNav(data, errorback) {
        return request._post('/supplier/supplier.page/nav', data, errorback);
    },
    /*广告列表*/
    menuList(data, errorback) {
      return request._post('/supplier/supplier.page.Mymenu/index', data, errorback);
    },
    /*添加广告*/
    addMenu(data, errorback) {
      return request._post('/supplier/supplier.page.Mymenu/add', data, errorback);
    },
    /*广告详情*/
    menuDetail(data, errorback) {
      return request._get('/supplier/supplier.page.Mymenu/detail', data, errorback);
    },
    /*修改广告*/
    editMenu(data, errorback) {
      return request._post('/supplier/supplier.page.Mymenu/edit', data, errorback);
    },
    /*删除广告*/
    deleteMenu(data, errorback) {
      return request._post('/supplier/supplier.page.Mymenu/delete', data, errorback);
    },
    /*首页模板列表*/
    HomeList(data, errorback) {
        return request._post('/supplier/supplier.page/list', data, errorback);
    },
    /*设为首页*/
    setPage(data, errorback) {
        return request._post('/supplier/supplier.page/setPage', data, errorback);
    },
    /*编辑页面*/
    getHome(data, errorback) {
        return request._get('/supplier/supplier.page/addPage', data, errorback);
    },
    /*保存编辑页面*/
    addhome(data, errorback) {
        return request._post('/supplier/supplier.page/addPage', data, errorback);
    },
    getEdit(data, errorback) {
        return request._get('/supplier/supplier.page/editPage', data, errorback);
    },
    editHome(data, errorback) {
        return request._post('/supplier/supplier.page/editPage', data, errorback);
    },
    /*主题详情*/
    themeDetail(data, errorback) {
      return request._get('/supplier/page.theme/index', data, errorback);
    },
    /*修改广告*/
    editTheme(data, errorback) {
      return request._post('/supplier/page.theme/index', data, errorback);
    },
    /*获取导航*/
    getbottomNav(data, errorback) {
        return request._get('/supplier/supplier.page/bottomnav', data, errorback);
    },
    editTabbar(data, errorback) {
        return request._post('/supplier/supplier.page/bottomedit', data, errorback);
    },
}
export default PageApi;
supplier_vue/src/assets/img/category_40.jpg
supplier_vue/src/assets/img/theme1.jpg
supplier_vue/src/assets/img/theme2.jpg
supplier_vue/src/assets/img/theme3.jpg
supplier_vue/src/assets/img/theme4.jpg
supplier_vue/src/assets/img/theme5.jpg
supplier_vue/src/assets/img/theme6.jpg
supplier_vue/src/assets/img/theme7.jpg
supplier_vue/src/components/setlink/SetTab.vue
New file
@@ -0,0 +1,102 @@
<template>
  <!--
        作者:luoyiming
        时间:2020-01-08
        描述:超链接选择
    -->
  <el-dialog title="超链接设置" append-to-body :visible.sync="dialogVisible" @close="dialogFormVisible"
    :close-on-click-modal="false" :close-on-press-escape="false" width="800px">
    <!--内容-->
    <el-tabs type="border-card" v-model="activeName">
      <!--页面-->
      <el-tab-pane label="页面" name="pages"><Pages v-if="activeName == 'pages'" @changeData="activeDataFunc"></Pages></el-tab-pane>
      <!-- <el-tab-pane label="营销" name="market"><Marketing v-if="activeName == 'market'" @changeData="activeDataFunc"></Marketing></el-tab-pane> -->
      <!-- <el-tab-pane label="产品" name="product"><Product v-if="activeName == 'product'" @changeData="activeDataFunc"></Product></el-tab-pane> -->
      <el-tab-pane label="文章" name="Article"><Article v-if="activeName == 'Article'" @changeData="activeDataFunc"></Article></el-tab-pane>
      <el-tab-pane label="自定义" name="diypage"><DiyPage v-if="activeName == 'diypage'" @changeData="activeDataFunc"></DiyPage></el-tab-pane>
    </el-tabs>
    <div slot="footer" class="dialog-footer d-b-c">
      <div class="flex-1">
        <div v-if="activeData != null" class="d-s-s d-c tl">
          <p class="text-ellipsis setlink-set-link">
            <span>当前链接:</span>
            <span class="gray9">{{ activeData.type }}</span>
            <span class="p-0-10 gray">/</span>
            <span class="blue">{{ activeData.name }}</span>
          </p>
          <p class="text-ellipsis gray" style="font-size: 10px;">{{ activeData.url }}</p>
        </div>
        <div v-else class="tl">
          暂无
        </div>
      </div>
      <div class="setlink-footer-btn">
        <el-button size="small" @click="dialogFormVisible(false)">取 消</el-button>
        <el-button size="small" type="primary" @click="dialogFormVisible(true)">确 定</el-button>
      </div>
    </div>
  </el-dialog>
</template>
<script>
import Pages from './part/Pages.vue';
import Marketing from './part/Marketing.vue';
import Product from './part/Product.vue';
import DiyPage from './part/DiyPage.vue';
import Article from './part/Article.vue';
import SmallProgram from './part/SmallProgram.vue';
import H5 from './part/H5.vue';
export default {
  components: {
    Pages,
    Marketing,
    Product,
    Article,
    SmallProgram,
    H5,
    DiyPage
  },
  data() {
    return {
      /*是否显示*/
      dialogVisible: true,
      /*选中的链接*/
      activeData: null,
      activeName: 'pages'
    };
  },
  props: ['is_linkset'],
  created() {
    this.dialogVisible = this.is_linkset;
  },
  methods: {
    /*关闭弹窗*/
    dialogFormVisible(e) {
      if (e) {
        if(this.activeData.url.indexOf('giftpackage') != -1){
          this.activeData.name = '礼包购-' + this.activeData.name;
        }
        if(this.activeData.url.indexOf('invite') != -1){
          this.activeData.name = '邀请有礼-' + this.activeData.name;
        }
        this.$emit('closeDialog', this.activeData);
      } else {
        this.$emit('closeDialog', null);
      }
    },
    /*页面返回值*/
    activeDataFunc(e) {
      this.activeData = e;
    }
  }
};
</script>
<style>
.marketing-box .el-tabs__item {
  font-size: 12px;
}
.setlink-footer-btn{ width: 160px;}
.setlink-set-link{ width: 500px;}
</style>
supplier_vue/src/components/setlink/part/Article.vue
New file
@@ -0,0 +1,131 @@
<template>
  <!--
        作者:luoyiming
        时间:2020-06-08
        描述:超链接选择-文章
    -->
  <div class="article-box">
    <!--搜索表单-->
    <div class="common-seach-wrap">
      <el-form size="small" :inline="true" class="demo-form-inline">
        <el-form-item>
          <el-button size="small" icon="el-icon-notebook-2" @click="chooseList">选择文章列表</el-button>
        </el-form-item>
      </el-form>
    </div>
    <!--内容-->
    <div class="article-content">
      <div class="table-wrap">
        <el-table size="mini" :data="tableData" border style="width: 100%">
          <el-table-column prop="article_title" label="文章标题"></el-table-column>
          <el-table-column prop="category.name" label="文章分类" width="80"></el-table-column>
          <el-table-column label="操作" width="80">
            <template slot-scope="scope">
              <el-button size="mini" @click="changeFunc(scope.row)">选择</el-button>
            </template>
          </el-table-column>
        </el-table>
      </div>
      <!--分页-->
      <div class="pagination">
        <el-pagination
          @size-change="handleSizeChange"
          @current-change="handleCurrentChange"
          background
          :current-page="curPage"
          :page-size="pageSize"
          layout="total, prev, pager, next, jumper"
          :total="totalDataNumber"
        ></el-pagination>
      </div>
    </div>
  </div>
</template>
<script>
import ArticleApi from '@/api/article.js';
export default {
  data() {
    return {
      /*tab切换选择中值*/
      activeTab: 'second',
      /*一页多少条*/
      pageSize: 5,
      /*一共多少条数据*/
      totalDataNumber: 0,
      /*当前是第几页*/
      curPage: 1,
      /*是否加载完成*/
      loading: true,
      /*产品数据表*/
      tableData: [],
      /*选中的值*/
      activePage: {}
    };
  },
  created() {
    this.chooseList();
    /*获取列表*/
    this.getData();
  },
  watch: {},
  methods: {
    /*选择第几页*/
    handleCurrentChange(val) {
      let self = this;
      self.curPage = val;
      self.getData();
    },
    /*每页多少条*/
    handleSizeChange(val) {
      this.pageSize = val;
      this.curPage = 1;
      this.getData();
    },
    /*获取文章列表*/
    getData() {
      let self = this;
      self.loading = true;
      let Params = {};
      Params.page = self.curPage;
      Params.list_rows = self.pageSize;
      ArticleApi.articlelist(Params, true)
        .then(data => {
          self.loading = false;
          self.tableData = data.data.list.data;
          self.totalDataNumber = data.data.list.total;
        })
        .catch(error => {
          console.log(error);
        });
    },
    /*选中的值*/
    changeFunc(e) {
      let obj={};
      obj.name = e.article_title;
      obj.url = 'pages/article/detail/detail?article_id=' + e.article_id;
      obj.type = '文章';
      this.$emit('changeData',obj);
    },
    /*选择列表*/
    chooseList(){
      let obj={};
      obj.name = '文章列表';
      obj.url = 'pages/article/list/list';
      obj.type = '文章';
      this.$emit('changeData',obj);
    }
  }
};
</script>
<style></style>
supplier_vue/src/components/setlink/part/DiyPage.vue
New file
@@ -0,0 +1,66 @@
<template>
  <!--
        作者:luoyiming
        时间:2020-06-08
        描述:超链接选择-自定义页面
    -->
  <el-select v-model="activePage" placeholder="请选择" class="percent-w100" @change="changeFunc" value-key="url" v-loading="loading">
    <el-option v-for="item in pages" :key="item.url" :label="item.name" :value="item"></el-option>
  </el-select>
</template>
<script>
import LinkApi from '@/api/link.js';
export default {
  data() {
    return {
      /*是否正在加载*/
      loading:true,
      /*页面数据*/
      pages: [],
      /*选中的值*/
      activePage: {}
    };
  },
  created() {
    this.getData();
  },
  methods: {
    /*获取自定义页面*/
    getData() {
      let self = this;
      LinkApi.getPageList({}, true)
        .then(res => {
          self.loading = false;
          let list = [];
          for (let i = 0,length=res.data.list.length; i < length; i++) {
            let item = res.data.list[i];
            let url = 'pages/diy-page/diy-page?page_id=' + item.page_id;
            let LinkList = {
              url: url,
              name: item.page_name,
              type: '自定义页面'
            };
            list.push(LinkList);
          }
          self.pages = list;
          if(self.pages.length>0){
            self.activePage=self.pages[0]
            self.changeFunc(self.activePage);
          }
        })
        .catch(error => {
          self.loading = false;
        });
    },
    /*选中的值*/
    changeFunc(e) {
      this.$emit('changeData', e);
    }
  }
};
</script>
<style></style>
supplier_vue/src/components/setlink/part/H5.vue
New file
@@ -0,0 +1,37 @@
<template>
  <el-form label-width="80px" :model="formmodel">
    <el-form-item label="https://">
      <el-input v-model="formmodel.name" @input="changeFunc"></el-input>
     </el-form-item>
    <el-form-item label="">
      <p>注意一:链接的网页必须支持SSL ,链接必须以 https:// 开头,否则无法跳转</p>
      <p>注意二:链接的域名必须是备案域名,否则无法跳转</p>
      <p>注意三:您的网站域名必须加到微信小程序公众平台的业务域名处,详细说明?</p>
    </el-form-item>
  </el-form>
</template>
<script>
  export default{
    data(){
      return {
        /*form模型*/
        formmodel: {}
      }
    },
    methods:{
      /*选中的值*/
      changeFunc(e){
        //从e中把name和ur赋值到下面的对象
        let boj={
          name:'',
          url:'https://'+e
        }
        this.$emit('changeData',boj);
      }
    }
  }
</script>
<style>
</style>
supplier_vue/src/components/setlink/part/Marketing.vue
New file
@@ -0,0 +1,175 @@
<template>
  <!--
        作者:luoyiming
        时间:2020-06-08
        描述:超链接选择-营销
    -->
  <div class="marketing-box">
    <el-tabs v-model="activeTab">
      <el-tab-pane label="签到" name="signin"></el-tab-pane>
      <el-tab-pane label="积分商城" name="points"></el-tab-pane>
      <el-tab-pane label="预售" name="presale"></el-tab-pane>
      <el-tab-pane label="秒杀" name="seckill"></el-tab-pane>
      <el-tab-pane label="拼团" name="assemble"></el-tab-pane>
      <el-tab-pane label="砍价" name="bargain"></el-tab-pane>
      <el-tab-pane label="预告" name="preview"></el-tab-pane>
      <el-tab-pane label="领券中心" name="coupon"></el-tab-pane>
      <el-tab-pane label="幸运转盘" name="lottery"></el-tab-pane>
      <el-tab-pane label="万能表单" name="table"></el-tab-pane>
    </el-tabs>
    <el-select v-model="activePage" placeholder="请选择" class="percent-w100" @change="changeFunc" value-key="id">
      <el-option v-for="(item, index) in pages" :key="index" :label="item.name" :value="item"></el-option>
    </el-select>
  </div>
</template>
<script>
import LinkApi from '@/api/link.js';
export default {
  data() {
    return {
      /*tab切换选择中值*/
      activeTab: 'signin',
      /*页面数据*/
      pages: [],
      /*选中的值*/
      activePage: null,
      /*秒杀数据*/
      seckillList: [
        {
          id: 0,
          url: 'pages/plus/seckill/list/list',
          name: '秒杀',
          type: '营销'
        }],
        /*秒杀数据*/
        presaleList: [{
          id: 0,
          url: 'pages/plus/presale/list',
          name: '预售',
          type: '营销'
        }],
        /*签到数据*/
        signinList: [{
          id: 0,
          url: 'pages/plus/signin/signin',
          name: '签到',
          type: '营销'
        }],
        /*积分商城数据*/
        pointsList: [{
          id: 0,
          url: 'pages/plus/points/list/list',
          name: '积分商城',
          type: '营销'
        }],
        /*拼团*/
        assembleList: [{
          id: 0,
          url: 'pages/plus/assemble/list/list',
          name: '拼团',
          type: '营销'
        }],
        /*砍价*/
        bargainList: [{
          id: 0,
          url: 'pages/plus/bargain/list/list',
          name: '砍价',
          type: '营销'
        }],
        /*领券中心*/
        couponList: [{
          id: 0,
          url: 'pages/coupon/coupon',
          name: '领券中心',
          type: '营销'
        }],
        /*幸运转盘*/
        lotteryList: [{
          id: 0,
          url: 'pages/plus/lottery/lottery',
          name: '幸运转盘',
          type: '营销'
        }
      ],
      // 万能表单
      tableList: [],
      previewList: [
        {
          id: 0,
          url: 'pages/plus/preview/list',
          name: '预告',
          type: '营销'
        }
      ]
    };
  },
  watch: {
    activeTab: function(n, o) {
      let self = this;
      self.pages = [];
      if (n != o) {
        if (n == 'signin') {
          self.pages = self.signinList;
        } else if (n == 'points') {
          self.pages = self.pointsList;
        } else if (n == 'presale') {
          self.pages = self.presaleList;
        } else if (n == 'seckill') {
          self.pages = self.seckillList;
        } else if (n == 'assemble') {
          self.pages = self.assembleList;
        } else if (n == 'bargain') {
          self.pages = self.bargainList;
        } else if (n == 'coupon') {
          self.pages = self.couponList;
        } else if (n == 'lottery') {
          self.pages = self.lotteryList;
        } else if (n == 'table') {
          self.pages = self.tableList;
        } else if (n == 'preview') {
          self.pages = self.previewList;
        }
        self.autoSend();
      }
    }
  },
  created() {
    this.pages = this.signinList;
    this.getData();
    this.autoSend();
  },
  methods: {
    /*获取数据*/
    getData() {
      let self = this;
      LinkApi.getList(
        {
          activeName: self.activeTab
        },
        true
      )
        .then(res => {
          self.tableList = res.data.tableList;
        })
        .catch(error => {});
    },
    /*自动发送*/
    autoSend(){
      if (this.pages.length > 0) {
        this.activePage = this.pages[0];
        this.changeFunc();
      }
    },
    /*选中的值*/
    changeFunc(e) {
      this.$emit('changeData', this.activePage);
    }
  }
};
</script>
<style></style>
supplier_vue/src/components/setlink/part/Menu.vue
New file
@@ -0,0 +1,165 @@
<template>
  <!--
        作者:luoyiming
        时间:2020-06-08
        描述:超链接选择-页面
    -->
    <el-select v-model="activePage" placeholder="请选择" class="percent-w100" @change="changeFunc" value-key="url">
        <el-option v-for="item in pages" :key="item.url" :value-key="item.name" :label="item.name" :value="item"></el-option>
    </el-select>
</template>
<script>
    export default{
        data(){
            return {
                /*页面数据*/
                pages: [
                    {
                        url: '/pages/user/address/address',
                        name: '收货地址',
                        type: '菜单'
                    },
                    {
                        url: '/pages/coupon/coupon',
                        name: '领券中心',
                        type: '菜单'
                    },
                    {
                        url: '/pages/user/my-coupon/my-coupon',
                        name: '我的优惠券',
                        type: '菜单',
                    },
                    {
                        url: '/pages/agent/index/index',
                        name: '分销中心',
                        type: '菜单',
                    },
                    {
                        url: '/pages2/team/index',
                        name: '团队分红',
                        type: '菜单',
                    },
                    {
                        url: '/pages2/delivery/index',
                        name: '配送点',
                        type: '菜单',
                    },
                    {
                        url: '/pages2/deliveryclerk/index',
                        name: '配送员',
                        type: '菜单',
                    },
                    {
                        url: '/pages/user/my-bargain/my-bargain',
                        name: '我的砍价',
                        type: '菜单',
                    },
                    {
                        url: '/pages/user/my_shop/my_shop',
                        name: '我的店铺',
                        type: '菜单',
                    },
                    {
                        url: '/pages/shop/application_status',
                        name: '我的店铺',
                        type: '菜单',
                    },
                    {
                        url: '/pages/shop/register',
                        name: '入驻店铺',
                        type: '菜单',
                    }, {
                        url: '/pages/user/my_attention/my_attention',
                        name: '我的收藏',
                        type: '菜单',
                    }, {
                        url: '/pages/user/my_collect/my_collect',
                        name: '我的关注',
                        type: '菜单',
                    }, {
                        url: '/pages/plus/signin/signin',
                        name: '签到有礼',
                        type: '菜单',
                    }, {
                        url: '/pages/plus/task/index',
                        name: '任务中心',
                        type: '菜单',
                    }, {
                        url: '/pages/user/set/set',
                        name: '设置',
                        type: '菜单',
                    }, {
                        url: 'scanQrcode',
                        name: '扫一扫',
                        type: '菜单',
                    }, {
                        url: '/pages2/regactivity/index/index',
                        name: '活动报名',
                        type: '菜单',
                    }, {
                        url: '/pages2/ticket/index/index',
                        name: '凭证上传',
                        type: '菜单',
                    }, {
                        url: '/pages/user/card/list',
                        name: '会员卡',
                        type: '菜单',
                    }, {
                      url: '/pages/plus/business/list',
                      name: '名片列表',
                      type: '菜单',
                  }, {
                      url: '/pages/plus/business/index',
                      name: '我的名片',
                      type: '菜单',
                    }, {
                      url: '/pages/plus/business/add',
                      name: '添加名片',
                      type: '菜单',
                    },
                    {
                        url: 'pages/user/my_activity/index',
                        name: '连盟活动',
                        type: '页面',
                    },
                    {
                        url: 'pages2/bonus/index/index',
                        name: '超级分红',
                        type: '菜单',
                    },
                    {
                        url: 'pages/plus/vip/index',
                        name: 'VIP专区',
                        type: '菜单',
                    },
                    {
                        url: 'pages3/release/demandindex/index',
                        name: '需求方',
                        type: '菜单',
                    },
                    {
                        url: 'pages3/release/supplyindex/index',
                        name: '供应方',
                        type: '菜单',
                    }
                    ],
                /*选中的值*/
                activePage: '收货地址'
            }
        },
        created() {
          /*初始化*/
          this.changeFunc(this.pages[0]);
        },
        methods: {
            /*选中的值*/
            changeFunc(e){
                this.$emit('changeData', e);
            }
        }
    }
</script>
<style>
</style>
supplier_vue/src/components/setlink/part/Pages.vue
New file
@@ -0,0 +1,117 @@
<template>
  <!--
        作者:luoyiming
        时间:2020-06-08
        描述:超链接选择-页面
    -->
    <el-select v-model="activePage" placeholder="请选择" class="percent-w100" @change="changeFunc" value-key="url">
        <el-option v-for="item in pages" :key="item.url" :value-key="item.name" :label="item.name" :value="item"></el-option>
    </el-select>
</template>
<script>
    export default{
        data(){
            return {
                /*页面数据*/
                pages: [
                    {
                        url: 'pages/index/index',
                        name: '首页',
                        type: '页面'
                    },
                    {
                        url: 'pages/product/category',
                        name: '分类',
                        type: '页面'
                    },
                    {
                        url: 'pages/article/list/list',
                        name: '文章首页',
                        type: '页面',
                    },
                    {
                        url: 'pages/shop/shop_list',
                        name: '店铺',
                        type: '页面',
                    },
                    {
                        url: 'pages/shop/shop_list?is_takeout=1',
                        name: '外卖店铺',
                        type: '页面',
                    },
                    {
                        url: 'pages/order/myorder',
                        name: '订单',
                        type: '页面',
                    },
                    {
                        url: 'pages/cart/cart',
                        name: '购物车',
                        type: '页面',
                    },
                    {
                        url: 'pages/tabBar/user/index',
                        name: '我的',
                        type: '页面',
                    },
                    {
                        url: 'pages2/goodstore/store',
                        name: '好店',
                        type: '页面',
                    },
                    {
                        url: 'pages2/goodcoupon/coupon',
                        name: '好券',
                        type: '页面',
                    },
                    {
                        url: 'pages/user/register/register',
                        name: '注册',
                        type: '页面',
                    },
                    {
                        url: 'pages/shop/register',
                        name: '商户入驻',
                        type: '页面',
                    },
                    {
                        url: 'pages/branch/branch/index/index',
                        name: '分会列表',
                        type: '页面',
                    },
                    {
                        url: 'pages/branch/activity/index/index',
                        name: '连盟活动',
                        type: '页面',
                    },
                    {
                        url: 'pages2/bonus/index/index',
                        name: '超级分红',
                        type: '页面',
                    },
                    {
                        url: 'pages/plus/vip/index',
                        name: 'VIP专区',
                        type: '页面',
                    }
                ],
                /*选中的值*/
                activePage: '首页'
            }
        },
        created() {
          /*初始化*/
          this.changeFunc(this.pages[0]);
        },
        methods: {
            /*选中的值*/
            changeFunc(e){
                this.$emit('changeData', e);
            }
        }
    }
</script>
<style>
</style>
supplier_vue/src/components/setlink/part/SmallProgram.vue
New file
@@ -0,0 +1,39 @@
<template>
  <el-form label-width="80px" :model="formmodel">
    <el-form-item label="appid "><el-input v-model="formmodel.name" @change="changeFunc"></el-input></el-form-item>
    <el-form-item label="页面路径 "><el-input v-model="formmodel.url" @change="changeFunc"></el-input></el-form-item>
    <el-form-item label="">
      <p>注意一:同一个小程序链接其他小程序,最多只能链接10个,超过将不生效</p>
      <p>注意二:不能填写自身小程序appid</p>
      <p>注意三:小程序链接留空默认跳到小程序首页</p>
    </el-form-item>
  </el-form>
</template>
<script>
  export default{
    data(){
      return {
        /*form模型*/
        formmodel: {
          name:'',
          url:''
        }
      }
    },
    methods:{
      /*选中的值*/
      changeFunc(){
        let obj={};
        let self = this;
        obj.name = self.formmodel.name;
        obj.url = self.formmodel.url;
        obj.type = '小程序';
        this.$emit('changeData',obj);
      }
    }
  }
</script>
<style>
</style>
supplier_vue/src/components/setlink/part/Store.vue
New file
@@ -0,0 +1,146 @@
<template>
  <!--
        作者:luoyiming
        时间:2020-06-08
        描述:超链接选择-文章
    -->
  <div class="article-box">
    <!--搜索表单-->
    <div class="common-seach-wrap">
      <el-form size="small" :inline="true" :model="searchForm" class="demo-form-inline">
        <el-form-item label="门店名称"><el-input size="small" v-model="searchForm.store_name" placeholder="请输入门店名称"></el-input></el-form-item>
        <el-form-item>
            <el-button size="small" icon="el-icon-search" @click="onSubmit">查询</el-button>
        </el-form-item>
        <el-form-item>
          <el-button size="small" icon="el-icon-notebook-2" @click="chooseList">选择好店列表</el-button>
        </el-form-item>
      </el-form>
    </div>
    <!--内容-->
    <div class="article-content">
      <div class="table-wrap">
        <el-table size="mini" :data="tableData" border style="width: 100%">
          <el-table-column prop="store_name" label="门店名称"></el-table-column>
          <el-table-column prop="supplier.name" label="所属商户" width="200"></el-table-column>
          <el-table-column label="操作" width="80">
            <template slot-scope="scope">
              <el-button size="mini" @click="changeFunc(scope.row)">选择</el-button>
            </template>
          </el-table-column>
        </el-table>
      </div>
      <!--分页-->
      <div class="pagination">
        <el-pagination
          @size-change="handleSizeChange"
          @current-change="handleCurrentChange"
          background
          :current-page="curPage"
          :page-size="pageSize"
          layout="total, prev, pager, next, jumper"
          :total="totalDataNumber"
        ></el-pagination>
      </div>
    </div>
  </div>
</template>
<script>
import StoreApi from '@/api/store.js';
export default {
  data() {
    return {
      /*tab切换选择中值*/
      activeTab: 'second',
      /*一页多少条*/
      pageSize: 5,
      /*一共多少条数据*/
      totalDataNumber: 0,
      /*当前是第几页*/
      curPage: 1,
      /*是否加载完成*/
      loading: true,
      /*产品数据表*/
      tableData: [],
      /*选中的值*/
      activePage: {},
      /*搜索表单对象*/
      searchForm: {
        store_name: ''
      },
    };
  },
  created() {
    this.chooseList();
    /*获取列表*/
    this.getData();
  },
  watch: {},
  methods: {
    /*选择第几页*/
    handleCurrentChange(val) {
      let self = this;
      self.curPage = val;
      self.getData();
    },
    /*每页多少条*/
    handleSizeChange(val) {
      this.pageSize = val;
      this.curPage = 1;
      this.getData();
    },
    /*获取文章列表*/
    getData() {
      let self = this;
      self.loading = true;
      let Params = {};
      Params.page = self.curPage;
      Params.list_rows = self.pageSize;
      Params.store_name = self.searchForm.store_name;
      StoreApi.shoplist(Params, true)
        .then(data => {
          self.loading = false;
          self.tableData = data.data.list.data;
          self.totalDataNumber = data.data.list.total;
        })
        .catch(error => {
          console.log(error);
        });
    },
    /*搜索查询*/
    onSubmit() {
      this.curPage=0;
      this.getData();
    },
    /*选中的值*/
    changeFunc(e) {
      let obj={};
      obj.name = e.store_name;
      obj.url = 'pages2/goodstore/detail?store_id=' + e.store_id;
      obj.type = '好店';
      this.$emit('changeData',obj);
    },
    /*选择列表*/
    chooseList(){
      let obj={};
      obj.name = '好店列表';
      obj.url = 'pages2/goodstore/store';
      obj.type = '好店';
      this.$emit('changeData',obj);
    }
  }
};
</script>
<style></style>
supplier_vue/src/views/page/page/add.vue
New file
@@ -0,0 +1,137 @@
<template>
  <!--
      作者:wangxw
      时间:2020-06-10
      描述:页面-页面列表-添加页面
  -->
  <div v-loading="loading" class="diy-container clearfix">
    <!--类别选择-->
    <div class="diy-menu"><Type v-if="!loading" :defaultData="defaultData"></Type></div>
    <!--手机diy容器-->
    <div class="diy-phone"><Model v-if="!loading" ref="model" :form="form" :defaultData="defaultData" :diyData="diyData"></Model></div>
    <!--参数设置-->
    <div class="diy-info"><Params v-if="!loading" :form="form" :defaultData="defaultData" :diyData="diyData"></Params></div>
    <!--提交-->
    <div class="common-button-wrapper">
      <el-button  size="small" type="info" @click="gotoBack">返回上一页</el-button>
      <el-button size="small" type="primary" @click="Submit()" :loading="loading">保存</el-button>
    </div>
  </div>
</template>
<script>
import {deepClone} from '@/utils/base.js'
import PageApi from '@/api/page.js';
import Type from './diy/Type.vue';
import Model from './diy/Model.vue';
import Params from './diy/Params.vue';
export default {
  components: {
    /*组件类别*/
    Type,
    /*组件信息*/
    Model,
    /*参数信息*/
    Params
  },
  data() {
    return {
      /*是否正在加载*/
      loading: true,
      /*默认数据*/
      defaultData: {},
      /*组件数据列表*/
      diyData: {
        items: []
      },
      opts: {},
      /*表单对象*/
      form: {
        umeditor: {},
        /*当前选中*/
        curItem: {},
        /*当前选中的元素(下标)*/
        selectedIndex: -1
      }
    };
  },
  created() {
    /*获取列表*/
    this.getData();
  },
  methods: {
    /*获取初始化数据*/
    getData() {
      let self = this;
      PageApi.toAddPage({}, true)
        .then(res => {
          self.defaultData = res.data.defaultData;
          self.diyData = res.data.jsonData;
          self.form.curItem=self.diyData.page;
          self.opts = res.data.opts;
          self.loading = false;
        })
        .catch(error => {
          self.loading = false;
        });
    },
    /**
     * 新增Diy组件
     * @param key
     */
    onAddItem: function(key) {
      // 复制默认diy组件数据
      let item = deepClone(this.defaultData[key]);
      this.diyData.items.push(item);
      // 编辑当前选中的元素
      this.$refs.model.onEditer(this.diyData.items.length - 1);
    },
    /*添加页面*/
    Submit() {
      let self = this;
      let params = self.diyData;
      if (params.items.length < 1) {
        self.$message({
          message: '至少要选择一个组件',
          type: 'warning'
        });
        return;
      }
      self.loading = true;
      PageApi.addPage(
        {
          params: JSON.stringify(params)
        },
        true
      )
        .then(data => {
          self.loading = false;
          self.$message({
            message: '恭喜你,添加成功',
            type: 'success'
          });
          self.gotoBack();
        })
        .catch(error => {
          self.loading = false;
        });
    },
    /*返回上一页面*/
    gotoBack(){
      this.$router.back(-1);
    }
  }
};
</script>
<style lang="scss">
@import '@/styles/page/diy.scss';
</style>
supplier_vue/src/views/page/page/addpage.vue
New file
@@ -0,0 +1,136 @@
<template>
  <!--
      作者:wangxw
      时间:2020-06-10
      描述:页面-首页
  -->
  <div v-loading="loading" class="diy-container clearfix">
    <!--类别选择-->
    <div class="diy-menu"><Type v-if="!loading" :defaultData="defaultData"></Type></div>
    <!--手机diy容器-->
    <div class="diy-phone"><Model v-if="!loading" ref="model" :form="form" :defaultData="defaultData" :diyData="diyData"></Model></div>
    <!--参数设置-->
    <div class="diy-info"><Params v-if="!loading" :form="form" :defaultData="defaultData" :diyData="diyData"></Params></div>
    <!--提交-->
    <div class="common-button-wrapper">
      <el-button  size="small" type="info" @click="gotoBack">返回上一页</el-button>
      <el-button size="small" type="primary" @click="Submit()" :loading="loading">保存</el-button>
    </div>
  </div>
</template>
<script>
import {deepClone} from '@/utils/base.js'
import PageApi from '@/api/page.js';
import Type from './diy/Type.vue';
import Model from './diy/Model.vue';
import Params from './diy/Params.vue';
export default {
  components: {
    /*组件类别*/
    Type,
    /*组件信息*/
    Model,
    /*参数信息*/
    Params
  },
  data() {
    return {
      /*是否正在加载*/
      loading: true,
      /*默认数据*/
      defaultData: {},
      /*组件数据列表*/
      diyData: {
        items: []
      },
      opts: {},
      /*表单对象*/
      form: {
        umeditor: {},
        /*当前选中*/
        curItem: {},
        /*当前选中的元素(下标)*/
        selectedIndex: -1
      }
    };
  },
  created() {
    /*获取列表*/
    this.getData();
  },
  methods: {
    /*获取列表*/
    getData() {
      let self = this;
      console.log(1)
      PageApi.getHome({}, true)
        .then(res => {
          console.log(res)
          self.defaultData = res.data.defaultData;
          self.diyData = res.data.jsonData;
          self.form.curItem=self.diyData.page;
          self.opts = res.data.opts;
          self.loading = false;
        })
        .catch(error => {
          self.loading = false;
        });
    },
   /*新增Diy组件*/
   onAddItem: function(key) {
     // 复制默认diy组件数据
     let item = deepClone(this.defaultData[key]),cur_index=0;
     if(this.form.selectedIndex<0){
       cur_index=0;
       this.diyData.items.unshift(item);
     }else{
       cur_index=this.form.selectedIndex + 1;
        this.diyData.items.splice(cur_index,0,item);
     }
     // 编辑当前选中的元素
     this.$refs.model.onEditer(cur_index);
   },
    /*上架*/
    Submit() {
      let self = this;
      self.loading = true;
      let params = self.diyData;
      let page_id = self.page_id;
      PageApi.addhome(
        {
          params: JSON.stringify(params),
          page_id: page_id
        },
        true
      )
        .then(data => {
          self.loading = false;
          self.$message({
            message: '恭喜你,修改成功',
            type: 'success'
          });
          self.getData();
          self.form.selectedIndex= -1;
        })
        .catch(error => {
          self.loading = false;
        });
    },
    /*返回上一页面*/
    gotoBack(){
      this.$router.back(-1);
    }
  }
};
</script>
<style lang="scss">
@import '@/styles/page/diy.scss';
</style>
supplier_vue/src/views/page/page/bottom/Edit.vue
New file
@@ -0,0 +1,133 @@
<template>
  <!--
        作者:wangxw
        时间:2019-10-26
        描述:产品分类-修改
    -->
  <el-dialog title="修改导航" :visible.sync="dialogVisible" @close="dialogFormVisible" :close-on-click-modal="false"
    :close-on-press-escape="false">
    <el-form size="small" :model="form" ref="form">
      <el-form-item label="名称" prop="text" :label-width="formLabelWidth">
        <el-input v-model="form.text" autocomplete="off"></el-input>
      </el-form-item>
      <el-form-item label="选中图标" prop="selectedIconPath" :label-width="formLabelWidth">
        <el-row>
          <el-button type="primary" @click="openUpload(1)">选择图片</el-button>
          <div v-if="form.selectedIconPath!=''" class="img">
            <img :src="form.selectedIconPath" width="36" height="36" />
          </div>
        </el-row>
      </el-form-item>
      <el-form-item label="未选中图标" prop="iconPath" :label-width="formLabelWidth">
        <el-row>
          <el-button type="primary" @click="openUpload(2)">选择图片</el-button>
          <div v-if="form.iconPath!=''" class="img">
            <img :src="form.iconPath" width="36" height="36" />
          </div>
        </el-row>
      </el-form-item>
    </el-form>
    <div slot="footer" class="dialog-footer">
      <el-button @click="dialogFormVisible(false)">取 消</el-button>
      <el-button type="primary" @click="submit" :loading="loading">确 定</el-button>
    </div>
    <!--上传图片组件-->
    <Upload v-if="isupload" :isupload="isupload" @returnImgs="returnImgsFunc">上传图片</Upload>
  </el-dialog>
</template>
<script>
  import PageApi from '@/api/page.js';
  import Upload from '@/components/file/Upload';
  export default {
    components: {
      Upload
    },
    data() {
      return {
        form: {
          text: '',
          iconPath: '',
          selectedIconPath: ''
        },
        /*左边长度*/
        formLabelWidth: '120px',
        /*是否显示*/
        dialogVisible: false,
        loading: false,
        /*是否上传图片*/
        isupload: false,
        // 上传类型,1选中 2未选中
        upload_type: 1
      };
    },
    props: ['open_edit', 'editform'],
    created() {
      this.dialogVisible = this.open_edit;
      this.form.text = this.editform.text;
      this.form.iconPath = this.editform.iconPath;
      this.form.selectedIconPath = this.editform.selectedIconPath;
    },
    methods: {
      /*修改用户*/
      submit() {
        let self = this;
        let params = self.form;
        params.index = self.editform.index;
        params.type = 'image';
        self.$refs.form.validate((valid) => {
          if (valid) {
            self.loading = true;
            PageApi.editTabbar(params, true).then(data => {
              self.loading = false;
              self.$message({
                message: '修改成功',
                type: 'success'
              });
              self.dialogFormVisible(true);
            }).catch(error => {
              self.loading = false;
            });
          }
        });
      },
      /*关闭弹窗*/
      dialogFormVisible(e) {
        if (e) {
          this.$emit('closeDialog', {
            type: 'success',
            openDialog: false
          })
        } else {
          this.$emit('closeDialog', {
            type: 'error',
            openDialog: false
          })
        }
      },
      /*上传*/
      openUpload(e) {
        this.upload_type = e;
        this.isupload = true;
      },
      /*获取图片*/
      returnImgsFunc(e) {
        if (e != null && e.length > 0) {
          if(this.upload_type == 1){
            this.form.selectedIconPath = e[0].file_path;
          }else{
            this.form.iconPath = e[0].file_path;
          }
        }
        this.isupload = false;
      },
    }
  };
</script>
<style>
  .img {
    margin-top: 10px;
  }
</style>
supplier_vue/src/views/page/page/bottomnav.vue
New file
@@ -0,0 +1,332 @@
<template>
  <!--
        作者:wangxw
        时间:2019-05-05
        描述:分类模板
    -->
  <div class="d-s-s pb50">
    <!--分类不同样式展示-->
    <div class="flex-1 mr30">
      <div class="model-container">
        <div class="img-box p10" :style="'backgroundColor:'+formData.backgroundColor+';'">
          <div class="d-a-c">
            <div v-for="(item,index) in formData.list" :key="index" class="d-c d-c-c" @mouseenter="mouseenter"
              @mouseleave="mouseleave">
              <div v-if="formData.type != 2">
                <img class="nav_img" v-img-url="index==0?item.selectedIconPath:item.iconPath" alt="">
              </div>
              <div v-if="formData.type != 1"
                :style="index==0?'color:'+formData.textHoverColor+';':'color:'+formData.textColor+';'">{{item.text}}
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
    <!--图片展示参数-->
    <div class="param-container">
      <div class="common-form"><span>展示设置</span></div>
      <el-form size="small" :model="formData" label-width="150px">
        <el-form-item label="是否开启自定义:">
          <el-radio-group v-model="formData.is_auto">
            <el-radio label="1">开启</el-radio>
            <el-radio label="0">关闭</el-radio>
          </el-radio-group>
        </el-form-item>
        <el-form-item label="导航类型:">
          <el-radio-group v-model="formData.type">
            <el-radio label="0">图文</el-radio>
            <el-radio label="1">图片</el-radio>
            <el-radio label="2">文字</el-radio>
          </el-radio-group>
        </el-form-item>
        <el-form-item label="背景颜色:">
          <div class="d-s-c">
            <el-color-picker v-model="formData.backgroundColor"></el-color-picker>
            <el-button type="button" style="margin-left: 10px;"
              @click.stop="onEditorResetColor(formData, 'backgroundColor', '#ffffff')">重置</el-button>
          </div>
        </el-form-item>
        <el-form-item label="文字颜色:">
          <div class="d-s-c">
            <el-color-picker v-model="formData.textColor"></el-color-picker>
            <el-button type="button" style="margin-left: 10px;"
              @click.stop="onEditorResetColor(formData, 'textColor', '#ffffff')">重置</el-button>
          </div>
        </el-form-item>
        <el-form-item label="选中颜色:">
          <div class="d-s-c">
            <el-color-picker v-model="formData.textHoverColor"></el-color-picker>
            <el-button type="button" style="margin-left: 10px;"
              @click.stop="onEditorResetColor(formData, 'textHoverColor', '#ffffff')">重置</el-button>
          </div>
        </el-form-item>
        <el-form-item :label="navBar.text+':'" :key="index" v-for="(navBar, index) in formData.list">
          <div class="param-img-item">
            <div class="d-e-c"><i class="el-icon-delete-solid" @click="onEditorDeleleData(index)"></i></div>
            <div class="d-a-c">
              <div class="icon">未选中:
                <img v-img-url="navBar.iconPath" alt="" @click="onEditorSelectImage(navBar, 'iconPath')">
              </div>
              <div class="icon"> 已选中:
                <img v-img-url="navBar.selectedIconPath" alt=""
                  @click="onEditorSelectImage(navBar, 'selectedIconPath')">
              </div>
            </div>
          </div>
          <div class="d-s-c mb16">
            <div class="url-box flex-1 d-s-c">
              <span class="key-name">链接:</span>
              <el-input disabled v-model="navBar.link_url"></el-input>
            </div>
            <div class="url-box ml10">
              <el-button type="primary" @click="changeLink(index)">选择链接</el-button>
            </div>
          </div>
          <div class="url-box flex-1 d-s-c ">
            <span class="key-name">名称:</span>
            <el-input v-model="navBar.text"></el-input>
          </div>
        </el-form-item>
        <div class="d-c-c" v-if="formData.list.length<5">
          <el-button @click="onEditorAddData">添加一个</el-button>
        </div>
      </el-form>
    </div>
    <!--提交-->
    <div class="common-button-wrapper">
      <el-button size="small" type="primary" @click="Submit()">保存</el-button>
    </div>
    <!--上传图片-->
    <Upload v-if="isupload" :isupload="isupload" :config="{ total: 3 }" @returnImgs="returnImgsFunc"></Upload>
    <Setlink v-if="is_linkset" :is_linkset="is_linkset" @closeDialog="closeLinkset">选择链接</Setlink>
  </div>
</template>
<script>
  import PageApi from '@/api/page.js';
  import Upload from '@/components/file/Upload';
  import Setlink from '@/components/setlink/SetTab';
  export default {
    data() {
      return {
        /*是否上传图片*/
        isupload: false,
        /*表单数据对象*/
        formData: {
          /* 导航类型*/
          type: '0',
          is_auto:'0',
          /* 背景颜色*/
          backgroundColor: "#ffffff",
          textColor: '#333333',
          textHoverColor: 'red',
          /* 悬浮 */
          bulge: false,
          list: []
        },
        is_linkset: false,
        index: 0,
      };
    },
    components: {
      Upload,
      Setlink
    },
    created() {
      this.getData();
    },
    methods: {
      /*获取数据*/
      getData() {
        let self = this;
        PageApi.getbottomNav({}, true).then(res => {
          self.formData = res.data.vars.data;
        }).catch(error => {
          self.loading = false;
        });
      },
      /*提交*/
      Submit() {
        let self = this;
        self.loading = true;
        let Params = self.formData;
        if (Params.list.length <= 0 || !Params.list) {
          Params = {}
        }
        PageApi.editTabbar({
            data: Params
          }, true)
          .then(data => {
            self.loading = false;
            self.$message({
              message: '恭喜你,修改成功',
              type: 'success'
            });
            self.getData();
          })
          .catch(error => {
            self.loading = false;
          });
      },
      /*选择链接*/
      changeLink(index) {
        this.is_linkset = true;
        this.index = index;
      },
      /*获取链接并关闭弹窗*/
      closeLinkset(e) {
        this.is_linkset = false;
        this.formData.list[this.index].link_url = '/' + e.url;
        this.formData.list[this.index].text = e.name;
      },
      onEditorDeleleData: function(index) {
        let self = this;
        if (self.formData.list.length <= 1) {
          self.$message({
            message: '至少保留一个',
            type: 'error'
          });
          return false;
        }
        self.formData.list.splice(index, 1);
      },
      onEditorSelectImage: function(index, imgUrl) {
        this.isupload = true;
        this.imgModel = {
          index: index,
          imgUrl: imgUrl
        };
      },
      /*上传图片*/
      returnImgsFunc(e) {
        if (e != null) {
          this.imgModel.index[this.imgModel.imgUrl] = e[0]['file_path'];
        }
        this.isupload = false;
      },
      onEditorResetColor: function(holder, attribute, color) {
        holder[attribute] = color;
      },
      onEditorAddData: function() {
        let self = this;
        // 新增data数据
        if (self.formData.list) {
          if (self.formData.list.length >= 5) {
            self.$message({
              message: '最多添加5个',
              type: 'error'
            });
            return false;
          } else {
            let newDataItem = {
              iconPath: '',
              text: '',
              is_show: true,
              selectedIconPath: '',
              link: {
                wap_url: ''
              }
            };
            self.formData.list.push(newDataItem);
          }
        } else {
          let newDataItem = {
            iconPath: '',
            text: '',
            is_show: true,
            selectedIconPath: '',
            link: {
              wap_url: ''
            }
          };
          let list = [{
            ...newDataItem
          }];
          self.formData = {
            type: 0,
            backgroundColor: "",
            textColor: '',
            textHoverColor: '',
            bulge: false,
            list: []
          }
          self.formData.list = list;
        }
      },
      mouseenter(e) {
        e.target.childNodes[2].style.color = this.formData.textHoverColor;
      },
      mouseleave(e) {
        e.target.childNodes[2].style.color = this.formData.textColor;
      }
    }
  };
</script>
<style scoped="scoped">
  .model-container {
    width: 375px;
    height: calc(100vh - 150px);
    margin: 0 auto;
  }
  .mr30 {
    margin-right: 30px;
  }
  .model-container img {
    width: 100%;
  }
  .model-container .img-box {
    box-shadow: 0 0 16px 0 rgba(0, 0, 0, .1);
  }
  .param-container {
    width: 700px;
    padding: 20px;
    /* height: calc(100vh - 150px); */
    border: 1px solid #cccccc;
  }
  .icon img {
    width: 50px;
    height: 50px;
  }
  .nav_img {
    width: 30px !important;
    height: 30px;
  }
  .delete-box {
    z-index: 99;
    display: flex;
    justify-content: flex-end;
  }
  .param-img-item {
    border: 1px solid #CCCCCC;
    margin-bottom: 10px;
    padding: 30px 15px;
  }
  .param-img-item .el-icon-delete-solid {
    font-size: 16px;
    text-align: right;
    color: #999999;
  }
  .key-name {
    white-space: nowrap;
  }
</style>
supplier_vue/src/views/page/page/category.vue
New file
@@ -0,0 +1,111 @@
<template>
  <!--
        作者:wangxw
        时间:2019-05-05
        描述:分类模板
    -->
  <div class="d-s-s">
    <!--分类不同样式展示-->
    <div class="model-container">
      <div class="img-box">
        <el-image v-if="formData.category_style==10" :src="category_10" fit="fill"></el-image>
        <el-image v-if="formData.category_style==20" :src="category_20" fit="fill"></el-image>
        <el-image v-if="formData.category_style==30" :src="category_30" fit="fill"></el-image>
        <el-image v-if="formData.category_style==40" :src="category_40" fit="fill"></el-image>
      </div>
    </div>
    <!--图片展示参数-->
    <div class="param-container flex-1">
      <div class="common-form"><span>展示设置</span></div>
      <el-form size="small" :model="formData" label-width="100px">
        <el-form-item label="分类页样式:">
          <el-radio-group v-model="formData.category_style">
            <el-radio :label="10">一级分类(大图)</el-radio>
            <el-radio :label="20">一级分类(小图)</el-radio>
            <el-radio :label="40">一级分类(列表)</el-radio>
            <el-radio :label="30">二级分类</el-radio>
          </el-radio-group>
          <p class="gray9">建议:一级分类(大图)尺寸建议710*300,其它均为等比图片即可,如:240*240</p>
        </el-form-item>
        <el-form-item label="分享标题:"><el-input v-model="formData.share_title"></el-input></el-form-item>
      </el-form>
    </div>
    <!--提交-->
    <div class="common-button-wrapper"><el-button size="small" type="primary" @click="Submit()">保存</el-button></div>
  </div>
</template>
<script>
  import PageApi from '@/api/page.js';
  import category_10 from '@/assets/img/category_10.jpg';
  import category_20 from '@/assets/img/category_20.jpg';
  import category_30 from '@/assets/img/category_30.jpg';
  import category_40 from '@/assets/img/category_40.jpg';
export default {
  data() {
    return {
      /*表单数据对象*/
      formData: {
        category_style: null
      },
      /*展示样式*/
      category_10:category_10,
      category_20:category_20,
      category_30:category_30,
      category_40:category_40,
    };
  },
  created() {
    this.getData();
  },
  methods: {
    /*获取数据*/
    getData() {
      let self = this;
      PageApi.getCategory({}, true).then(res => {
        self.formData=res.data.model;
      }).catch(error => {
        self.loading = false;
      });
    },
    /*提交*/
    Submit() {
      let self = this;
      self.loading = true;
      let Params = self.formData;
      PageApi.postCategory(Params,true)
        .then(data => {
          self.loading = false;
          self.$message({
            message: '恭喜你,修改成功',
            type: 'success'
          });
          self.getData();
        })
        .catch(error => {
          self.loading = false;
        });
    }
  }
};
</script>
<style scoped="scoped">
.model-container {
  width: 300px;
  height: calc(100vh - 150px);
  margin-right: 30px;
}
.model-container img{width: 100%;}
.model-container .img-box{ box-shadow: 0 0 16px 0 rgba(0,0,0,.1);}
.param-container {
  padding: 20px;
  height: calc(100vh - 150px);
  border: 1px solid #cccccc;
}
</style>
supplier_vue/src/views/page/page/diy/Model.vue
New file
@@ -0,0 +1,313 @@
<template>
  <!--
        作者:luoyiming
        时间:2019-11-05
        描述:diy组件-模拟手机显示
    -->
  <div class="diy-phone-container">
    <!--顶部设置栏-->
    <div class="diy-phone-item" :class="{ active: form.selectedIndex < 0 }"><Setpages :diyData="diyData"></Setpages></div>
    <draggable class="wrapper" v-model="diyData.items" :options="{ animation: 120, filter: '.drag__nomove' }">
      <div class="diy-phone-item" :class="{ active: form.selectedIndex == index }" v-for="(item, index) in diyData.items" :key="item.id">
        <!-- 图片轮播 -->
        <template v-if="item.type == 'banner'">
          <Banner :item="item" :index="index" :selectedIndex="form.selectedIndex"></Banner>
        </template>
        <!-- 图片-->
        <template v-else-if="item.type == 'imageSingle'">
          <ImageSingle :item="item" :index="index" :selectedIndex="form.selectedIndex"></ImageSingle>
        </template>
        <!-- 橱窗-->
        <template v-else-if="item.type == 'window'">
          <Window :item="item" :index="index" :selectedIndex="form.selectedIndex"></Window>
        </template>
        <!-- 视频组-->
        <template v-else-if="item.type == 'video'">
          <Video :item="item" :index="index" :selectedIndex="form.selectedIndex"></Video>
        </template>
        <!--文章-->
        <template v-else-if="item.type == 'article'">
          <Article :item="item" :index="index" :selectedIndex="form.selectedIndex"></Article>
        </template>
        <!--头条快报-->
        <template v-else-if="item.type == 'special'">
          <Special :item="item" :index="index" :selectedIndex="form.selectedIndex"></Special>
        </template>
        <!--公告组-->
        <template v-else-if="item.type == 'notice'">
          <Notice :item="item" :index="index" :selectedIndex="form.selectedIndex"></Notice>
        </template>
        <!--导航组-->
        <template v-else-if="item.type == 'navBar'">
          <NavBar :item="item" :index="index" :selectedIndex="form.selectedIndex"></NavBar>
        </template>
        <!--商品组-->
        <template v-else-if="item.type == 'product'">
          <Product :item="item" :index="index" :selectedIndex="form.selectedIndex"></Product>
        </template>
        <!--优惠券-->
        <template v-else-if="item.type == 'coupon'">
          <Coupon :item="item" :index="index" :selectedIndex="form.selectedIndex"></Coupon>
        </template>
        <!--门店-->
        <template v-else-if="item.type == 'store'">
          <Store :item="item" :index="index" :selectedIndex="form.selectedIndex"></Store>
        </template>
        <!--客服-->
        <template v-else-if="item.type == 'service'">
          <Service :item="item" :index="index" :selectedIndex="form.selectedIndex"></Service>
        </template>
        <!--富文本-->
        <template v-else-if="item.type == 'richText'">
          <RichText :item="item" :index="index" :selectedIndex="form.selectedIndex"></RichText>
        </template>
        <!--辅助空白-->
        <template v-else-if="item.type == 'blank'">
          <Blank :item="item" :index="index" :selectedIndex="form.selectedIndex"></Blank>
        </template>
        <!--辅助线-->
        <template v-else-if="item.type == 'guide'">
          <Guide :item="item" :index="index" :selectedIndex="form.selectedIndex"></Guide>
        </template>
        <!--秒杀-->
        <template v-else-if="item.type == 'seckillProduct'">
          <Seckill :item="item" :index="index" :selectedIndex="form.selectedIndex"></Seckill>
        </template>
        <!--预告-->
        <template v-else-if="item.type == 'previewProduct'">
          <Preview :item="item" :index="index" :selectedIndex="form.selectedIndex"></Preview>
        </template>
        <!--拼团-->
        <template v-else-if="item.type == 'assembleProduct'">
          <assembleProduct :item="item" :index="index" :selectedIndex="form.selectedIndex"></assembleProduct>
        </template>
        <!--砍价-->
        <template v-else-if="item.type == 'bargainProduct'">
          <BargainProduct :item="item" :index="index" :selectedIndex="form.selectedIndex"></BargainProduct>
        </template>
        <!--直播-->
        <template v-else-if="item.type == 'live'">
          <Live :item="item" :index="index" :selectedIndex="form.selectedIndex"></Live>
        </template>
        <!--标题-->
        <template v-else-if="item.type == 'title'">
          <Title :item="item" :index="index" :selectedIndex="form.selectedIndex"></Title>
        </template>
        <!--导航组 by lyzflash-->
        <template v-else-if="item.type == 'button'">
          <Button :item="item" :index="index" :selectedIndex="form.selectedIndex"></Button>
        </template>
        <!--选项卡组 by lyzflash-->
        <template v-else-if="item.type == 'tab'">
          <Tab :item="item" :index="index" :selectedIndex="form.selectedIndex"></Tab>
        </template>
      </div>
    </draggable>
  </div>
</template>
<script>
import Setpages from './model/Setpages.vue';
import Banner from './model/Banner.vue';
import ImageSingle from './model/ImageSingle.vue';
import Window from './model/Window.vue';
import Video from './model/Video.vue';
import Article from './model/Article.vue';
import Special from './model/Special.vue';
import Notice from './model/Notice.vue';
import NavBar from './model/NavBar.vue';
import Product from './model/Product.vue';
import Coupon from './model/Coupon.vue';
import Store from './model/Store.vue';
import Service from './model/Service.vue';
import RichText from './model/RichText.vue';
import Blank from './model/Blank.vue';
import Guide from './model/Guide.vue';
import Seckill from './model/Seckill.vue';
import Preview from './model/Preview.vue';
import assembleProduct from './model/assembleProduct.vue';
import BargainProduct from './model/BargainProduct.vue';
import Live from './model/Live.vue';
import Title from './model/Title.vue';
import Button from './model/Button.vue'; // 按钮组 by lyzflash
import Tab from './model/Tab.vue'; // 选项卡组 by lyzflash
import draggable from 'vuedraggable';
export default {
  components: {
    /*顶部状态栏*/
    Setpages,
    /*图片轮播组件*/
    Banner,
    /*图片组件*/
    ImageSingle,
    /*图片橱窗*/
    Window,
    /*视频*/
    Video,
    /*文章*/
    Article,
    /*头条快报*/
    Special,
    /*公告组*/
    Notice,
    /*导航组*/
    NavBar,
    /*商品组*/
    Product,
    /*优惠券*/
    Coupon,
    /*门店*/
    Store,
    /*客服*/
    Service,
    /*富文本*/
    RichText,
    /*辅助空白*/
    Blank,
    /*辅助线*/
    Guide,
    /*拖动*/
    draggable,
    /*秒杀*/
    Seckill,
    /*拼团*/
    assembleProduct,
    /*砍价*/
    BargainProduct,
    /*直播*/
    Live,
    /*标题*/
    Title,
    Preview,
    /*按钮组 by lyzflash*/
    Button,
    /*选项卡组 by lyzflash*/
    Tab,
  },
  data() {
    return {};
  },
  props: {
    form: Object,
    defaultData: Object,
    diyData: Object
  },
  created() {},
  methods: {
    /*删除diy元素*/
    onDeleleItem: function(index) {
      let self = this;
      self
        .$confirm('确定要删除吗?', '提示', {
          type: 'warning'
        })
        .then(() => {
          self.diyData.items.splice(index, 1);
          self.form.selectedIndex = -1;
        });
    },
    /*编辑当前选中的Diy元素*/
    onEditer: function(index) {
      let self = this;
      // 记录当前选中元素的索引
      self.form.selectedIndex = index;
      // 当前选中的元素数据
      self.form.curItem = self.form.selectedIndex < 0 ? self.diyData.page : self.diyData.items[self.form.selectedIndex];
     // 注册编辑器事件
      //self.initEditor();
    },
    /* 注册编辑器事件*/
    initEditor: function() {
      let self = this;
      // 注册dom事件
      self.$nextTick(function() {
        // 销毁 umeditor 组件
        if (self.form.umeditor.hasOwnProperty('key')) {
          self.form.umeditor.destroy();
        }
        // 注册html组件
        self.editorHtmlComponent();
        // 富文本事件
        if (self.form.curItem.type === 'richText') {
          //self.onRichText(self.form.curItem);
        }
      });
    },
    /*编辑器事件:html组件*/
    editorHtmlComponent: function() {
      let self = this;
      var editor = self.$refs['diy-editor'];
      // 单/多选框
      //editor.find('input[type=checkbox], input[type=radio]').uCheck();
      // select组件
      // $editor.find('select').selected();
    }
  }
};
</script>
<style>
.diy-phone-container {
  position: relative;
  height: calc(100vh - 150px);
}
.diy-phone-container .wrapper {
  height:calc(100% - 90px) ;
  overflow-y: auto;
}
.diy-phone-container .phone-top {
  padding: 0 20px;
  border-radius: 18px 18px 0 0;
}
.diy-phone-container .phone-top .status-bar {
  height: 20px;
  display: flex;
  justify-content: space-between;
}
.diy-phone-container .phone-top .svg-icon {
  width: 20px;
  height: 20px;
  color: #333333;
}
.diy-phone-container .phone-top .navigation {
  height: 44px;
  line-height: 44px;
  text-align: center;
  font-size: 18px;
}
.diy-phone-container .diy-phone-item {
}
.diy-phone-container .diy-phone-item > div {
  position: relative;
  border: 2px solid #f1f1f2;
}
.diy-phone-container .diy-phone-item > div:hover,
.diy-phone-container .diy-phone-item.active > div {
  border: 2px dashed #3a8ee6;
}
.diy-phone-container .diy-phone-item .btn-edit-del {
  position: absolute;
  bottom: 0;
  right: 0;
  z-index: 10;
}
.diy-phone-container .diy-phone-item .btn-edit-del > div {
  width: 32px;
  height: 16px;
  line-height: 16px;
  display: inline-block;
  text-align: center;
  font-size: 10px;
  color: #fff;
  background: rgba(0, 0, 0, 0.4);
  margin-left: 2px;
  cursor: pointer;
}
.diy-phone-container img {
  width: 100%;
}
</style>
supplier_vue/src/views/page/page/diy/Params.vue
New file
@@ -0,0 +1,407 @@
<template>
  <!--
        作者:luoyiming
        时间:2020-06-20
        描述:diy组件-参数设置
    -->
  <div id="diy-editor" ref="diy-editor" class="diy-editor form-horizontal">
    <template v-show="diyData.items.length && form.curItem">
      <!--顶部设置-->
      <template v-if="form.curItem.type == 'page'">
        <Setpages :curItem="form.curItem"></Setpages>
      </template>
      <!--图片轮播-->
      <template v-if="form.curItem.type == 'banner'">
        <Banner :curItem="form.curItem" :selectedIndex="form.selectedIndex"></Banner>
      </template>
      <!--图片-->
      <template v-if="form.curItem.type == 'imageSingle'">
        <ImageSingle :curItem="form.curItem" :selectedIndex="form.selectedIndex"></ImageSingle>
      </template>
      <!--图片橱窗-->
      <template v-if="form.curItem.type == 'window'">
        <Window :curItem="form.curItem" :selectedIndex="form.selectedIndex"></Window>
      </template>
      <!--视频组件-->
      <template v-if="form.curItem.type == 'video'">
        <Video :curItem="form.curItem" :selectedIndex="form.selectedIndex"></Video>
      </template>
      <!--文章组件-->
      <template v-if="form.curItem.type == 'article'">
        <Article :curItem="form.curItem" :selectedIndex="form.selectedIndex"></Article>
      </template>
      <!--头条快报-->
      <template v-if="form.curItem.type == 'special'">
        <Special :curItem="form.curItem" :selectedIndex="form.selectedIndex"></Special>
      </template>
      <!--公告组-->
      <template v-if="form.curItem.type == 'notice'">
        <Notice :curItem="form.curItem" :selectedIndex="form.selectedIndex"></Notice>
      </template>
      <!--导航组-->
      <template v-if="form.curItem.type == 'navBar'">
        <NavBar :curItem="form.curItem" :selectedIndex="form.selectedIndex"></NavBar>
      </template>
      <!--商品组-->
      <template v-if="form.curItem.type == 'product'">
        <Product :curItem="form.curItem" :selectedIndex="form.selectedIndex"></Product>
      </template>
      <!--优惠券-->
      <template v-if="form.curItem.type == 'coupon'">
        <Coupon :curItem="form.curItem" :selectedIndex="form.selectedIndex"></Coupon>
      </template>
      <!--门店-->
      <template v-if="form.curItem.type == 'store'">
        <Store :curItem="form.curItem" :selectedIndex="form.selectedIndex"></Store>
      </template>
      <!--客服-->
      <template v-if="form.curItem.type == 'service'">
        <Service :curItem="form.curItem" :selectedIndex="form.selectedIndex"></Service>
      </template>
      <!--富文本-->
      <template v-if="form.curItem.type == 'richText'">
        <RichText :curItem="form.curItem" :selectedIndex="form.selectedIndex"></RichText>
      </template>
      <!--辅助空白-->
      <template v-if="form.curItem.type == 'blank'">
        <Blank :curItem="form.curItem" :selectedIndex="form.selectedIndex"></Blank>
      </template>
      <!--辅助线-->
      <template v-if="form.curItem.type == 'guide'">
        <Guide :curItem="form.curItem" :selectedIndex="form.selectedIndex"></Guide>
      </template>
      <!--秒杀-->
      <template v-if="form.curItem.type == 'seckillProduct'">
        <Seckill :curItem="form.curItem" :selectedIndex="form.selectedIndex"></Seckill>
      </template>
      <!--拼团-->
      <template v-if="form.curItem.type == 'assembleProduct'">
        <assembleProduct :curItem="form.curItem" :selectedIndex="form.selectedIndex"></assembleProduct>
      </template>
      <!--预告-->
      <template v-if="form.curItem.type == 'previewProduct'">
        <Preview :curItem="form.curItem" :selectedIndex="form.selectedIndex"></Preview>
      </template>
      <!--砍价-->
      <template v-if="form.curItem.type == 'bargainProduct'">
        <BargainProduct :curItem="form.curItem" :selectedIndex="form.selectedIndex"></BargainProduct>
      </template>
      <!--直播-->
      <template  v-if="form.curItem.type == 'live'">
        <Live :curItem="form.curItem" :selectedIndex="form.selectedIndex"></Live>
      </template>
      <!--标题-->
      <template  v-if="form.curItem.type == 'title'">
        <Title :curItem="form.curItem" :selectedIndex="form.selectedIndex"></Title>
      </template>
      <!--导航组 by lyzflash-->
      <template v-if="form.curItem.type == 'button'">
        <Button :curItem="form.curItem" :selectedIndex="form.selectedIndex"></Button>
      </template>
      <!--选项卡组 by lyzflash-->
      <template v-if="form.curItem.type == 'tab'">
        <Tab :curItem="form.curItem" :selectedIndex="form.selectedIndex"></Tab>
      </template>
    </template>
    <!--上传图片-->
    <Upload v-if="isupload" :isupload="isupload" :config="config" @returnImgs="returnImgsFunc"></Upload>
    <!--选择商品-->
    <ProductSelect :isproduct="isproduct" :excludeIds="excludeIds" :islist="islist"
      @closeDialog="closeProductDialogFunc($event)">产品列表弹出层</ProductSelect>
    <!--选择门店-->
    <StoreSelect :isstore="isstore" :islist="isstorelist"></StoreSelect>
  </div>
</template>
<script>
  import {
    deepClone
  } from '@/utils/base.js';
  import Setpages from './params/Setpages.vue';
  import Banner from './params/Banner.vue';
  import ImageSingle from './params/ImageSingle.vue';
  import Window from './params/Window.vue';
  import Video from './params/Video.vue';
  import Article from './params/Article.vue';
  import Special from './params/Special.vue';
  import Notice from './params/Notice.vue';
  import NavBar from './params/NavBar.vue';
  import Product from './params/Product.vue';
  import Coupon from './params/Coupon.vue';
  import Store from './params/Store.vue';
  import Service from './params/Service.vue';
  import RichText from './params/RichText.vue';
  import Blank from './params/Blank.vue';
  import Guide from './params/Guide.vue';
  import Seckill from './params/Seckill.vue';
  import Preview from './params/Preview.vue';
  import assembleProduct from './params/assembleProduct.vue';
  import BargainProduct from './params/BargainProduct.vue';
  import Live from './params/Live.vue';
  import Title from './params/Title.vue';
  import Upload from '@/components/file/Upload';
  import ProductSelect from '@/components/product/Product';
  import StoreSelect from '@/components/store/StoreSelect';
  import Button from './params/Button.vue'; // 按钮组
  import Tab from './params/Tab.vue'; // 选项卡组
export default {
  components: {
    /*顶部设置*/
    Setpages,
    /*图片轮播组件*/
    Banner,
    /*图片组件*/
    ImageSingle,
    /*图片橱窗*/
    Window,
    /*视频*/
    Video,
    /*文章*/
    Article,
    /*文章*/
    Special,
    /*公告组*/
    Notice,
    /*导航组*/
    NavBar,
    /*商品组*/
    Product,
    /*优惠券*/
    Coupon,
    /*门店*/
    Store,
    /*客服*/
    Service,
    /*富文本*/
    RichText,
    /*辅助空白*/
    Blank,
    /*辅助线*/
    Guide,
    /*秒杀*/
    Seckill,
    /*拼团*/
    assembleProduct,
    /*砍价*/
    BargainProduct,
    /*上传图片*/
    Upload,
    /*商品选择*/
    ProductSelect,
    /*门店选中*/
    StoreSelect,
    /*直播*/
    Live,
    /*标题*/
    Title,
    Preview,
    /*按钮组 by lyzflash*/
    Button,
    /*选项卡组 by lyzflash*/
    Tab,
  },
  data() {
    return {
      /*是否上传图片*/
      isupload: false,
      /*图片当前对象*/
      imgModel: null,
      /*是否打开产品弹出层*/
      isproduct: false,
      /*商品需要去重的*/
      excludeIds: [],
      /*是否多选*/
      islist: false,
      /*是否显示门店选中*/
      isstore: false,
      /*门店是否多选*/
      isstorelist: false,
      // 上传文件类型image图片,video视频 by lyzflash
      file_type: 'image',
      /*视频当前对象 by lyzflash*/
      videoModel: null,
      config: {},
    };
  },
  props: ['form', 'defaultData', 'diyData', 'opts'],
  created() {},
  methods: {
    /**
     * 编辑器:添加data元素
     */
    onEditorAddData: function() {
      let self = this;
      // 新增data数据
      var newDataItem = deepClone(self.defaultData[self.form.curItem.type].data[0]);
      self.form.curItem.data.push(newDataItem);
    },
    /**
     * 编辑器:重置颜色
     * @param holder
     * @param attribute
     * @param color
     */
    onEditorResetColor: function(holder, attribute, color) {
      holder[attribute] = color;
    },
    /**
     * 编辑器:删除data元素
     * @param index
     * @param selectedIndex
     */
    onEditorDeleleData: function(index, selectedIndex) {
      let self = this;
      if (self.diyData.items[selectedIndex].data.length <= 1) {
        self.$message({
          message: '至少保留一个',
          type: 'error'
        });
        return false;
      }
      self.diyData.items[selectedIndex].data.splice(index, 1);
    },
    /**
     * 编辑器:选择图片
     * @param source
     * @param index
     */
    onEditorSelectImage: function(index, imgUrl) {
      this.isupload = true;
      this.file_type = 'image';
      this.config = {
        total: 3,
        file_type: 'image'
      };
      this.imgModel = {
        index: index,
        imgUrl: imgUrl
      };
    },
    /**
     * 编辑器:选择视频
     * @param source
     * @param index
     */
     onEditorSelectVideo: function(index, videoUrl) {
      this.isupload = true;
      this.file_type = 'video';
      this.config = {
        total: 1,
        file_type: 'video'
      };
      this.videoModel = {
        index: index,
        videoUrl: videoUrl
      };
    },
    /*上传图片*/
    returnImgsFunc(e) {
      if (e != null) {
        if (this.file_type == 'image') {
          this.imgModel.index[this.imgModel.imgUrl] = e[0]['file_path'];
        } else if (this.file_type == 'video') {
          this.videoModel.index[this.videoModel.videoUrl] = e[0]['file_path'];
        }
      }
      this.isupload = false;
    },
    /*商品选择列表弹出层*/
    openProduct(list, islist) {
      let arr = [];
      list.forEach(item => {
        arr.push(item.product_id);
      });
      this.excludeIds = arr;
      if (islist && typeof islist != 'undefined') {
        this.islist = true;
      } else {
        this.islist = false;
      }
      this.isproduct = true;
    },
      /*商品选择关闭弹窗*/
      closeProductDialogFunc(e) {
        if (this.form.curItem == null) {
          return;
        }
        this.isproduct = false;
        if (e.type == 'success') {
          if (this.form.curItem.data.length > 0 && this.form.curItem.data[0].is_default) {
            this.form.curItem.data = [];
          }
          if (this.islist) {
            this.form.curItem.data = this.form.curItem.data.concat(e.params);
          } else {
            this.form.curItem.data.push(e.params);
          }
        }
      },
    /*商品选择列表弹出层*/
    openStore(list, islist) {
      let arr = [];
      list.forEach(item => {
        arr.push(item.store_id);
      });
      this.excludeIds = arr;
      if (islist && typeof islist != 'undefined') {
        this.isstorelist = true;
      } else {
        this.isstorelist = false;
      }
      this.isstore = true;
    }
  }
};
</script>
<style>
.param-img-item {
  position: relative;
  padding: 10px;
  margin-bottom: 10px;
  border: 1px solid #eeeeee;
  line-height: 20px;
}
.param-img-item .delete-box {
  position: absolute;
  top: 10px;
  right: 10px;
  font-size: 20px;
  cursor: pointer;
  color: #cccccc;
}
.param-img-item .delete-box:hover {
  color: rgb(255, 51, 0);
}
.param-img-item .pic img {
  width: 200px;
  height: 100px;
  margin: 0 auto;
}
.param-img-item .icon img {
  width: 100px;
  height: 100px;
  margin: 0 auto;
}
.param-img-item .url-box {
  display: flex;
  justify-content: flex-start;
  line-height: 40px;
}
.param-img-item .url-box .key-name {
  display: block;
  width: 80px;
}
.param-img-item .url-box .el-input {
  flex: 1;
}
</style>
supplier_vue/src/views/page/page/diy/Preview.vue
New file
@@ -0,0 +1,322 @@
<template>
  <!--
        作者:luoyiming
        时间:2019-11-05
        描述:diy组件-模拟手机显示
    -->
  <div class="diy-phone-container">
    <!--顶部设置栏-->
    <div class="diy-phone-item"><Setpages :diyData="diyData"></Setpages></div>
    <div class="wrapper">
      <div class="diy-phone-item" v-for="(item, index) in diyData.items" :key="item.id">
        <!-- 搜索栏 -->
        <template v-if="item.type == 'search'">
          <Search :item="item" :index="index" :selectedIndex="form.selectedIndex"></Search>
        </template>
        <!-- 图片轮播 -->
        <template v-else-if="item.type == 'banner'">
          <Banner :item="item" :index="index" :selectedIndex="form.selectedIndex"></Banner>
        </template>
        <!-- 图片-->
        <template v-else-if="item.type == 'imageSingle'">
          <ImageSingle :item="item" :index="index" :selectedIndex="form.selectedIndex"></ImageSingle>
        </template>
        <!-- 橱窗-->
        <template v-else-if="item.type == 'window'">
          <Window :item="item" :index="index" :selectedIndex="form.selectedIndex"></Window>
        </template>
        <!-- 视频组-->
        <template v-else-if="item.type == 'video'">
          <Video :item="item" :index="index" :selectedIndex="form.selectedIndex"></Video>
        </template>
        <!--文章-->
        <template v-else-if="item.type == 'article'">
          <Article :item="item" :index="index" :selectedIndex="form.selectedIndex"></Article>
        </template>
        <!--头条快报-->
        <template v-else-if="item.type == 'special'">
          <Special :item="item" :index="index" :selectedIndex="form.selectedIndex"></Special>
        </template>
        <!--公告组-->
        <template v-else-if="item.type == 'notice'">
          <Notice :item="item" :index="index" :selectedIndex="form.selectedIndex"></Notice>
        </template>
        <!--导航组-->
        <template v-else-if="item.type == 'navBar'">
          <NavBar :item="item" :index="index" :selectedIndex="form.selectedIndex"></NavBar>
        </template>
        <!--商品组-->
        <template v-else-if="item.type == 'product'">
          <Product :item="item" :index="index" :selectedIndex="form.selectedIndex"></Product>
        </template>
        <!--优惠券-->
        <template v-else-if="item.type == 'coupon'">
          <Coupon :item="item" :index="index" :selectedIndex="form.selectedIndex"></Coupon>
        </template>
        <!--门店-->
        <template v-else-if="item.type == 'store'">
          <Store :item="item" :index="index" :selectedIndex="form.selectedIndex"></Store>
        </template>
        <!--客服-->
        <template v-else-if="item.type == 'service'">
          <Service :item="item" :index="index" :selectedIndex="form.selectedIndex"></Service>
        </template>
        <!--富文本-->
        <template v-else-if="item.type == 'richText'">
          <RichText :item="item" :index="index" :selectedIndex="form.selectedIndex"></RichText>
        </template>
        <!--辅助空白-->
        <template v-else-if="item.type == 'blank'">
          <Blank :item="item" :index="index" :selectedIndex="form.selectedIndex"></Blank>
        </template>
        <!--辅助线-->
        <template v-else-if="item.type == 'guide'">
          <Guide :item="item" :index="index" :selectedIndex="form.selectedIndex"></Guide>
        </template>
        <!--秒杀-->
        <template v-else-if="item.type == 'seckillProduct'">
          <Seckill :item="item" :index="index" :selectedIndex="form.selectedIndex"></Seckill>
        </template>
        <!--预告-->
        <template v-else-if="item.type == 'previewProduct'">
          <Preview :item="item" :index="index" :selectedIndex="form.selectedIndex"></Preview>
        </template>
        <!--拼团-->
        <template v-else-if="item.type == 'assembleProduct'">
          <assembleProduct :item="item" :index="index" :selectedIndex="form.selectedIndex"></assembleProduct>
        </template>
        <!--砍价-->
        <template v-else-if="item.type == 'bargainProduct'">
          <BargainProduct :item="item" :index="index" :selectedIndex="form.selectedIndex"></BargainProduct>
        </template>
        <!--直播-->
        <template v-else-if="item.type == 'live'">
          <Live :item="item" :index="index" :selectedIndex="form.selectedIndex"></Live>
        </template>
        <!--标题-->
        <template v-else-if="item.type == 'title'">
          <Title :item="item" :index="index" :selectedIndex="form.selectedIndex"></Title>
        </template>
        <!--按钮组 by lyzflash-->
        <template v-else-if="item.type == 'button'">
          <Button :item="item" :index="index" :selectedIndex="form.selectedIndex"></Button>
        </template>
        <!--选项卡组 by lyzflash-->
        <template v-else-if="item.type == 'tab'">
          <Tab :item="item" :index="index" :selectedIndex="form.selectedIndex"></Tab>
        </template>
      </div>
    </div>
  </div>
</template>
<script>
import Setpages from './model/Setpages.vue';
import Search from './model/Search.vue';
import Banner from './model/Banner.vue';
import ImageSingle from './model/ImageSingle.vue';
import Window from './model/Window.vue';
import Video from './model/Video.vue';
import Article from './model/Article.vue';
import Special from './model/Special.vue';
import Notice from './model/Notice.vue';
import NavBar from './model/NavBar.vue';
import Product from './model/Product.vue';
import Coupon from './model/Coupon.vue';
import Store from './model/Store.vue';
import Service from './model/Service.vue';
import RichText from './model/RichText.vue';
import Blank from './model/Blank.vue';
import Guide from './model/Guide.vue';
import Seckill from './model/Seckill.vue';
import assembleProduct from './model/assembleProduct.vue';
import BargainProduct from './model/BargainProduct.vue';
import Live from './model/Live.vue';
import Title from './model/Title.vue';
import draggable from 'vuedraggable';
import Preview from './model/Preview.vue';
import Button from './model/Button.vue';
import Tab from './model/Tab.vue';
export default {
  components: {
    /*顶部状态栏*/
    Setpages,
    /*搜索组件*/
    Search,
    /*图片轮播组件*/
    Banner,
    /*图片组件*/
    ImageSingle,
    /*图片橱窗*/
    Window,
    /*视频*/
    Video,
    /*文章*/
    Article,
    /*头条快报*/
    Special,
    /*公告组*/
    Notice,
    /*导航组*/
    NavBar,
    /*商品组*/
    Product,
    /*优惠券*/
    Coupon,
    /*门店*/
    Store,
    /*客服*/
    Service,
    /*富文本*/
    RichText,
    /*辅助空白*/
    Blank,
    /*辅助线*/
    Guide,
    /*拖动*/
    draggable,
    /*秒杀*/
    Seckill,
    /*拼团*/
    assembleProduct,
    /*砍价*/
    BargainProduct,
    /*微信直播*/
    Live,
    /*标题*/
    Title,
    Preview,
    /*按钮组 by lyzflash*/
    Button,
    /*选项卡组 by lyzflash*/
    Tab,
  },
  data() {
    return {};
  },
  props: {
    form: Object,
    defaultData: Object,
    diyData: Object
  },
  created() {
    console.log(this.diyData)
  },
  methods: {
    /*删除diy元素*/
    onDeleleItem: function(index) {
      let self = this;
      self
        .$confirm('确定要删除吗?', '提示', {
          type: 'warning'
        })
        .then(() => {
          self.diyData.items.splice(index, 1);
          self.form.selectedIndex = -1;
        });
    },
    /*编辑当前选中的Diy元素*/
    onEditer: function(index) {
      let self = this;
      // 记录当前选中元素的索引
      self.form.selectedIndex = index;
      // 当前选中的元素数据
      self.form.curItem = self.form.selectedIndex < 0 ? self.diyData.page : self.diyData.items[self.form.selectedIndex];
     // 注册编辑器事件
      //self.initEditor();
    },
    /* 注册编辑器事件*/
    initEditor: function() {
      let self = this;
      // 注册dom事件
      self.$nextTick(function() {
        // 销毁 umeditor 组件
        if (self.form.umeditor.hasOwnProperty('key')) {
          self.form.umeditor.destroy();
        }
        // 注册html组件
        self.editorHtmlComponent();
        // 富文本事件
        if (self.form.curItem.type === 'richText') {
          //self.onRichText(self.form.curItem);
        }
      });
    },
    /*编辑器事件:html组件*/
    editorHtmlComponent: function() {
      let self = this;
      var editor = self.$refs['diy-editor'];
      // 单/多选框
      //editor.find('input[type=checkbox], input[type=radio]').uCheck();
      // select组件
      // $editor.find('select').selected();
    }
  }
};
</script>
<style>
.diy-phone-container {
  position: relative;
  height: calc(100vh - 150px);
}
.diy-phone-container .wrapper {
  height:calc(100% - 90px) ;
  overflow-y: auto;
}
.diy-phone-container .phone-top {
  padding: 0 20px;
  border-radius: 18px 18px 0 0;
}
.diy-phone-container .phone-top .status-bar {
  height: 20px;
  display: flex;
  justify-content: space-between;
}
.diy-phone-container .phone-top .svg-icon {
  width: 20px;
  height: 20px;
  color: #333333;
}
.diy-phone-container .phone-top .navigation {
  height: 44px;
  line-height: 44px;
  text-align: center;
  font-size: 18px;
}
.diy-phone-container .diy-phone-item {
}
.diy-phone-container .diy-phone-item > div {
  position: relative;
  border: 2px solid #f1f1f2;
}
.diy-phone-container .diy-phone-item > div:hover,
.diy-phone-container .diy-phone-item.active > div {
  border: 2px dashed #3a8ee6;
}
.diy-phone-container .diy-phone-item .btn-edit-del {
  position: absolute;
  bottom: 0;
  right: 0;
  z-index: 10;
}
.diy-phone-container .diy-phone-item .btn-edit-del > div {
  width: 32px;
  height: 16px;
  line-height: 16px;
  display: inline-block;
  text-align: center;
  font-size: 10px;
  color: #fff;
  background: rgba(0, 0, 0, 0.4);
  margin-left: 2px;
  cursor: pointer;
}
.diy-phone-container img {
  width: 100%;
}
</style>
supplier_vue/src/views/page/page/diy/Type.vue
New file
@@ -0,0 +1,72 @@
<template>
  <!--
        作者:luoyiming
        时间:2020-06-20
        描述:diy组件-组件类别
    -->
  <div v-if="typeList!=null">
    <div class="common-form">组件库</div>
    <div class="min-group">
      <div v-for="(group,key) in typeList" :key="key">
         <div class="hd">{{key | typename}}</div>
         <div class="bd">
           <div class="item" v-for="(item,index) in group.children" :key="index" @click="$parent.onAddItem(item.type)">
             <p class="p-icon icon iconfont icon-tuichu"></p>
             <p class="p-txt">{{item.name}}</p>
           </div>
         </div>
      </div>
    </div>
  </div>
</template>
<script>
export default {
  data() {
    return {
      /*类别列表*/
      typeList:null
    };
  },
  props: {
    defaultData: Object
  },
  created() {
    this.init();
  },
  filters:{
    /*组名转换成中文*/
    typename:function(type){
      let name='';
      if(type=='media'){
        name="媒体组件";
      }else if(type=='shop'){
        name="商城组件";
      }else if(type=='tools'){
        name="工具组件";
      }
      return name;
    }
  },
  methods: {
    /*初始化数据*/
    init() {
      let tempList={};
      for(let key in this.defaultData){
        let item=this.defaultData[key];
        if(!tempList.hasOwnProperty(item.group)){
          tempList[item.group]={};
          tempList[item.group].children=[];
        }
        tempList[item.group].children.push(item);
      }
      this.typeList=tempList;
    }
  }
};
</script>
<style></style>
supplier_vue/src/views/page/page/diy/model/Article.vue
New file
@@ -0,0 +1,77 @@
<template>
  <!--
        作者:luoyiming
        时间:2020-06-20
        描述:diy组件-模拟显示-文章列表
    -->
  <div @click.stop="$parent.$parent.onEditer(index)">
    <div class="drag optional" :class="{selected:index === selectedIndex}">
      <div class="diy-article">
        <div class="article-item"
          v-for="(item,index) in (item.params.source == 'choice' ? item.data : item.defaultData)"
          :class="'show-type__' + item.show_type" :key="index">
          <!-- 小图模式 -->
          <template>
            <div class="article-item__image">
              <img v-img-url="item.image" alt="">
            </div>
            <div class="article-item__left flex-1">
              <div class="article-item__title text-ellipsis-2">
                <span class="f18">{{ item.article_title }}</span>
              </div>
              <div class="article-item__footer d-b-c">
                <span class="gray9">
                  {{ item.views_num }}次浏览
                </span>
                <span class="gray9">
                  2022-02-22
                </span>
              </div>
            </div>
          </template>
        </div>
      </div>
      <div class="btn-edit-del">
        <div class="btn-del" @click.stop="$parent.$parent.onDeleleItem(index)">删除</div>
      </div>
    </div>
  </div>
</template>
<script>
  export default {
    data() {
      return {
      };
    },
    props: ['item', 'index', 'selectedIndex'],
    methods: {
    }
  };
</script>
<style>
  .diy-article .show-type__10 {
    display: flex;
    padding: 10px;
    border-bottom: 1px solid #EEEEEE;
  }
  .diy-article .show-type__10 .article-item__image {
    width: 123px;
    height: 70px;
    border-radius: 3px;
    overflow: hidden;
  }
  .diy-article .show-type__10 .article-item__image>img {
    width: 123px;
    height: 70px;
  }
  .diy-article .show-type__10 .article-item__title {
    height: 40px;
  }
</style>
supplier_vue/src/views/page/page/diy/model/Banner.vue
New file
@@ -0,0 +1,120 @@
<template>
  <!--
        作者:luoyiming
        时间:2020-06-20
        描述:diy组件-模拟显示-轮播图
    -->
  <div class="drag optional" @click.stop="$parent.$parent.onEditer(index)" :class="{selected: index === selectedIndex}"
    :style="'background-color:'+item.style.background+';'">
    <div class="diy-banner" :style="'height:'+(item.style.height*0.5)+'px;'" :class="item.style.imgShape">
      <div class="img-list">
        <div  :key="index" v-for="(banner, index) in item.data"  v-if="index <= 1"
        :style="item.style.imgShape=='square'?'':'padding-bottom:'+(item.style.height*0.04)+'px;'">
          <img :style="item.style.imgShape=='square'?'height:'+(item.style.height*0.5)+'px;':'height:'+(item.style.height*0.46)+'px;'" v-img-url="banner.imgUrl">
        </div>
      </div>
      <div class="dots center d-c-c">
        <div :key="index" :class="index==0?'active '+item.style.btnShape:item.style.btnShape"
          v-for="(banner,index) in item.data" :style="index==0?'background:item.style.btnColor':''"></div>
      </div>
    </div>
    <div class="btn-edit-del">
      <div class="btn-del" @click.stop="$parent.$parent.onDeleleItem(index)">删除</div>
    </div>
  </div>
</template>
<script>
  export default {
    data() {
      return {
      };
    },
    props: ['item', 'index', 'selectedIndex'],
    methods: {
    }
  };
</script>
<style lang="scss">
  .p15{
    padding: 15px;
  }
  .diy-banner.round {
    padding: 12px;
    box-sizing: content-box;
    overflow: hidden;
    text-align: center;
  }
  .diy-banner.round img {
    width: 100%;
    height: 100px;
    object-fit: fill;
    border-radius: 10px;
    margin-bottom: 12px;
    box-sizing: content-box;
  }
  .diy-banner.square {
    height: 100px;
    overflow: hidden;
    text-align: center;
  }
  .diy-banner.square img {
    width: 100%;
    height: 100px;
    object-fit: fill;
  }
  .diy-banner.square .dots{
    position: absolute;
    left: 0;
    right:0;
    margin:0 auto;
    bottom: 10px;
  }
  .diy-banner.round .dots{
    position: absolute;
    left: 0;
    right:0;
    margin:0 auto;
    bottom: 20px;
  }
  .diy-banner .dots .square,
  .diy-banner .dots .round,
  .diy-banner .dots .rectangle {
    bottom: 40rpx;
    left: 0;
    right: 0;
    margin: auto;
  }
  .diy-banner .dots .square{
    width: 7px;
    height: 7px;
    margin: 0 2px;
    background:#ebedf0;
    opacity: 0.3;
  }
  .diy-banner .dots .round{
    width: 11px;
    height: 11px;
    margin: 0 2px;
    background: #ebedf0;
    opacity: 0.3;
    border-radius: 50%;
  }
  .diy-banner .dots .rectangle{
    width: 20px;
    height: 3px;
     margin: 0 2px;
    background: #ebedf0;
    opacity: 0.3;
    border-radius: 4rpx;
  }
  .diy-banner .dots .active{
    opacity: 1;
  }
</style>
supplier_vue/src/views/page/page/diy/model/BargainProduct.vue
New file
@@ -0,0 +1,193 @@
<template>
  <!--
        作者:luoyiming
        时间:2020-06-20
        描述:diy组件-模拟显示-砍价
    -->
  <div class="drag optional " :class="{ selected: index === selectedIndex }"
    @click.stop="$parent.$parent.onEditer(index)">
    <div class="diy-sharpproduct" :style="{ background: item.style.background }">
      <div class="sharpproduct-head d-b-c" :style="'background: url('+item.style.background_image+');'">
        <div class="left d-s-c">
          <div class="name"> </div>
          <div class="datetime d-s-c">
            <div class="daybox hour"
              :style="{ background: item.style.countdown_back_color,color: item.style.countdown_color}">12天</div>
            <span class="hour" :style="{color: item.style.color}">30</span>
            <span class="text" :style="{ color: item.style.color }">:</span>
            <span class="hour" :style="{color: item.style.color}">00</span>
            <span class="text" :style="{ color: item.style.color }">:</span>
            <span class="hour" :style="{color: item.style.color}">00</span>
          </div>
        </div>
        <div class="right mr10">更多</div>
      </div>
      <ul class="product-list column__3" :style="getUlwidth(item)">
        <li class="product-item" v-for="(product, index) in item.data" :key="index">
          <!-- 两列三列 -->
          <div class="product-cover"><img v-img-url="product.image" /></div>
          <div class="product-info p-0-10">
            <div class="price d-b-c f12 tc">
              <div v-if="item.style.show.floorPrice == '1'">
                <div class="red">¥120</div>
                <div v-if="item.style.show.originalPrice == '1'" class="gray6 text-d-line">¥233</div>
              </div>
            </div>
          </div>
        </li>
      </ul>
    </div>
    <div class="btn-edit-del">
      <div class="btn-del" @click.stop="$parent.$parent.onDeleleItem(index)">删除</div>
    </div>
  </div>
</template>
<script>
  import ProductApi from '@/api/product.js';
  export default {
    data() {
      return {
        /*商品列表*/
        tableData: [],
        /*分类id*/
        category_id: 0
      };
    },
    created() {},
    props: ['item', 'index', 'selectedIndex'],
    methods: {
      /*计算宽度*/
      getUlwidth(item) {
        if (item.style.display == 'slide') {
          let total = 0;
          if (item.params.source == 'choice') {
            total = item.data.length;
          } else {
            total = item.defaultData.length;
          }
          let w = 0;
          if (item.style.column == 2) {
            w = total * 150;
          } else {
            w = total * 100;
          }
          return 'width:' + w + 'px;';
        }
      }
    }
  };
</script>
<style>
  .diy-sharpproduct {
    padding: 10px;
  }
  .diy-sharpproduct .product-list {
    display: flex;
    justify-content: flex-start;
    flex-wrap: wrap;
    background: linear-gradient(180deg, #F4DCD2 0%, #FFFFFF 100%);
    box-shadow: 0px 4px 2px 0px rgba(6, 0, 1, 0.03);
  }
  .diy-sharpproduct .product-list .product-title {
    margin-top: 4px;
    height: 20px;
    line-height: 20px;
    display: -webkit-box;
    overflow: hidden;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
  }
  .diy-sharpproduct .display__list .column__3 {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    padding: 10px;
  }
  .diy-sharpproduct .product-list.column__3 .product-item {
    width: 66px;
    margin-bottom: 10px;
    margin-right: 23px;
    padding: 10px;
  }
  .diy-sharpproduct .product-list.column__3 .product-item .product-cover {
    width: 66px;
    height: 66px;
    border-radius: 6px;
    overflow: hidden;
  }
  .diy-sharpproduct .product-list.column__3 .product-item .product-cover img {
    width: 66px;
    height: 66px;
  }
  .diy-sharpproduct .product-list.column__3 .product-title {
    height: 20px;
    overflow: hidden;
  }
  .diy-sharpproduct .sharpproduct-head {
    height: 45px;
    align-items: center;
    background-size: 100% 100% !important;
    border-top-left-radius: 6px;
    border-top-right-radius: 6px;
  }
  .sharpproduct-head .name {
    font-size: 18px;
    font-weight: bold;
    width: 100px;
  }
  .sharpproduct-head .datetime {
    margin-left: 20px;
  }
  .sharpproduct-head .datetime>span {
    display: inline-block;
  }
  .sharpproduct-head .datetime .text {
    padding: 0 2px;
  }
  .sharpproduct-head .datetime .box {
    padding: 2px;
    background: #000000;
    color: #ffffff;
  }
  .diy-sharpproduct .product-list .barginbtns {
    width: 100px;
    background: linear-gradient(90deg, #FF4545 0%, #F6220C 100%);
    height: 25px;
    line-height: 25px;
    font-size: 13px;
    text-align: center;
    color: #FFFFFF;
    margin: 0 auto;
    border-radius: 13px;
  }
  .left .datetime {
    padding: 1px;
    border-radius: 200px 0 200px 200px;
    border: 1px solid #EEEEEE;
    padding-right: 4px;
  }
  .left .datetime .daybox {
    padding: 0 10px;
    border-radius: 200px;
    margin-right: 5px;
  }
</style>
supplier_vue/src/views/page/page/diy/model/Blank.vue
New file
@@ -0,0 +1,36 @@
<template>
  <!--
        作者:wangxw
        时间:2019-11-05
        描述:diy组件 搜索栏
    -->
  <div>
    <div @click.stop="$parent.$parent.onEditer(index)">
      <div class="drag optional" :class="{selected:index === selectedIndex}">
        <div class="diy-blank" :style="{height: item.style.height +'px', background:item.style.background }">
        </div>
        <div class="btn-edit-del">
          <div class="btn-del" @click.stop="$parent.$parent.onDeleleItem(index)">删除</div>
        </div>
      </div>
    </div>
  </div>
</template>
<script>
  export default {
    data() {
      return {
      };
    },
    props: ['item', 'index', 'selectedIndex'],
    methods: {
    }
  };
</script>
<style>
</style>
supplier_vue/src/views/page/page/diy/model/Button.vue
New file
@@ -0,0 +1,58 @@
<template>
    <!--
          作者:lyzflash
          时间:2023-08-10
          描述:diy组件-模拟显示-按钮组
      -->
    <div @click.stop="$parent.$parent.onEditer(index)">
      <div class="drag optional" :class="{selected:index === selectedIndex}">
        <div class="diy-navBar" :style="{background:item.style.background}">
          <ul class="list button-list" :class="'column-'+item.style.rowsNum">
            <li class="item" :key="index" v-for="(navBar,index) in item.data" v-if="index<item.style.rowsNum">
              <div class="item-text text-ellipsis" :style="{color:navBar.color}">
                {{navBar.text}}</div>
            </li>
          </ul>
        </div>
        <div class="btn-edit-del">
          <div class="btn-del" @click.stop="$parent.$parent.onDeleleItem(index)">删除</div>
        </div>
      </div>
    </div>
</template>
<script>
  export default {
    data() {
      return {
      };
    },
    props: ['item', 'index', 'selectedIndex'],
    methods: {
    }
  };
</script>
<style>
.diy-navBar .list{ display: flex; flex-wrap: wrap; align-items: flex-start;}
.diy-navBar .list .item{ padding: 10px 0; display: flex; justify-content: center; align-items: center; flex-direction: column;}
.diy-navBar .list.column-3 .item{ width: 33.333333333%;}
.diy-navBar .list.column-2 .item{ width: 50%;}
.diy-navBar .list .item-text{ width: 100%; padding: 4px 0; text-align: center;}
.diy-navBar .button-list li {
  position: relative;
}
.diy-navBar .button-list li:before {
  content: '';
  position: absolute;
  left: 0;
  top: 5px;
  bottom: 5px;
  border-left: 1px solid #eee;
}
.diy-navBar .button-list li:first-child:before {
  border: 0;
}
</style>
supplier_vue/src/views/page/page/diy/model/Coupon.vue
New file
@@ -0,0 +1,106 @@
<template>
  <!--
        作者:wangxw
        时间:2019-11-05
        描述:diy组件 搜索栏
    -->
  <div @click.stop="$parent.$parent.onEditer(index)" class="drag optional" :class="{selected: index === selectedIndex}">
    <div class="diy-coupon" :style="{background:item.style.background,padding: item.style.paddingTop+'px '+' 0'}">
      <div :key="index" v-for="(coupon,index) in item.data" class="coupon-wrapper">
        <div class="coupon-item d-b-c" >
          <i class="before" :style="{background:item.style.background}"></i>
          <div  class="left-content">
            <div class="content-top">
              <span class="">¥</span>
              <span class="f20">{{ coupon.reduce_price }}</span>
            </div>
            <div class="content-bottom">
              <span>满{{ coupon.min_price }}减{{ coupon.reduce_price }}</span>
            </div>
          </div>
          <div class="right-receive">
            <div class="lr-tb">立即领取</div>
          </div>
        </div>
      </div>
    </div>
    <div class="btn-edit-del">
      <div class="btn-del" @click.stop="$parent.$parent.onDeleleItem(index)">删除</div>
    </div>
  </div>
</template>
<script>
  export default {
    data() {
      return {
      };
    },
    props: ['item', 'index', 'selectedIndex'],
    methods: {
    }
  };
</script>
<style>
  .diy-coupon {
    display: flex;
    justify-content: flex-start;
    align-items: center;
    overflow-x: auto;
  }
  .diy-coupon .coupon-wrapper {
  }
  .diy-coupon .coupon-wrapper .coupon-item {
    border-radius: 4px;
    overflow: hidden;
    margin-right: 10px;
  }
  .diy-coupon .coupon-wrapper .left-content {
    width: 80px;
    height: 56px;
    padding: 0;
    box-sizing: border-box;
    color: #FFFFFF;
    flex: 1;
    background: #FF4C01;
  }
  .diy-coupon .coupon-wrapper .left-content .price {
    font-size: 20px;
    font-weight: bold;
  }
  .diy-coupon .coupon-wrapper .content-top {
    font-size: 12px;
    text-align: center;
  }
  .diy-coupon .coupon-wrapper .content-bottom{
    font-size: 10px;
    text-align: center;
  }
  .diy-coupon .coupon-wrapper .right-receive {
    height: 56px;
    width: 26px;
    flex-shrink: 0;
    display: flex;
    justify-content: center;
    align-items: center;
    border-left: 1px dashed #ffffff;
    text-align: center;
    color: #FFF5D4;
    background: #FF4C01;
    font-size: 9px;
    line-height: 10px;
  }
  .lr-tb{
    width: 13px;
  }
</style>
supplier_vue/src/views/page/page/diy/model/Guide.vue
New file
@@ -0,0 +1,36 @@
<template>
  <!--
        作者:wangxw
        时间:2019-11-05
        描述:diy组件 搜索栏
    -->
  <div>
    <div @click.stop="$parent.$parent.onEditer(index)" class="drag optional" :class="{selected: index === selectedIndex}">
      <div class="diy-guide" :style="{padding: item.style.paddingTop +'px '+'0', background:item.style.background }">
        <p class="line" :style="{borderTopWidth: item.style.lineHeight +'px',borderTopColor:item.style.lineColor,borderTopStyle: item.style.lineStyle }">
        </p>
      </div>
      <div class="btn-edit-del">
        <div class="btn-del" @click.stop="$parent.$parent.onDeleleItem(index)">删除</div>
      </div>
    </div>
  </div>
</template>
<script>
  export default {
    data() {
      return {
      };
    },
    props: ['item', 'index', 'selectedIndex'],
    methods: {
    }
  };
</script>
<style>
</style>
supplier_vue/src/views/page/page/diy/model/ImageSingle.vue
New file
@@ -0,0 +1,37 @@
<template>
<!--
        作者:luoyiming
        时间:2020-06-20
        描述:diy组件-模拟显示-单图组
    -->
    <div @click.stop="$parent.$parent.onEditer(index)">
      <div class="drag optional" :class="{selected:index === selectedIndex}">
        <div class="diy-imageSingle" :style="{ paddingBottom: item.style.paddingTop + 'px', background: item.style.background}">
          <div class="item-image" :key="index" v-for="(imageSingle, index) in item.data" :style="{padding: item.style.paddingTop + 'px ' + item.style.paddingLeft + 'px 0'}">
            <img v-img-url="imageSingle.imgUrl">
          </div>
        </div>
        <div class="btn-edit-del">
          <div class="btn-del" @click.stop="$parent.$parent.onDeleleItem(index)">删除</div>
        </div>
      </div>
    </div>
</template>
<script>
  export default {
    data() {
      return {
      };
    },
    props: ['item', 'index', 'selectedIndex'],
    methods: {
    }
  };
</script>
<style>
.diy-imageSingle img{ max-width: 100%;}
</style>
supplier_vue/src/views/page/page/diy/model/Live.vue
New file
@@ -0,0 +1,93 @@
<template>
  <!--
        作者:luoyiming
        时间:2020-06-20
        描述:diy组件-模拟显示-微信直播
    -->
  <div class="drag optional p10" :class="{ selected: index === selectedIndex }"
    @click.stop="$parent.$parent.onEditer(index)">
    <div class="diy-wxlive">
      <div class="wxlive-head d-b-c">
        <img v-img-url="item.style.background_image" />
      </div>
      <ul class="wxlive-list d-s-c f-w" :style="getUlwidth(item)">
        <li class="item" v-for="(live, index) in item.data" :key="index">
          <div class="box">
            <div class="pic">
              <img v-img-url="live.image" />
            </div>
            <div>{{live.name}}</div>
          </div>
        </li>
      </ul>
    </div>
    <div class="btn-edit-del">
      <div class="btn-del" @click.stop="$parent.$parent.onDeleleItem(index)">删除</div>
    </div>
  </div>
</template>
<script>
  export default {
    data() {
      return {
        /*商品列表*/
        tableData: [],
        /*分类id*/
        category_id: 0
      };
    },
    created() {},
    props: ['item', 'index', 'selectedIndex'],
    methods: {
      /*计算宽度*/
      getUlwidth(item) {
        if (item.style.display == 'slide') {
          let total = 0;
          if (item.params.source == 'choice') {
            total = item.data.length;
          } else {
            total = item.defaultData.length;
          }
          let w = 0;
          if (item.style.column == 2) {
            w = total * 150;
          } else {
            w = total * 100;
          }
          return 'width:' + w + 'px;';
        }
      }
    }
  };
</script>
<style>
  .diy-wxlive {}
  .diy-wxlive .wxlive-head {
    height: 40px;
    border-top-left-radius: 6px;
    border-top-right-radius: 6px;
    overflow: hidden;
  }
  .diy-wxlive .wxlive-head .name {
    font-size: 18px;
    font-weight: bold;
  }
  .diy-wxlive .wxlive-list {}
  .diy-wxlive .wxlive-list .item {
    width: 50%;
  }
  .diy-wxlive .wxlive-list .item .box {
    padding: 10px;
  }
  .diy-wxlive .wxlive-list .item img {
    width: 100%;
  }
</style>
supplier_vue/src/views/page/page/diy/model/NavBar.vue
New file
@@ -0,0 +1,50 @@
<template>
    <!--
          作者:luoyiming
          时间:2020-06-20
          描述:diy组件-模拟显示-导航组
      -->
    <div @click.stop="$parent.$parent.onEditer(index)">
      <div class="drag optional" :class="{selected:index === selectedIndex}">
        <div class="diy-navBar" :style="{background:item.style.background}">
          <ul class="list" :class="'column-'+item.style.rowsNum">
            <li class="item" :key="index" v-for="(navBar,index) in item.data">
              <div class="item-image">
                <img v-img-url="navBar.imgUrl">
              </div>
              <div class="item-text text-ellipsis" :style="{color:navBar.color}">
                {{navBar.text}}</div>
            </li>
          </ul>
        </div>
        <div class="btn-edit-del">
          <div class="btn-del" @click.stop="$parent.$parent.onDeleleItem(index)">删除</div>
        </div>
      </div>
    </div>
</template>
<script>
  export default {
    data() {
      return {
      };
    },
    props: ['item', 'index', 'selectedIndex'],
    methods: {
    }
  };
</script>
<style>
.diy-navBar .list{ display: flex; flex-wrap: wrap; align-items: flex-start;}
.diy-navBar .list .item{ padding: 10px 0; display: flex; justify-content: center; align-items: center; flex-direction: column;}
.diy-navBar .list.column-3 .item{ width: 33.333333333%;}
.diy-navBar .list.column-4 .item{ width: 25%;}
.diy-navBar .list.column-5 .item{ width: 20%;}
.diy-navBar .list .item-image{ width: 60%;}
.diy-navBar .list .item-image img{ width: 100%;}
.diy-navBar .list .item-text{ width: 100%; padding: 4px 0; text-align: center;}
</style>
supplier_vue/src/views/page/page/diy/model/Notice.vue
New file
@@ -0,0 +1,44 @@
<template>
  <!--
        作者:wangxw
        时间:2019-11-05
        描述:diy组件 搜索栏
    -->
  <div>
    <div @click.stop="$parent.$parent.onEditer(index)">
      <div class="drag optional" :class="{selected:index === selectedIndex}">
        <div class="diy-notice" :style="{padding: item.style.paddingTop + 'px' + ' 10px', background: item.style.background}">
          <div class="notice-icon">
            <img v-img-url="item.params.icon">
          </div>
          <div class="notice-text flex-1 text-ellipsis">
            <span :style="{color: item.style.textColor}">{{item.params.text}}</span>
          </div>
        </div>
        <div class="btn-edit-del">
          <div class="btn-del" @click.stop="$parent.$parent.onDeleleItem(index)">删除</div>
        </div>
      </div>
    </div>
  </div>
</template>
<script>
  export default {
    data() {
      return {
      };
    },
    props: ['item', 'index', 'selectedIndex'],
    methods: {
    }
  };
</script>
<style>
.diy-notice{ display: flex; justify-content: flex-start; align-items: center;}
.diy-notice .notice-icon{ width: 32px; height: 32px;}
.diy-notice .notice-text{ margin-left: 10px; overflow: hidden; white-space: nowrap;}
</style>
supplier_vue/src/views/page/page/diy/model/Preview.vue
New file
@@ -0,0 +1,173 @@
<template>
  <!--
        作者:luoyiming
        时间:2020-06-20
        描述:diy组件-模拟显示-限时秒杀
    -->
  <div class="drag optional" :class="{ selected: index === selectedIndex }"
    @click.stop="$parent.$parent.onEditer(index)">
    <div class="diy-preview">
      <div class="diy-head d-b-c" :style="'background: url('+item.style.background_image+');'">
        <div class="left d-s-c">
          <div class="name"> </div>
        </div>
        <div class="right mr10 white">更多</div>
      </div>
      <ul class="product-list column__3"   :style="{ background: item.style.background_color,width: getUlwidth(item)}">
        <li class="product-item" v-for="(product, index) in item.data" :key="index">
          <!-- 两列三列 -->
          <div class="datetime d-s-c"  :style="{ background: item.style.countdown_back_color,color: item.style.countdown_color}">
            <img style="width: 51px;height: 19px;" :src="item.style.top_image" alt="">
            <div class="daybox hour">12天</div>
            <span class="hour">30</span>
            <span class="text">:</span>
            <span class="hour">00</span>
            <span class="text">:</span>
            <span class="hour">00</span>
          </div>
          <div class="d-b-c" style="padding: 7px;">
            <div class="product-info flex-1">
              <div class="price  f12">
                <div class="red"   :style="{ color: item.style.color}">¥{{product.product_price}}起</div>
                <div class="gray3 text-ellipsis">{{product.product_name}}</div>
                <div class="gray6 text-d-line">¥{{product.original_price}}</div>
              </div>
            </div>
            <div class="product-cover"><img v-img-url="product.image" /></div>
          </div>
        </li>
      </ul>
    </div>
    <div class="btn-edit-del">
      <div class="btn-del" @click.stop="$parent.$parent.onDeleleItem(index)">删除</div>
    </div>
  </div>
</template>
<script>
  export default {
    data() {
      return {
        /*分类id*/
        category_id: 0
      };
    },
    created() {},
    props: ['item', 'index', 'selectedIndex'],
    methods: {
      /*计算宽度*/
      getUlwidth(item) {
        if (item.style.display == 'slide') {
          let total = 0;
          if (item.params.source == 'choice') {
            total = item.data.length;
          } else {
            total = item.defaultData.length;
          }
          let w = 0;
          if (item.style.column == 2) {
            w = total * 150;
          } else {
            w = total * 100;
          }
          return  w + 'px;';
        }
      }
    }
  };
</script>
<style>
  .diy-preview {
    padding: 10px;
    border-radius: 10px;
  }
  .diy-preview .diy-head {
    padding: 0 10px;
    height: 45px;
    background-size: 100% 100% !important;
    border-top-left-radius: 6px;
    border-top-right-radius: 6px;
  }
  .diy-preview .diy-head .name {
    font-size: 18px;
    font-weight: bold;
    width: 100px;
  }
  .diy-preview .diy-head .datetime {
    margin-left: 20px;
  }
  .diy-preview .diy-head .datetime>span {
    display: inline-block;
  }
  .diy-preview .diy-head .datetime .text {
    padding: 0 4px;
  }
  .diy-preview .diy-head .datetime .box {
    padding: 2px;
    border-radius: 4px;
    background: #000000;
    color: #ffffff;
  }
  .diy-preview .product-list {
    display: flex;
    justify-content: flex-start;
    flex-wrap: wrap;
    background: linear-gradient(180deg, #F4DCD2 0%, #FFFFFF 100%);
    box-shadow: 0px 4px 2px 0px rgba(6, 0, 1, 0.03);
    padding:10px;
    box-sizing: border-box;
    height: 215px;
    box-sizing: border-box;
    flex-direction: column;
    border-radius: 0 0 8px 8px;
  }
  .diy-preview .product-list .product-title {
    margin-top: 4px;
    height: 40px;
    line-height: 20px;
    display: -webkit-box;
    overflow: hidden;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
  }
  .diy-preview .display__list .column__3 {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
  }
  .diy-preview .product-list.column__3 .product-item {
    width: 150px;
    margin-right: 20px;
    border-radius: 8px;
    overflow: hidden;
    background-color: #ffffff;
    margin-bottom: 10px;
  }
  .diy-preview .product-list.column__3 .product-item .product-cover {
    width: 44px;
    height: 44px;
    border-radius: 6px;
    overflow: hidden;
  }
  .diy-preview .product-list.column__3 .product-item .product-cover img {
    width: 44px;
    height: 44px;
  }
  .diy-preview .product-list.column__3 .product-title {
    height: 20px;
    overflow: hidden;
  }
</style>
supplier_vue/src/views/page/page/diy/model/Product.vue
New file
@@ -0,0 +1,211 @@
<template>
 <!--
        作者:luoyiming
        时间:2020-06-20
        描述:diy组件-模拟显示-商品栏
    -->
  <div class="drag optional" :class="{ selected: index === selectedIndex }" @click.stop="$parent.$parent.onEditer(index)">
    <div class="diy-product" :style="{ background: item.style.background }">
      <div :class="['display__' + item.style.display]">
        <ul class="product-list" :class="['column__' + item.style.column]" :style="getUlwidth(item)">
          <li class="product-item" v-for="(product,index) in item.data" :key="index">
            <!-- 单列商品 -->
            <template v-if="item.style.column == 1">
              <div class="product-item-box">
                <!-- 商品图片 -->
                <div class="product-cover"><img v-img-url="product.image" /></div>
                <div class="product-info">
                  <!-- 商品名称 -->
                  <div v-if="item.style.show.productName" class="product-title">
                    <span>{{ product.product_name }}</span>
                  </div>
                  <!-- 商品卖点 -->
                  <div v-if="item.style.show.sellingPoint" class="selling-point gray9">
                    <span>{{ product.selling_point }}</span>
                  </div>
                  <!-- 商品销量 -->
                  <div v-if="item.style.show.productSales" class="already-sale">
                    <span>已售{{ product.product_sales }}件</span>
                  </div>
                  <!-- 商品价格 -->
                  <div class="price d-s-c">
                    <div v-if="item.style.show.productPrice" class="orange">
                      <span>¥</span>
                      <span class="f18 fb">{{ product.product_price }}</span>
                    </div>
                    <div class="ml10 gray9 text-d-line" v-if="item.style.show.linePrice && product.line_price > 0">
                      <span>¥</span>
                      <span>{{ product.line_price }}</span>
                    </div>
                  </div>
                </div>
              </div>
            </template>
            <!-- 两列三列 -->
            <template v-else>
              <div class="product-cover"><img v-img-url="product.image" /></div>
              <div class="product-info p-0-10">
                <div v-if="item.style.show.productName" class="product-title">{{ product.product_name }}</div>
                <div class="price d-s-c f12">
                  <div v-if="item.style.show.productPrice" class="orange">
                    <span>¥</span>
                    <span class="">{{ product.product_price }}</span>
                  </div>
                  <div class="ml4 gray9 text-d-line" v-if="item.style.show.linePrice && product.line_price > 0">
                    ¥{{ product.line_price }}
                  </div>
                </div>
              </div>
            </template>
          </li>
        </ul>
      </div>
    </div>
    <div class="btn-edit-del">
      <div class="btn-del" @click.stop="$parent.$parent.onDeleleItem(index)">删除</div>
    </div>
  </div>
</template>
<script>
  import ProductApi from '@/api/product.js';
  export default {
    data() {
      return {
        /*商品列表*/
        tableData: {},
        /*分类id*/
        category_id: 0,
      };
    },
    created() {
      /*获取列表*/
      this.getData();
    },
    props: ['item', 'index', 'selectedIndex'],
    methods: {
      getData() {
        let self = this;
        ProductApi.productList({
            category_id: self.category_id
          }, true).then(res => {
            self.tableData = res.data.list.data;
          })
          .catch(error => {
            self.loading = false;
          });
      },
      /*计算宽度*/
      getUlwidth(item){
        if(item.style.display=='slide'){
           let total=0;
          if(item.params.source=='choice'){
             total=item.data.length;
          }else{
            total=item.defaultData.length;
          }
          let w=0;
          if(item.style.column==2){
            w=total*150;
          }else{
            w=total*100;
          }
           return 'width:'+w+'px;';
        }
      }
    }
  };
</script>
<style>
  .diy-product .product-list.column__1 .product-item {
    padding: 10px;
    border-bottom: 1px solid #dddddd;
    background: #FFFFFF;
  }
  .diy-product .product-list.column__1 .product-item-box {
    display: flex;
    justify-content: flex-start;
    align-items: stretch;
  }
  .diy-product .display__slide{
    overflow-x: auto;
  }
  .diy-product .display__slide .product-list{display: flex;
    justify-content: flex-start;}
  .diy-product .display__slide .product-list.column__2 .product-item{
    width: 150px;
  }
  .diy-product .display__slide .product-list.column__3 .product-item{
    width: 100px;
  }
.diy-product .display__slide .product-list .product-item{ margin-right: 10px;}
  .diy-product .product-list img {
    width: 100%;
  }
  .diy-product .product-list.column__1 .product-cover {
    width: 100px;
    height: 100px;
  }
  .diy-product .product-list.column__1 .product-info {
    margin-left: 10px;
    flex: 1;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
  }
  .diy-product .product-list .product-title {
    margin-top: 4px;
    height: 40px;
    line-height: 20px;
    display: -webkit-box;
    overflow: hidden;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
  }
  .diy-product .display__list .column__2,
  .diy-product .display__list .column__3 {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
  }
  .diy-product .product-list.column__2 .product-item {
    width:170px;
    margin-bottom: 10px;
    background: #FFFFFF;
  }
  .diy-product .product-list.column__2 .product-item .product-cover{
    width: 110px;
    height: 110px;
    overflow: hidden;
    margin: 10px auto;
  }
  .diy-product .product-list.column__3 .product-item {
    width: 117px;
    margin-bottom: 10px;
    background: #FFFFFF;
  }
   .diy-product .product-list.column__3 .product-item .product-cover{
    width: 117px;
    height: 117px;
    overflow: hidden;
   }
   .diy-product .product-list.column__3 .product-item .product-cover img{
     width: 117px;
   }
  .diy-product .product-list.column__2 .product-title,
  .diy-product .product-list.column__3 .product-title {
    height: 40px; overflow: hidden;
  }
</style>
supplier_vue/src/views/page/page/diy/model/RichText.vue
New file
@@ -0,0 +1,37 @@
<template>
  <!--
        作者:wangxw
        时间:2019-11-05
        描述:diy组件 富文本框
    -->
    <div @click.stop="$parent.$parent.onEditer(index)">
      <div class="drag optional" :class="{selected: index === selectedIndex}">
        <div class="diy-richText" :style="{background: item.style.background, padding: item.style.paddingTop + 'px ' + item.style.paddingLeft + 'px'}"
          v-html="item.params.content">
        </div>
        <div class="btn-edit-del">
          <div class="btn-del" @click.stop="$parent.$parent.onDeleleItem(index)">删除</div>
        </div>
      </div>
    </div>
</template>
<script>
  export default {
    data() {
      return {
      };
    },
    props: ['item', 'index', 'selectedIndex'],
    methods: {
    }
  };
</script>
<style>
.diy-richText video{ width: 100%;}
</style>
supplier_vue/src/views/page/page/diy/model/Search.vue
New file
@@ -0,0 +1,50 @@
<template>
  <!--
        作者:luoyiming
        时间:2020-06-20
        描述:diy组件-模拟显示-搜索栏
    -->
  <div class="drag optional" :class="{ selected: index === selectedIndex }" @click.stop="$parent.$parent.onEditer(index)">
    <div class="diy-search">
      <div class="inner" :class="'inner-'+item.style.searchStyle">
        <div class="search-input" :class="'search-input-'+item.style.textAlign">
          <i class="el-icon-search"></i>
          <span>{{ item.params.placeholder }}</span>
        </div>
      </div>
    </div>
    <div class="btn-edit-del">
      <div class="btn-del" @click.stop="$parent.$parent.onDeleleItem(index)">删除</div>
    </div>
  </div>
</template>
<script>
export default {
  data() {
    return {};
  },
  props: ['item', 'index', 'selectedIndex'],
  created() {
  },
  methods: {
  }
};
</script>
<style>
.diy-search{padding: 10px;background: #f1f1f2;}
.diy-search .inner{
    height: 30px;
    line-height: 30px;
    background: #fff;
    overflow: hidden;}
.diy-search .inner-3{}
.diy-search .inner-6{border-radius: 8px;}
.diy-search .inner-9{border-radius: 15px;}
.diy-search .inner .search-input{ padding: 0 10px; display: flex; align-items: center;}
.diy-search .search-input-3{ justify-content: flex-start;}
.diy-search .search-input-6{ justify-content: center;}
.diy-search .search-input-9{ justify-content: flex-end;}
</style>
supplier_vue/src/views/page/page/diy/model/Seckill.vue
New file
@@ -0,0 +1,165 @@
<template>
  <!--
        作者:luoyiming
        时间:2020-06-20
        描述:diy组件-模拟显示-限时秒杀
    -->
  <div class="drag optional" :class="{ selected: index === selectedIndex }"
    @click.stop="$parent.$parent.onEditer(index)">
    <div class="diy-seckill">
      <div class="diy-head d-b-c" :style="'background: url('+item.style.background_image+');'">
        <div class="left d-s-c">
          <div class="name"> </div>
          <div class="datetime d-s-c">
            <div class="daybox hour"
              :style="{ background: item.style.countdown_back_color,color: item.style.countdown_color}">12天</div>
            <span class="hour" :style="{color: item.style.color}">30</span>
            <span class="text" :style="{ color: item.style.color }">:</span>
            <span class="hour" :style="{color: item.style.color}">00</span>
            <span class="text" :style="{ color: item.style.color }">:</span>
            <span class="hour" :style="{color: item.style.color}">00</span>
          </div>
        </div>
        <div class="right mr10">更多</div>
      </div>
      <ul class="product-list column__3" :style="getUlwidth(item)">
        <li class="product-item" v-for="(product, index) in item.data" :key="index">
          <!-- 两列三列 -->
          <div class="product-cover"><img v-img-url="product.image" /></div>
          <div class="product-info p-0-10">
            <div class="price  f12 tc">
              <span v-if="item.style.show.seckillPrice == '1'" class="red">¥120</span>
              <span v-if="item.style.show.linePrice == '1'" class="gray6 text-d-line">¥233</span>
            </div>
          </div>
        </li>
      </ul>
    </div>
    <div class="btn-edit-del">
      <div class="btn-del" @click.stop="$parent.$parent.onDeleleItem(index)">删除</div>
    </div>
  </div>
</template>
<script>
  export default {
    data() {
      return {
        /*分类id*/
        category_id: 0
      };
    },
    created() {},
    props: ['item', 'index', 'selectedIndex'],
    methods: {
      /*计算宽度*/
      getUlwidth(item) {
        if (item.style.display == 'slide') {
          let total = 0;
          if (item.params.source == 'choice') {
            total = item.data.length;
          } else {
            total = item.defaultData.length;
          }
          let w = 0;
          if (item.style.column == 2) {
            w = total * 150;
          } else {
            w = total * 100;
          }
          return 'width:' + w + 'px;';
        }
      }
    }
  };
</script>
<style>
  .diy-seckill {
    padding: 10px;
    border-radius: 10px;
  }
  .diy-seckill .diy-head {
    padding: 0 10px;
    height: 45px;
    background-size: 100% 100% !important;
    border-top-left-radius: 6px;
    border-top-right-radius: 6px;
  }
  .diy-seckill .diy-head .name {
    font-size: 18px;
    font-weight: bold;
    width: 100px;
  }
  .diy-seckill .diy-head .datetime {
    margin-left: 20px;
  }
  .diy-seckill .diy-head .datetime>span {
    display: inline-block;
  }
  .diy-seckill .diy-head .datetime .text {
    padding: 0 4px;
  }
  .diy-seckill .diy-head .datetime .box {
    padding: 2px;
    border-radius: 4px;
    background: #000000;
    color: #ffffff;
  }
  .diy-seckill .product-list {
    display: flex;
    justify-content: flex-start;
    flex-wrap: wrap;
    background: linear-gradient(180deg, #F4DCD2 0%, #FFFFFF 100%);
    box-shadow: 0px 4px 2px 0px rgba(6, 0, 1, 0.03);
    padding:10px;
  }
  .diy-seckill .product-list .product-title {
    margin-top: 4px;
    height: 40px;
    line-height: 20px;
    display: -webkit-box;
    overflow: hidden;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
  }
  .diy-seckill .display__list .column__3 {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
  }
  .diy-seckill .product-list.column__3 .product-item {
    width: 66px;
    padding-bottom: 10px;
    margin-right: 23px;
  }
  .diy-seckill .product-list.column__3 .product-item:nth-child(3n) {
    margin-right: ;: 0;
  }
  .diy-seckill .product-list.column__3 .product-item .product-cover {
    width: 66px;
    height: 66px;
    border-radius: 6px;
    overflow: hidden;
  }
  .diy-seckill .product-list.column__3 .product-item .product-cover img {
    width: 66px;
    height: 66px;
  }
  .diy-seckill .product-list.column__3 .product-title {
    height: 20px;
    overflow: hidden;
  }
</style>
supplier_vue/src/views/page/page/diy/model/Service.vue
New file
@@ -0,0 +1,44 @@
<template>
  <!--
        作者:luoyiming
        时间:2020-06-20
        描述:diy组件-模拟显示-在线客服
    -->
  <div class="diy-service-wrap" :style="{ right: item.style.right + '%', bottom: item.style.bottom + '%' }">
    <div class="diy-service drag optional drag__nomove" @click.stop="$parent.$parent.onEditer(index)" :class="{ selected: index === selectedIndex }">
      <div class="service-icon" :style="{ opacity: item.style.opacity / 100 }"><img v-img-url="item.params.image" alt="" /></div>
      <div class="btn-edit-del"><div class="btn-del" @click.stop="$parent.$parent.onDeleleItem(index)">删除</div></div>
    </div>
  </div>
</template>
<script>
export default {
  data() {
    return {};
  },
  props: ['item', 'index', 'selectedIndex'],
  methods: {}
};
</script>
<style>
.diy-phone-container .diy-phone-item > div.diy-service-wrap {
  position: absolute;
  z-index: 90;
}
.diy-service {
  width: 60px;
  height: 60px;
}
.diy-service .service-icon {
  height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
}
.diy-service .service-icon img {
  width: 40px;
  height: 40px;
}
</style>
supplier_vue/src/views/page/page/diy/model/Setpages.vue
New file
@@ -0,0 +1,77 @@
<template>
  <!--
        作者:luoyiming
        时间:2020-06-20
        描述:diy组件-模拟显示-顶部设置栏
    -->
  <div class="phone-top" v-if="diyData.page" @click.stop="$parent.onEditer(-1)"
    :style="'background:' + diyData.page.style.titleBackgroundColor">
    <div class="status-bar">
      <span class="icon iconfont icon-wifi" :style="'color:' + diyData.page.style.titleTextColor">
      </span>
      <span class="time" :style="'color:' + diyData.page.style.titleTextColor">19:00</span>
      <span class="icon iconfont icon-xinhao" :style="'color:' + diyData.page.style.titleTextColor">
      </span>
      <span class="ml4 icon iconfont icon-iconset0250" :style="'color:' + diyData.page.style.titleTextColor">
      </span>
    </div>
    <div class="navigation d-s-c" :style="'color:' + diyData.page.style.titleTextColor">
      <img style="width: 30px;height: 30px;" :src="diyData.page.style.toplogo" alt="">
      <div class="phone-top-search-box" :style="'color:' + diyData.page.style.titleBackgroundColor"><i
          class="el-icon-search"></i>搜索商品</div>
      <!-- <div style="width: 100px;" class=""></div> -->
    </div>
    <div  v-if="diyData.page.category.open" class="d-s-c" :style="'color:' +  diyData.page.category.color">
      <div class="f16 mr10">分类一</div>
      <div class="f16 mr10">分类二</div>
      <div class="f16 mr10">分类三</div>
      <div class="f16 mr10">分类四</div>
    </div>
  </div>
</template>
<script>
  export default {
    data() {
      return {};
    },
    props: {
      diyData: Object
    },
    methods: {
      getImg(src) {
        var img_url = src
        var img = new Image()
        img.src = img_url;
        return Math.ceil(img.width * 60 / img.height) + 'px'
      },
    }
  };
</script>
<style>
  .phone-top-search-box {
    flex: 1;
    height: 30px;
    line-height: 30px;
    background-color: #FFFFFF;
    border-radius: 3px;
    margin-left: 10px;
    color: #999999;
    font-size: 13px;
    text-align: left;
    padding-left: 10px;
    border-radius: 15px;
    font-weight: 800;
  }
  .phone-top-search-box .el-icon-search {
    font-weight: 800;
    margin-right: 4px;
  }
  .navigation>img {
    width: 30px;
    height: 30px;
  }
</style>
supplier_vue/src/views/page/page/diy/model/Special.vue
New file
@@ -0,0 +1,54 @@
<template>
  <!--
        作者:wangxw
        时间:2019-11-05
        描述:diy组件 头条快报
    -->
    <div @click.stop="$parent.$parent.onEditer(index)">
      <div class="drag optional" :class="{selected:index === selectedIndex}">
        <div class="diy-special">
          <div class="special-left">
            <img v-img-url="item.style.image" alt="">
          </div>
          <div class="special-content" :class="'display_' + item.style.display">
            <ul class="special-content-list">
              <li class="content-item text-ellipsis" v-for="(item,index) in (item.params.source == 'choice' ? item.data : item.defaultData)" :key="index">
                <span>{{ item.article_title }}</span>
              </li>
            </ul>
          </div>
          <div class="special-more">
            <i class="el-icon-arrow-right"></i>
          </div>
        </div>
        <div class="btn-edit-del">
          <div class="btn-del" @click.stop="$parent.$parent.onDeleleItem(index)">删除</div>
        </div>
      </div>
    </div>
</template>
<script>
  export default {
    data() {
      return {
      };
    },
    props: ['item', 'index', 'selectedIndex'],
    methods: {
    }
  };
</script>
<style>
.diy-special{ padding: 4px; display: flex; justify-content: space-between; align-items: center;}
.diy-special .special-left{ width: 68px; height: 16px;}
.diy-special .special-left img{ width: 100%; height: 100%;}
.diy-special .special-more{ font-size: 18px;}
.diy-special .special-content{ flex: 1; margin: 0 10px; overflow: hidden;}
.diy-special .content-item{ padding: 4px 0;}
.diy-special .special-content.display_1{ height: 22px;}
.diy-special .special-content.display_2{ height: 44px;}
</style>
supplier_vue/src/views/page/page/diy/model/Store.vue
New file
@@ -0,0 +1,70 @@
<template>
  <!--
        作者:luoyiming
        时间:2020-06-20
        描述:diy组件-模拟显示-线下门店
    -->
    <div @click.stop="$parent.$parent.onEditer(index)">
      <div class="drag optional" :class="{selected:index === selectedIndex}" :style="{ background: item.style.background }">
        <div class="diy-shop">
          <div class="diy-head d-b-c">
            <div class="left d-s-c">
              <div class="name">
                线下门店
              </div>
            </div>
          </div>
          <div class="shop-item" :key="index" v-for="(shop, index) in (item.params.source == 'choice' ? item.data : item.defaultData)">
            <div class="shop-item-logo">
              <img v-img-url="shop.logo_image" alt="门店logo">
            </div>
            <div class="shop-item-content">
              <div class="shop-item-title">
                <span>{{ shop.shop_name }}</span>
              </div>
              <div class="shop-item-address">
                <span>门店地址:{{ shop.region.province }}{{ shop.region.city }}{{ shop.region.region }}{{ shop.address }}</span>
              </div>
              <div class="shop-item-phone">
                <span>联系电话:{{ shop.phone }}</span>
              </div>
            </div>
          </div>
        </div>
        <div class="btn-edit-del">
          <div class="btn-del" @click.stop="$parent.$parent.onDeleleItem(index)">删除</div>
        </div>
      </div>
  </div>
</template>
<script>
  export default {
    data() {
      return {
      };
    },
    props: ['item', 'index', 'selectedIndex'],
    methods: {
    }
  };
</script>
<style>
.diy-shop .diy-head {
    height: 40px;
  }
.diy-shop .diy-head .name {
    font-size: 18px;
    font-weight: bold;
  }
.diy-shop .shop-item{ display: flex; justify-content: flex-start; align-items: center;}
.diy-shop .shop-item-logo, .diy-shop .shop-item-logo img{ width: 60px; height: 60px; border-radius: 50%;}
.diy-shop .shop-item{ padding: 10px;}
.diy-shop .shop-item .shop-item-content{ margin-left: 10px;}
.diy-shop .shop-item .shop-item-title{ font-size: 16px; color:rgb(255, 51, 0);}
.diy-shop .shop-item .shop-item-address{ padding-top: 6px; color: #999999;}
.diy-shop .shop-item .shop-item-phone{ padding-top: 6px; color: #999999;}
</style>
supplier_vue/src/views/page/page/diy/model/Tab.vue
New file
@@ -0,0 +1,66 @@
<template>
    <!--
          作者:lyzflash
          时间:2023-08-10
          描述:diy组件-模拟显示-选项卡组
      -->
    <div @click.stop="$parent.$parent.onEditer(index)">
      <div class="drag optional" :class="{selected:index === selectedIndex}">
        <div class="diy-tab-box" :style="{background:item.style.background}">
          <ul class="list tab-list" :class="item.style.show_type==2?'tab-nowrap':'tab-flex d-b-c'">
            <li class="item" :key="index" v-for="(navBar,index) in item.data" :style="index==0?'background:'+item.style.background_active:''">
              <div class="item-text" :class="item.style.show_type==1?'text-ellipsis':''" :style="index==0?'color:'+item.style.text_active:'color:'+navBar.color">{{navBar.text}}</div>
            </li>
          </ul>
        </div>
        <div class="btn-edit-del">
          <div class="btn-del" @click.stop="$parent.$parent.onDeleleItem(index)">删除</div>
        </div>
      </div>
    </div>
</template>
<script>
  export default {
    data() {
      return {
      };
    },
    props: ['item', 'index', 'selectedIndex'],
    methods: {
    }
  };
</script>
<style>
.diy-tab-box .list{ display: flex; flex-wrap: wrap; align-items: flex-start;}
.diy-tab-box .list .item{ padding: 10px 20px; display: flex; justify-content: center; align-items: center; flex-direction: column;}
.diy-tab-box .list .item-text{ width: 100%; padding: 4px 0; text-align: center;}
.diy-tab-box .tab-list li {
  position: relative;
}
.diy-tab-box .tab-list li:before {
  content: '';
  position: absolute;
  left: 0;
  top: 5px;
  bottom: 5px;
  border-left: 1px solid #eee;
}
.diy-tab-box .button-list li:first-child:before {
  border: 0;
}
.tab-flex .item {
  flex: 1;
}
.diy-tab-box .tab-nowrap {
  display: block;
  white-space: nowrap;
  overflow: hidden;
}
.diy-tab-box .tab-nowrap .item {
  display: inline-block;
}
</style>
supplier_vue/src/views/page/page/diy/model/Title.vue
New file
@@ -0,0 +1,78 @@
<template>
  <!--
        作者:wangxw
        时间:2019-11-05
        描述:diy组件 搜索栏
    -->
  <div>
    <div @click.stop="$parent.$parent.onEditer(index)">
      <div class="drag optional" :class="{selected:index === selectedIndex}">
        <div class="diy-title"
          :style="{padding: item.style.paddingTop + 'px' + ' 10px', background: item.style.background}">
          <div class="title-icon pr" v-if="item.params.show_icon == 'yes'" :style="{background: item.style.background}">
            <img v-img-url="item.params.icon">
          </div>
          <span class="title-text text-ellipsis pr"  :style="{color: item.style.textColor,background: item.style.background}">
            {{item.params.title}}
          </span>
          <div class="title-line"></div>
        </div>
        <div class="btn-edit-del">
          <div class="btn-del" @click.stop="$parent.$parent.onDeleleItem(index)">删除</div>
        </div>
      </div>
    </div>
  </div>
</template>
<script>
  export default {
    data() {
      return {
      };
    },
    props: ['item', 'index', 'selectedIndex'],
    methods: {
    }
  };
</script>
<style>
  .optional .diy-title {
    display: flex;
    justify-content: center;
    align-items: center;
  }
  .optional .diy-title .title-icon {
    width: 32px;
    height: 32px;
    padding: 5px;
    z-index: 1;
  }
  .diy-title .title-text {
    overflow: hidden;
    white-space: nowrap;
    padding: 0 5px;
    z-index: 1;
    font-size: 19px;
    font-weight: 800;
  }
  .title-line {
    width: 245px;
    height: 1px;
    background-color: #c7c7c7;
    border-radius: 1px;
    position: absolute;
    left: 0;
    bottom: 0;
    top: 0;
    right: 0;
    margin: auto;
    z-index: 0;
  }
</style>
supplier_vue/src/views/page/page/diy/model/Video.vue
New file
@@ -0,0 +1,41 @@
<template>
  <!--
        作者:wangxw
        时间:2019-11-05
        描述:diy组件 视频
    -->
    <div class="pr">
      <div class="cover-box"  @click.stop="$parent.$parent.onEditer(index)"></div>
      <div class="drag-optional" :class="{selected:index === selectedIndex}">
        <div class="diy-video" :style="{padding:item.style.paddingTop + 'px 0'}">
          <video :style="{height:item.style.height + 'px'}" :src="item.params.videoUrl" :poster="item.params.poster"
            :autoplay="item.params.autoplay == 1" controls>
            您的浏览器不支持 video 标签
          </video>
        </div>
        <div class="btn-edit-del">
          <div class="btn-del" @click.stop="$parent.$parent.onDeleleItem(index)">删除</div>
        </div>
      </div>
    </div>
</template>
<script>
  export default {
    data() {
      return {
      };
    },
    props: ['item', 'index', 'selectedIndex'],
    methods: {
    }
  };
</script>
<style>
.diy-video video{ display: block; width: 100%;}
.cover-box{ position: absolute; top: 0; left: 0; width: 100%; height: 100%; z-index: 10;}
</style>
supplier_vue/src/views/page/page/diy/model/Window.vue
New file
@@ -0,0 +1,81 @@
<template>
  <!--
        作者:wangxw
        时间:2019-11-05
        描述:diy组件 图片橱窗
    -->
    <div @click.stop="$parent.$parent.onEditer(index)">
      <div class="drag optional" :class="{selected:index === selectedIndex}">
        <div class="diy-window" :style="{ background: item.style.background, padding: item.style.paddingTop + 'px ' + item.style.paddingLeft + 'px' }">
          <ul class="data-list" v-if="item.style.layout > -1" :class="'column__' + item.style.layout">
            <li :key="index" v-for="(window,index) in item.data" :style="{ padding: item.style.paddingTop + 'px ' + item.style.paddingLeft + 'px' }">
              <div class="item-image">
                <img v-img-url="window.imgUrl">
              </div>
            </li>
          </ul>
          <div class="display" v-else :style="{ padding:item.style.paddingTop + 'px ' + item.style.paddingLeft + 'px' }">
            <div class="percent-w50">
              <div class="img-box-wrap-1">
                <div class="img-box">
                  <img v-img-url="item.data[0].imgUrl" />
                </div>
              </div>
            </div>
            <div class="percent-w50 d-s-c d-c">
              <div class="img-box-wrap-2" v-if="item.data.length >= 2">
               <div class="img-box">
                  <img v-img-url="item.data[1].imgUrl" />
                </div>
              </div>
              <div class="d-s-c img-box-wrap-3">
                <div class="img-box-wrap-4" v-if="item.data.length >= 3">
                  <div class="img-box">
                    <img v-img-url="item.data[2].imgUrl" />
                  </div>
                </div>
                <div class="img-box-wrap-4" v-if="item.data.length >= 4" >
                  <div class="img-box">
                    <img v-img-url="item.data[3].imgUrl" />
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>
        <div class="btn-edit-del">
          <div class="btn-del" @click.stop="$parent.$parent.onDeleleItem(index)">删除</div>
        </div>
      </div>
    </div>
</template>
<script>
  export default {
    data() {
      return {
      };
    },
    props: ['item', 'index', 'selectedIndex'],
    methods: {
    }
  };
</script>
<style>
.diy-window .data-list{ display: flex; flex-wrap: wrap;}
.diy-window .data-list.column__2 li{width: 50%; }
.diy-window .data-list.column__3 li{width: 33.333333333333%; }
.diy-window .data-list.column__4 li{width: 25%; }
.diy-window .data-list.column__5 li{width: 50%; }
.diy-window .display{ display: flex;}
.diy-window .display .img-box-wrap-1{ position: relative; padding-bottom: 100%;}
.diy-window .display .img-box-wrap-2{position: relative; width: 100%; height: 50%;}
.diy-window .display .img-box{ position: absolute; top: 0; right: 0; bottom: 0; left: 0;}
.diy-window .display .img-box img{ height: 100%;}
.diy-window .display .img-box-wrap-3{ width: 100%; height: 50%;}
.diy-window .display .img-box-wrap-4{ position: relative; width: 50%; height: 100%;}
</style>
supplier_vue/src/views/page/page/diy/model/assembleProduct.vue
New file
@@ -0,0 +1,221 @@
<template>
  <!--
        作者:luoyiming
        时间:2020-06-20
        描述:diy组件-模拟显示-限时拼团
    -->
  <div class="drag optional" :class="{ selected: index === selectedIndex }"
    @click.stop="$parent.$parent.onEditer(index)">
    <div class="diy-sharpproduct" style="background: #ffffff">
      <div class="sharpproduct-head d-b-c">
        <img v-img-url="item.style.background_image" />
      </div>
      <ul class="product-list assemble" :class="['column__3']" :style="getUlwidth(item)">
        <li class="product-item" v-for="(product, index) in item.data" :key="index">
          <div v-if="item.style.show.productName == '1'" class="product-title">{{ product.product_name }}</div>
          <div class="d-b-s">
            <div class="product-cover">
              <img v-img-url="product.image" />
              <div class="desc-situation product-sale">
                <span class="">2人团</span>
              </div>
            </div>
            <div class="flex-1">
              <div class="">
                <div class="f12">
                  <div>
                    <span v-if="item.style.show.assemblePrice == '1'" style="color:#f6220c;" class="f12">¥</span><span
                      style="color:#f6220c;" class="f16 fb" v-if="item.style.show.assemblePrice == '1'">233.00</span>
                  </div>
                  <div v-if="item.style.show.linePrice == '1'" class="text-d-line-through gray9">¥233</div>
                </div>
              </div>
              <div class="assemble_btns">去开团</div>
            </div>
          </div>
        </li>
      </ul>
    </div>
    <div class="btn-edit-del">
      <div class="btn-del" @click.stop="$parent.$parent.onDeleleItem(index)">删除</div>
    </div>
  </div>
</template>
<script>
  export default {
    data() {
      return {
        /*商品列表*/
        tableData: [],
        /*分类id*/
        category_id: 0
      };
    },
    created() {},
    props: ['item', 'index', 'selectedIndex'],
    methods: {
      /*计算宽度*/
      getUlwidth(item) {
        if (item.style.display == 'slide') {
          let total = 0;
          if (item.params.source == 'choice') {
            total = item.data.length;
          } else {
            total = item.defaultData.length;
          }
          let w = 0;
          if (item.style.column == 2) {
            w = total * 150;
          } else {
            w = total * 100;
          }
          return 'width:' + w + 'px;';
        }
      }
    }
  };
</script>
<style scoped>
  .diy-sharpproduct {
    padding: 3px 10px;
    background-color: #F2F2F2;
  }
  .diy-sharpproduct .product-list.assemble {
    display: flex;
    justify-content: flex-start;
    flex-wrap: wrap;
    background-color: #FFFFFF;
  }
  .diy-sharpproduct .product-list.assemble .product-title {
    height: 40px;
    line-height: 20px;
    display: -webkit-box;
    overflow: hidden;
    -webkit-line-clamp: 1;
    -webkit-box-orient: vertical;
    margin-bottom: 18px;
  }
  .diy-sharpproduct .product-list.assemble .price {
    margin: 0 auto;
    margin-top: 10px;
    margin-bottom: 15px;
    width: 100%;
    display: -webkit-box;
    overflow: hidden;
    -webkit-line-clamp: 1;
    -webkit-box-orient: vertical;
    text-align: center;
  }
  .diy-sharpproduct .display__list .column__3 {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
  }
  .diy-sharpproduct .product-list.assemble.column__3 {
    overflow-x: scroll;
    flex-wrap: nowrap;
    background: #FFFFFF;
  }
  .diy-sharpproduct .product-list.assemble.column__3 .product-item {
    width: 221px;
    margin-right: 10px;
    overflow: hidden;
    margin-bottom: 10px;
    background: #ffffff;
    flex-shrink: 0;
    margin-right: 10px;
    background: linear-gradient(180deg, #FFEFE8 0%, #FFFFFF 100%);
    padding: 15px;
    box-sizing: border-box;
  }
  .diy-sharpproduct .product-list.assemble.column__3 .product-item .product-cover {
    width: 63px;
    height: 57px;
    border-radius: 3px;
    background-color: #f6f6f6;
    overflow: hidden;
    position: relative;
  }
  .diy-sharpproduct .product-list.assemble.column__3 .product-item .product-cover img {
    width: 63px;
    height: 57px;
    border-radius: 3px;
  }
  .diy-sharpproduct .product-list.assemble.column__3 .product-item .product-cover .desc-situation {
    position: absolute;
    bottom: 1px;
    left: 1px;
    background: linear-gradient(60deg, #FC4528 0%, #FC573C 43%, #FC7639 100%);
    color: #FFFFFF !important;
    padding: 0 3px;
    border-top-left-radius: 6px;
    border-bottom-right-radius: 6px;
  }
  .diy-sharpproduct .product-list.assemble.column__3 .product-title {
    margin: 0 auto;
    margin-bottom: 8px;
    width: 100%;
    height: 36px;
    line-height: 18px;
    display: -webkit-box;
    overflow: hidden;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    font-size: 12px;
  }
  .sharpproduct-head {
    height: 40px;
    border-top-left-radius: 6px;
    border-top-right-radius: 6px;
  }
  .sharpproduct-head .name.assemble_name {
    font-size: 18px;
    font-weight: bold;
    color: #333333;
  }
  .sharpproduct-head .datetime {
    margin-left: 20px;
  }
  .sharpproduct-head .datetime>span {
    display: inline-block;
  }
  .sharpproduct-head .datetime .text {
    padding: 0 2px;
  }
  .sharpproduct-head .datetime .box {
    padding: 2px;
    background: #000000;
    color: #ffffff;
  }
  .diy-sharpproduct .product-list.assemble .assemble_btns {
    line-height: 20px;
    font-size: 10px;
    text-align: center;
    color: #FFFFFF;
    width: 63px;
    height: 20px;
    background: #FF4C01;
    border-radius: 10px;
  }
</style>
supplier_vue/src/views/page/page/diy/params/Article.vue
New file
@@ -0,0 +1,77 @@
<template>
  <!--
        作者:luoyiming
        时间:2020-06-20
        描述:diy组件-参数设置-文章列表
    -->
    <div>
        <div class="common-form">
            <span>{{ curItem.name }}</span>
        </div>
        <el-form size="small" :model="curItem" label-width="100px">
            <!-- 文章分类 -->
            <el-form-item label="文章分类:">
              <el-select v-model="curItem.params.auto.category">
                <el-option label="全部分类" :value="''+0"></el-option>
                  <el-option
                    v-for="item in category"
                    :key="item.category_id"
                    :label="item.name"
                    :value="''+item.category_id">
                  </el-option>
              </el-select>
            </el-form-item>
            <!-- 显示数量 -->
            <el-form-item label="显示数量:">
                <el-input type="number" style="width: auto;" v-model="curItem.params.auto.showNum"
                          class="w-auto"></el-input>
                <div>
                    文章数据请到
                    <a href="#" target="_blank">内容管理 - 文章列表</a>
                    中管理
                </div>
            </el-form-item>
            <!--显示类型-->
            <el-form-item label="显示类型:">
              <el-radio-group v-model="curItem.style.display">
                <el-radio label="10">有图模式</el-radio>
                <el-radio label="20">无图模式</el-radio>
              </el-radio-group>
            </el-form-item>
        </el-form>
    </div>
</template>
<script>
    import ArticleApi from '@/api/article.js';
    export default {
        data() {
            return {
                category: {},
            };
        },
        props: ['curItem', 'selectedIndex', 'opts'],
        created() {
            /*获取文章栏目*/
            this.getData();
        },
        methods: {
            /*获取文章栏目*/
            getData() {
                let self = this;
                ArticleApi.getCategory({
                    page_id: self.page_id
                }, true).then(data =>
                {
                    self.category = data.data.category;
                })
                    .catch(error =>
                    {
                        self.loading = false;
                    });
            },
        }
    };
</script>
<style></style>
supplier_vue/src/views/page/page/diy/params/Banner.vue
New file
@@ -0,0 +1,112 @@
<template>
  <!--
        作者:luoyiming
        时间:2020-06-20
        描述:diy组件-参数设置-轮播图
    -->
  <div>
    <div class="common-form">
      <span>{{ curItem.name }}</span>
    </div>
    <el-form size="small" :model="curItem" label-width="100px">
      <el-form-item label="轮播图显示:">
        <el-radio-group v-model="curItem.style.imgShape">
          <el-radio label="round">圆形</el-radio>
          <el-radio label="square">正方形</el-radio>
        </el-radio-group>
      </el-form-item>
      <el-form-item label="指示点形状:">
        <el-radio-group v-model="curItem.style.btnShape">
          <el-radio label="round">圆形</el-radio>
          <el-radio label="square">正方形</el-radio>
          <el-radio label="rectangle">长方形</el-radio>
        </el-radio-group>
      </el-form-item>
      <el-form-item label="图片宽度(px):">
        <el-input placeholder="请输入图片宽度" value="750" disabled></el-input>
      </el-form-item>
      <el-form-item label="图片高度(px):">
        <el-input placeholder="请输入图片高度" v-model="curItem.style.height"></el-input>
      </el-form-item>
      <el-form-item label="指示点颜色:">
        <div class="d-s-c">
          <el-color-picker v-model="curItem.style.btnColor"></el-color-picker>
          <el-button type="button" style="margin-left: 10px;"
            @click.stop="$parent.onEditorResetColor(curItem.style, 'btnColor', '#ffffff')">重置
          </el-button>
        </div>
      </el-form-item>
      <el-form-item label="背景颜色:">
        <div class="d-s-c">
          <el-color-picker v-model="curItem.style.background"></el-color-picker>
          <el-button type="button" style="margin-left: 10px;"
            @click.stop="$parent.onEditorResetColor(curItem.style, 'background', '#ffffff')">重置
          </el-button>
        </div>
      </el-form-item>
      <el-form-item label="切换时间:">
        <el-input v-model="curItem.params.interval"></el-input>
        <p>轮播图自动切换的间隔时间,单位:毫秒</p>
      </el-form-item>
      <el-form-item label="图片:">
        <div class="param-img-item" :key="index" v-for="(banner, index) in curItem.data">
          <div class="delete-box"><i class="el-icon-delete-solid"
              @click="$parent.onEditorDeleleData(index, selectedIndex)"></i></div>
          <div class="pic">
            <img v-img-url="banner.imgUrl" alt="" @click="$parent.onEditorSelectImage(banner, 'imgUrl')" />
          </div>
          <div class="d-s-c">
            <div class="url-box flex-1">
              <span class="key-name">链接地址:</span>
              <el-input placeholder="请选择链接地址" v-model="banner.name"></el-input>
            </div>
            <div class="url-box ml10">
              <el-button type="primary" @click="changeLink(index)">选择链接</el-button>
            </div>
          </div>
        </div>
        <div class="d-c-c">
          <el-button @click="$parent.onEditorAddData">添加一个</el-button>
        </div>
      </el-form-item>
    </el-form>
    <Setlink v-if="is_linkset" :is_linkset="is_linkset" @closeDialog="closeLinkset">选择链接</Setlink>
  </div>
</template>
<script>
  import Setlink from '@/components/setlink/Setlink';
  export default {
    components: {
      Setlink
    },
    data() {
      return {
        /*是否选择链接*/
        is_linkset: false,
        index: null
      };
    },
    props: ['curItem', 'selectedIndex'],
    methods: {
      /*选择链接*/
      changeLink(index) {
        this.is_linkset = true;
        this.index = index;
      },
      /*获取链接并关闭弹窗*/
      closeLinkset(e) {
        this.is_linkset = false;
        if (e) {
          this.curItem.data[this.index].type=e.type;
          this.curItem.data[this.index].inputname=e.name;
          this.curItem.data[this.index].linkUrl = e.url;
          this.curItem.data[this.index].name = '链接到' + ' ' + e.type + ' ' + e.name;
        }
      }
    }
  };
</script>
<style></style>
supplier_vue/src/views/page/page/diy/params/BargainProduct.vue
New file
@@ -0,0 +1,97 @@
<template>
  <!--
    作者:luoyiming
    时间:2020-06-20
    描述:diy组件-参数设置-砍价
-->
  <div>
    <div class="common-form">
      <span>{{ curItem.name }}</span>
    </div>
    <el-form size="small" :model="curItem" label-width="100px">
      <!--显示数量-->
      <el-form-item label="显示数量:">
        <el-input v-model="curItem.params.showNum" class="w-auto"></el-input>
      </el-form-item>
      <!-- 文字颜色 -->
      <el-form-item label="时间颜色:">
          <div class="d-s-c">
              <el-color-picker v-model="curItem.style.color"></el-color-picker>
              <el-button type="button" style="margin-left: 10px;"
                  @click.stop="$parent.onEditorResetColor(curItem.style, 'color', '#ffffff')">重置
              </el-button>
          </div>
      </el-form-item>
      <el-form-item label="日期文字:">
          <div class="d-s-c">
              <el-color-picker v-model="curItem.style.countdown_color"></el-color-picker>
              <el-button type="button" style="margin-left: 10px;"
                  @click.stop="$parent.onEditorResetColor(curItem.style, 'countdown_color', '#FF02A8')">重置
              </el-button>
          </div>
      </el-form-item>
      <el-form-item label="日期背景:">
          <div class="d-s-c">
              <el-color-picker v-model="curItem.style.countdown_back_color"></el-color-picker>
              <el-button type="button" style="margin-left: 10px;"
                  @click.stop="$parent.onEditorResetColor(curItem.style, 'countdown_back_color', '#FEE24F')">重置
              </el-button>
          </div>
      </el-form-item>
      <el-form-item label="背景图片:">
        <div class="diy-notice-icon">
          <img v-img-url="curItem.style.background_image" alt="" @click="$parent.onEditorSelectImage(curItem.style, 'background_image')">
        </div>
        <div>建议尺寸700×90</div>
      </el-form-item>
      <!--组件样式-->
      <div class="p-10-0 mb16 f14 border-b">
        <span class="gray6">组件样式</span>
      </div>
      <!-- 商品排序 -->
      <el-form-item label="显示内容:">
        <el-checkbox v-model="productName" @change="checked=>check(checked, 'productName')">商品名称</el-checkbox>
        <el-checkbox v-model="peoples" @change="checked=>check(checked, 'peoples')">正在砍价</el-checkbox>
        <el-checkbox v-model="floorPrice" @change="checked=>check(checked, 'floorPrice')">砍价底价</el-checkbox>
        <el-checkbox v-model="originalPrice" @change="checked=>check(checked, 'originalPrice')">商品原价</el-checkbox>
      </el-form-item>
    </el-form>
  </div>
</template>
<script>
  export default {
    data() {
      return {
        /*商品名称*/
        productName: false,
        /*正在砍价*/
        peoples: false,
        /*砍价底价*/
        floorPrice: false,
        /*商品价格*/
        originalPrice: false
      };
    },
    props: ['curItem', 'selectedIndex', 'opts'],
    created() {
      /*获取列表*/
      //this.getData();
      this.productName = this.curItem.style.show.productName == '1' ? true : false;
      this.peoples = this.curItem.style.show.peoples == '1' ? true : false;
      this.floorPrice = this.curItem.style.show.floorPrice == '1' ? true : false;
      this.originalPrice = this.curItem.style.show.originalPrice == '1' ? true : false;
    },
    methods: {
      /*内容是否选择*/
      check(checked, name) {
        let value = checked ? '1' : '0';
        this.curItem.style.show[name] = value;
      },
    }
  };
</script>
<style>
</style>
supplier_vue/src/views/page/page/diy/params/Blank.vue
New file
@@ -0,0 +1,46 @@
<template>
  <!--
        作者:wangxw
        时间:2019-11-05
        描述:diy组件 搜索栏
    -->
  <div>
    <div class="common-form">
      <span>{{ curItem.name }}</span>
    </div>
    <el-form size="small" :model="curItem" label-width="100px">
      <!-- 背景颜色 -->
      <el-form-item label="背景颜色:">
        <div class="d-s-c">
          <el-color-picker v-model="curItem.style.background"></el-color-picker>
          <el-button type="button" style="margin-left: 10px;" @click.stop="$parent.onEditorResetColor(curItem.style, 'background', '#ffffff')">重置</el-button>
        </div>
      </el-form-item>
      <!--组件高度-->
      <el-form-item label="组件高度:">
        <el-slider v-model="curItem.style.height" :min="1" :max='200' show-input></el-slider>
      </el-form-item>
    </el-form>
   </div>
</template>
<script>
  export default {
    data() {
      return {
      };
    },
    props: ['curItem', 'selectedIndex', 'opts'],
    created() {
      this.curItem.style.height = parseInt(this.curItem.style.height);
    },
    methods: {
    }
  };
</script>
<style>
</style>
supplier_vue/src/views/page/page/diy/params/Button.vue
New file
@@ -0,0 +1,99 @@
<template>
  <!--
        作者:lyzflash
      时间:2023-08-10
      描述:diy组件-模拟显示-按钮组
    -->
  <div>
    <div class="common-form"><span>{{ curItem.name }}</span></div>
    <el-form size="small" :model="curItem" label-width="100px">
      <!--背景颜色-->
      <el-form-item label="背景颜色:">
        <div class="d-s-c">
            <el-color-picker v-model="curItem.style.background"></el-color-picker>
            <el-button type="button" style="margin-left: 10px;" @click.stop="$parent.onEditorResetColor(curItem.style, 'background', '#ffffff')">
              重置
            </el-button>
        </div>
      </el-form-item>
      <!--每行数量-->
      <el-form-item label="按钮数量:">
        <el-radio-group v-model="curItem.style.rowsNum">
            <el-radio label="2">2个</el-radio>
            <el-radio label="3">3个</el-radio>
          </el-radio-group>
      </el-form-item>
      <el-form-item label="内容:">
        <div class="param-img-item" :key="index" v-for="(navBar, index) in curItem.data" v-if="index<curItem.style.rowsNum">
          <div class="delete-box">
            <i class="el-icon-delete-solid" @click="$parent.onEditorDeleleData(index, selectedIndex)"></i>
          </div>
          <div class="url-box">
            <span class="key-name">文字内容:</span>
            <el-input v-model="navBar.text" class="max-w460"></el-input>
          </div>
          <div class="url-box">
            <span class="key-name">颜色:</span>
            <div class="d-s-c">
                <el-color-picker v-model="navBar.color"></el-color-picker>
                <el-button type="button" style="margin-left: 10px;" @click.stop="$parent.onEditorResetColor(navBar, 'color', '#666666')">
                  重置
                </el-button>
            </div>
          </div>
          <div class="d-s-c">
            <div class="url-box flex-1">
            <span class="key-name">链接名称:</span>
            <el-input v-model="navBar.name"></el-input>
          </div>
          <div class="url-box ml10">
            <el-button type="primary" @click="changeLink(index)">选择链接</el-button>
          </div>
          </div>
        </div>
        <div class="d-c-c" v-if="curItem.data.length<curItem.style.rowsNum">
          <el-button @click="$parent.onEditorAddData">添加一个</el-button>
        </div>
      </el-form-item>
    </el-form>
    <Setlink v-if="is_linkset" :is_linkset="is_linkset" @closeDialog="closeLinkset">选择链接</Setlink>
  </div>
</template>
<script>
    import Setlink from '@/components/setlink/Setlink';
  export default {
      components: {
          Setlink,
      },
    data() {
      return {
        /*是否选择链接*/
          is_linkset: false,
          index: null,
      };
    },
    props: ['curItem', 'selectedIndex', 'opts'],
    methods: {
      /*选择链接*/
        changeLink(index) {
            this.is_linkset = true;
            this.index = index;
        },
      /*获取链接并关闭弹窗*/
        closeLinkset(e) {
            this.is_linkset = false;
            this.curItem.data[this.index].type=e.type;
            this.curItem.data[this.index].inputname=e.name;
            this.curItem.data[this.index].linkUrl=e.url;
            this.curItem.data[this.index].name = '链接到' + ' ' + e.type + ' ' + e.name;
        },
    }
  };
</script>
<style>
</style>
supplier_vue/src/views/page/page/diy/params/Coupon.vue
New file
@@ -0,0 +1,41 @@
<template>
  <!--
        作者:wangxw
        时间:2019-11-05
        描述:diy组件 搜索栏
    -->
  <div>
    <div class="common-form">
      <span>{{ curItem.name }}</span>
    </div>
    <el-form size="small" :model="curItem" label-width="100px">
      <!--上下边距-->
      <el-form-item label="上下边距:"><el-slider v-model="curItem.style.paddingTop" show-input></el-slider></el-form-item>
      <!--背景颜色-->
      <el-form-item label="背景颜色:">
        <div class="d-s-c">
          <el-color-picker v-model="curItem.style.background"></el-color-picker>
          <el-button type="button" style="margin-left: 10px;" @click.stop="$parent.onEditorResetColor(curItem.style, 'background', '#ffffff')">重置</el-button>
        </div>
      </el-form-item>
      <!--显示数量-->
      <el-form-item label="显示数量:"><el-slider v-model="curItem.params.limit" :min="1" :max="5" show-input></el-slider></el-form-item>
    </el-form>
  </div>
</template>
<script>
export default {
  data() {
    return {};
  },
  props: ['curItem', 'selectedIndex', 'opts'],
  created() {
    this.curItem.style.paddingTop = parseInt(this.curItem.style.paddingTop);
    this.curItem.params.limit = parseInt(this.curItem.params.limit);
  },
  methods: {}
};
</script>
<style></style>
supplier_vue/src/views/page/page/diy/params/Guide.vue
New file
@@ -0,0 +1,62 @@
<template>
  <!--
        作者:wangxw
        时间:2019-11-05
        描述:diy组件 辅助线
    -->
  <div>
    <div class="common-form">
      <span>{{ curItem.name }}</span>
    </div>
    <el-form size="small" :model="curItem" label-width="100px">
      <!--背景颜色-->
      <el-form-item label="背景颜色:">
        <div class="d-s-c">
          <el-color-picker v-model="curItem.style.background"></el-color-picker>
          <el-button type="button" style="margin-left: 10px;" @click.stop="$parent.onEditorResetColor(curItem.style, 'background', '#ffffff')">重置</el-button>
        </div>
      </el-form-item>
      <!-- 线条样式 -->
      <el-form-item label="线条样式:">
        <el-radio-group v-model="curItem.style.lineStyle">
          <el-radio :label="'solid'">实线</el-radio>
          <el-radio :label="'dashed'">虚线</el-radio>
          <el-radio :label="'dotted'">点状</el-radio>
        </el-radio-group>
      </el-form-item>
      <!--线条颜色-->
      <el-form-item label="线条颜色:">
        <div class="d-s-c">
          <el-color-picker v-model="curItem.style.lineColor"></el-color-picker>
          <el-button type="button" style="margin-left: 10px;" @click.stop="$parent.onEditorResetColor(curItem.style, 'lineColor', '#000000')">重置</el-button>
        </div>
      </el-form-item>
      <!--线条高度-->
      <el-form-item label="线条高度:"><el-slider v-model="curItem.style.lineHeight" show-input></el-slider></el-form-item>
      <!--线条高度-->
      <el-form-item label="上下边距:"><el-slider v-model="curItem.style.paddingTop" show-input></el-slider></el-form-item>
    </el-form>
  </div>
</template>
<script>
  export default {
    data() {
      return {
      };
    },
    props: ['curItem', 'selectedIndex', 'opts'],
    created() {
      this.curItem.style.lineHeight = parseInt(this.curItem.style.lineHeight);
      this.curItem.style.paddingTop = parseInt(this.curItem.style.paddingTop);
    },
    methods: {
    }
  };
</script>
<style>
</style>
supplier_vue/src/views/page/page/diy/params/ImageSingle.vue
New file
@@ -0,0 +1,93 @@
<template>
<!--
        作者:luoyiming
        时间:2020-06-20
        描述:diy组件-参数设置-单图组
    -->
    <div>
        <div class="common-form">
            <span>{{ curItem.name }}</span>
        </div>
        <el-form size="small" :model="curItem" label-width="100px">
            <!--上下边距-->
            <el-form-item label="上下边距:">
                <el-slider v-model="curItem.style.paddingTop" show-input></el-slider>
            </el-form-item>
            <!--左右边距-->
            <el-form-item label="左右边距:">
                <el-slider v-model="curItem.style.paddingLeft" :min="0" :max="50" show-input></el-slider>
            </el-form-item>
            <!--背景颜色-->
            <el-form-item label="背景颜色:">
                <div class="d-s-c">
                    <el-color-picker v-model="curItem.style.background"></el-color-picker>
                    <el-button type="button" style="margin-left: 10px;"
                               @click.stop="$parent.onEditorResetColor(curItem.style, 'background', '#ffffff')">重置
                    </el-button>
                </div>
            </el-form-item>
            <el-form-item label="图片:">
                <div class="param-img-item" :key="index" v-for="(imageSingle, index) in curItem.data">
                    <div class="delete-box"><i class="el-icon-delete-solid"
                                               @click="$parent.onEditorDeleleData(index, selectedIndex)"></i></div>
                    <div class="pic"><img v-img-url="imageSingle.imgUrl" alt=""
                                          @click="$parent.onEditorSelectImage(imageSingle, 'imgUrl')"/></div>
                    <div class="d-s-c">
                      <div class="url-box flex-1">
                          <span class="key-name">链接地址:</span>
                          <el-input v-model="imageSingle.name"></el-input>
                      </div>
                      <div class="url-box ml10">
                          <el-button type="primary" @click="changeLink(index)">选择链接</el-button>
                      </div>
                    </div>
                </div>
                <div class="d-c-c">
                    <el-button @click="$parent.onEditorAddData">添加一个</el-button>
                </div>
            </el-form-item>
        </el-form>
        <Setlink v-if="is_linkset" :is_linkset="is_linkset" @closeDialog="closeLinkset">选择链接</Setlink>
    </div>
</template>
<script>
    import Setlink from '@/components/setlink/Setlink';
    export default {
        components: {
            Setlink,
        },
        data() {
            return {
                /*是否选择链接*/
                is_linkset: false,
                index: null,
            };
        },
        props: ['curItem', 'selectedIndex'],
        created() {
          this.curItem.style.paddingTop = parseInt(this.curItem.style.paddingTop);
          this.curItem.style.paddingLeft = parseInt(this.curItem.style.paddingLeft);
        },
        methods: {
            /*选择链接*/
            changeLink(index) {
                this.is_linkset = true;
                this.index = index;
            },
            /*获取链接并关闭弹窗*/
            closeLinkset(e) {
                this.is_linkset = false;
                this.curItem.data[this.index].type=e.type;
                this.curItem.data[this.index].inputname=e.name;
                this.curItem.data[this.index].linkUrl=e.url;
//                this.curItem.data[this.index].name = e.name;
                this.curItem.data[this.index].name = '链接到' + ' ' + e.type + ' ' + e.name;
            },
        }
    };
</script>
<style>
</style>
supplier_vue/src/views/page/page/diy/params/Live.vue
New file
@@ -0,0 +1,55 @@
<template>
  <!--
        作者:luoyiming
        时间:2020-06-20
        描述:diy组件-参数设置-微信直播
    -->
  <div>
    <div class="common-form">
      <span>{{ curItem.name }}</span>
    </div>
    <el-form size="small" :model="curItem" label-width="100px">
      <!--显示数量-->
      <el-form-item label="显示数量:">
          <el-input v-model="curItem.params.showNum" class="w-auto"></el-input>
      </el-form-item>
      <!--组件样式-->
      <div class="p-10-0 mb16 f14 border-b">
          <span class="gray6">组件样式</span>
      </div>
      <!-- 文字颜色 -->
      <el-form-item label="文字颜色:">
          <div class="d-s-c">
              <el-color-picker v-model="curItem.style.color"></el-color-picker>
              <el-button type="button" style="margin-left: 10px;"
                  @click.stop="$parent.onEditorResetColor(curItem.style, 'color', '#000000')">重置
              </el-button>
          </div>
      </el-form-item>
      <el-form-item label="背景图片:">
        <div class="diy-notice-icon">
          <img v-img-url="curItem.style.background_image" alt="" @click="$parent.onEditorSelectImage(curItem.style, 'background_image')">
        </div>
        <div>建议尺寸700×90</div>
      </el-form-item>
    </el-form>
  </div>
</template>
<script>
export default {
  components: {},
  data() {
    return {};
  },
  props: ['curItem', 'selectedIndex'],
  created() {
    console.log(this.curItem);
  },
  methods: {}
};
</script>
<style>
  .diy-notice-icon, .diy-notice-icon img{ width: 350px; height: 45px;}
</style>
supplier_vue/src/views/page/page/diy/params/NavBar.vue
New file
@@ -0,0 +1,104 @@
<template>
  <!--
        作者:luoyiming
        时间:2020-06-20
        描述:diy组件-参数设置-导航组
    -->
  <div>
    <div class="common-form"><span>{{ curItem.name }}</span></div>
    <el-form size="small" :model="curItem" label-width="100px">
      <!--背景颜色-->
      <el-form-item label="背景颜色:">
        <div class="d-s-c">
            <el-color-picker v-model="curItem.style.background"></el-color-picker>
            <el-button type="button" style="margin-left: 10px;" @click.stop="$parent.onEditorResetColor(curItem.style, 'background', '#ffffff')">
              重置
            </el-button>
        </div>
      </el-form-item>
      <!--每行数量-->
      <el-form-item label="每行数量:">
        <el-radio-group v-model="curItem.style.rowsNum">
            <el-radio label="3">3个</el-radio>
            <el-radio label="4">4个</el-radio>
            <el-radio label="5">5个</el-radio>
          </el-radio-group>
      </el-form-item>
      <el-form-item label="图片:">
        <div class="param-img-item" :key="index" v-for="(navBar, index) in curItem.data">
          <div class="delete-box">
            <i class="el-icon-delete-solid" @click="$parent.onEditorDeleleData(index, selectedIndex)"></i>
          </div>
          <div class="icon">
            <img v-img-url="navBar.imgUrl" alt="" @click="$parent.onEditorSelectImage(navBar, 'imgUrl')">
          </div>
          <p class="tc gray9">建议尺寸100x100</p>
          <div class="url-box">
            <span class="key-name">文字内容:</span>
            <el-input v-model="navBar.text"></el-input>
          </div>
          <div class="url-box">
            <span class="key-name">颜色:</span>
            <div class="d-s-c">
                <el-color-picker v-model="navBar.color"></el-color-picker>
                <el-button type="button" style="margin-left: 10px;" @click.stop="$parent.onEditorResetColor(navBar, 'color', '#666666')">
                  重置
                </el-button>
            </div>
          </div>
          <div class="d-s-c">
            <div class="url-box flex-1">
            <span class="key-name">链接名称:</span>
            <el-input v-model="navBar.name"></el-input>
          </div>
          <div class="url-box ml10">
            <el-button type="primary" @click="changeLink(index)">选择链接</el-button>
          </div>
          </div>
        </div>
        <div class="d-c-c">
          <el-button @click="$parent.onEditorAddData">添加一个</el-button>
        </div>
      </el-form-item>
    </el-form>
    <Setlink v-if="is_linkset" :is_linkset="is_linkset" @closeDialog="closeLinkset">选择链接</Setlink>
  </div>
</template>
<script>
    import Setlink from '@/components/setlink/Setlink';
  export default {
      components: {
          Setlink,
      },
    data() {
      return {
        /*是否选择链接*/
          is_linkset: false,
          index: null,
      };
    },
    props: ['curItem', 'selectedIndex', 'opts'],
    methods: {
      /*选择链接*/
        changeLink(index) {
            this.is_linkset = true;
            this.index = index;
        },
      /*获取链接并关闭弹窗*/
        closeLinkset(e) {
            this.is_linkset = false;
            this.curItem.data[this.index].type=e.type;
            this.curItem.data[this.index].inputname=e.name;
            this.curItem.data[this.index].linkUrl=e.url;
            this.curItem.data[this.index].name = '链接到' + ' ' + e.type + ' ' + e.name;
        },
    }
  };
</script>
<style>
</style>
supplier_vue/src/views/page/page/diy/params/Notice.vue
New file
@@ -0,0 +1,62 @@
<template>
  <!--
        作者:wangxw
        时间:2019-11-05
        描述:diy组件 搜索栏
    -->
  <div>
    <div class="common-form">
      <span>{{ curItem.name }}</span>
    </div>
    <el-form size="small" :model="curItem" label-width="100px">
      <!--上下边距-->
      <el-form-item label="上下边距:"><el-slider v-model="curItem.style.paddingTop" show-input></el-slider></el-form-item>
      <!--背景颜色-->
      <el-form-item label="背景颜色:">
        <div class="d-s-c">
          <el-color-picker v-model="curItem.style.background"></el-color-picker>
          <el-button type="button" style="margin-left: 10px;" @click.stop="$parent.onEditorResetColor(curItem.style, 'background', '#ffffff')">重置</el-button>
        </div>
      </el-form-item>
      <!--文字颜色-->
      <el-form-item label="文字颜色:">
        <div class="d-s-c">
          <el-color-picker v-model="curItem.style.textColor"></el-color-picker>
          <el-button type="button" style="margin-left: 10px;" @click.stop="$parent.onEditorResetColor(curItem.style, 'textColor', '#000000')">重置</el-button>
        </div>
      </el-form-item>
      <!--公告图标-->
      <el-form-item label="公告图标:">
        <div class="diy-notice-icon">
          <img v-img-url="curItem.params.icon" alt="" @click="$parent.onEditorSelectImage(curItem.params, 'icon')">
        </div>
        <div>建议尺寸32×32</div>
      </el-form-item>
      <!-- 公告内容 -->
      <el-form-item label="公告内容:">
        <el-input v-model="curItem.params.text" class="w-auto"></el-input>
      </el-form-item>
    </el-form>
  </div>
</template>
<script>
  export default {
    data() {
      return {
      };
    },
    props: ['curItem', 'selectedIndex', 'opts'],
    created() {
      this.curItem.style.paddingTop = parseInt(this.curItem.style.paddingTop);
    },
    methods: {
    }
  };
</script>
<style>
.diy-notice-icon, .diy-notice-icon img{ width: 32px; height: 32px;}
</style>
supplier_vue/src/views/page/page/diy/params/Preview.vue
New file
@@ -0,0 +1,83 @@
<template>
<!--
        作者:luoyiming
        时间:2020-06-20
        描述:diy组件-参数设置-限时秒杀
    -->
    <div>
        <div class="common-form">
            <span>{{ curItem.name }}</span>
        </div>
        <el-form size="small" :model="curItem" label-width="100px">
            <!--显示数量-->
            <el-form-item label="显示数量:">
                <el-input v-model="curItem.params.showNum" class="w-auto"></el-input>
            </el-form-item>
            <!-- 文字颜色 -->
            <el-form-item label="时间颜色:">
                <div class="d-s-c">
                    <el-color-picker v-model="curItem.style.countdown_color"></el-color-picker>
                    <el-button type="button" style="margin-left: 10px;"
                        @click.stop="$parent.onEditorResetColor(curItem.style, 'countdown_color', '#ff4c01')">重置
                    </el-button>
                </div>
            </el-form-item>
            <el-form-item label="价格颜色:">
                <div class="d-s-c">
                    <el-color-picker v-model="curItem.style.color"></el-color-picker>
                    <el-button type="button" style="margin-left: 10px;"
                        @click.stop="$parent.onEditorResetColor(curItem.style, 'color', '#ff4c01')">重置
                    </el-button>
                </div>
            </el-form-item>
            <el-form-item label="时间背景颜色:">
                <div class="d-s-c">
                    <el-color-picker v-model="curItem.style.countdown_back_color"></el-color-picker>
                    <el-button type="button" style="margin-left: 10px;"
                        @click.stop="$parent.onEditorResetColor(curItem.style, 'countdown_back_color', '#fef7e4')">重置
                    </el-button>
                </div>
            </el-form-item>
            <el-form-item label="背景颜色:">
                <div class="d-s-c">
                    <el-color-picker v-model="curItem.style.background_color"></el-color-picker>
                    <el-button type="button" style="margin-left: 10px;"
                        @click.stop="$parent.onEditorResetColor(curItem.style, 'background_color', '#ff4c01')">重置
                    </el-button>
                </div>
            </el-form-item>
            <el-form-item label="背景顶部图片:">
              <div class="diy-notice-icon">
                <img v-img-url="curItem.style.background_image" alt="" @click="$parent.onEditorSelectImage(curItem.style, 'background_image')">
              </div>
              <div>建议尺寸710×90</div>
            </el-form-item>
            <el-form-item label="倒计时脚标:">
              <div class="diy-notice-icon">
                <img v-img-url="curItem.style.top_image" alt="" @click="$parent.onEditorSelectImage(curItem.style, 'top_image')">
              </div>
              <div>建议尺寸102×38</div>
            </el-form-item>
        </el-form>
    </div>
</template>
<script>
    export default {
        data() {
            return {
            };
        },
        props: ['curItem', 'selectedIndex'],
        created() {
        },
        methods: {
        }
    };
</script>
<style>
</style>
supplier_vue/src/views/page/page/diy/params/Product.vue
New file
@@ -0,0 +1,246 @@
<template>
  <!--
        作者:luoyiming
        时间:2020-06-20
        描述:diy组件-参数设置-商品栏
    -->
  <div>
    <div class="common-form">
      <span>{{ curItem.name }}</span>
    </div>
    <el-form size="small" :model="curItem" label-width="100px">
      <el-form-item label="商品来源:">
        <el-radio-group v-model="curItem.params.source">
          <el-radio :label="'auto'">自动获取</el-radio>
          <el-radio :label="'choice'">手动选择</el-radio>
        </el-radio-group>
      </el-form-item>
      <!-- 自动获取 -->
      <template v-if="curItem.params.source == 'auto'">
        <!-- 商品分类 -->
        <el-form-item label="商品分类:">
          <el-cascader
            class="ww100"
            v-model="currCategory"
            v-if="CategoryList.length > 0"
            ref="cascader"
            :options="CategoryList"
            :props="{ checkStrictly: true, children: 'child', value: 'category_id', label: 'name' }"
            @change="changeCategory"
            clearable
          ></el-cascader>
        </el-form-item>
        <!-- 商品排序 -->
        <el-form-item label="商品排序:">
          <el-radio-group v-model="curItem.params.auto.productSort">
            <el-radio :label="'all'">综合</el-radio>
            <el-radio :label="'sales'">销量</el-radio>
            <el-radio :label="'price'">价格</el-radio>
          </el-radio-group>
        </el-form-item>
        <!-- 显示数量 -->
        <el-form-item label="显示数量:"><el-input v-model="curItem.params.auto.showNum" class="w-auto"></el-input></el-form-item>
      </template>
      <!-- 手动选择 -->
      <template v-if="curItem.params.source == 'choice'">
        <el-form-item label="商品列表:">
          <div class="choice-product-list">
            <draggable v-model="curItem.data" :options = "{draggable:'.item',animation:500}">
              <transition-group class="d-s-c f-w">
                <div v-for="(product, index) in curItem.data" class="item" :key="product.product_id">
                  <div class="delete-box"><i class="el-icon-error" @click="$parent.onEditorDeleleData(index, selectedIndex)"></i></div>
                  <img v-img-url="product.image" alt="" />
                </div>
              </transition-group>
            </draggable>
          </div>
          <div>
            <el-button icon="el-icon-plus" @click.stop="$parent.openProduct(curItem.data,true)">选择产品</el-button>
          </div>
        </el-form-item>
      </template>
      <!--组件样式-->
      <div class="p-10-0 mb16 f14 border-b"><span class="gray6">组件样式</span></div>
      <!-- 背景颜色 -->
      <el-form-item label="背景颜色:">
        <div class="d-s-c">
          <el-color-picker v-model="curItem.style.background"></el-color-picker>
          <el-button type="button" style="margin-left: 10px;" @click.stop="$parent.onEditorResetColor(curItem.style, 'background', '#F6F6F6')">重置</el-button>
        </div>
      </el-form-item>
      <!-- 商品排序 -->
      <el-form-item label="商品排序:">
        <el-radio-group v-model="curItem.style.display">
          <el-radio :label="'list'">列表平铺</el-radio>
          <el-radio :label="'slide'" :disabled="curItem.style.column == 1">横向滑动</el-radio>
        </el-radio-group>
      </el-form-item>
      <!-- 商品排序 -->
      <el-form-item label="分列数量:">
        <el-radio-group v-model="curItem.style.column">
          <el-radio label="1" :disabled="curItem.style.display == 'slide'">单列</el-radio>
          <el-radio label="2">两列</el-radio>
          <el-radio label="3">三列</el-radio>
        </el-radio-group>
      </el-form-item>
      <!-- 商品排序 -->
      <el-form-item label="显示内容:">
        <el-checkbox v-model="productNameShow" @change="checked => check(checked, 'productName')">商品名称</el-checkbox>
        <el-checkbox v-model="productPriceShow" @change="checked => check(checked, 'productPrice')">商品价格</el-checkbox>
        <el-checkbox v-model="linePriceShow" @change="checked => check(checked, 'linePrice')">划线价格</el-checkbox>
        <el-checkbox v-model="sellingPointShow" @change="checked => check(checked, 'sellingPoint')" v-show="curItem.style.column == 1">商品卖点</el-checkbox>
        <el-checkbox v-model="productSalesShow" @change="checked => check(checked, 'productSales')" v-show="curItem.style.column == 1">商品销量</el-checkbox>
      </el-form-item>
    </el-form>
  </div>
</template>
<script>
import ProductApi from '@/api/product.js';
import draggable from 'vuedraggable';
export default {
  components: {
    draggable
  },
  data() {
    return {
      /*是否正在加载*/
      loading: true,
      /*商品类别*/
      CategoryList: [],
      /*当前选中的*/
      currCategory:[],
      productNameShow: false,
      productPriceShow: false,
      linePriceShow: false,
      sellingPointShow: false,
      productSalesShow: false
    };
  },
  props: ['curItem', 'selectedIndex', 'opts'],
  created() {
    /*获取列表*/
    this.getData();
    this.productNameShow = this.curItem.style.show.productName == 1 ? true : false;
    this.productPriceShow = this.curItem.style.show.productPrice == 1 ? true : false;
    this.linePriceShow = this.curItem.style.show.linePrice == 1 ? true : false;
    this.sellingPointShow = this.curItem.style.show.sellingPoint == 1 ? true : false;
    this.productSalesShow = this.curItem.style.show.productSales == 1 ? true : false;
  },
  watch: {
    selectedIndex: function(n, o) {
      this.currCategory=this.currCategoryAuto(this.CategoryList);
    }
  },
  methods: {
    /*获取商品*/
    getData() {
      let self = this;
      ProductApi.catList(
        {
          page_id: self.page_id
        },
        true
      )
        .then(res => {
          self.CategoryList = res.data.list;
          self.currCategory=self.currCategoryAuto(res.data.list);
          self.loading = false;
        })
        .catch(error => {
          self.loading = false;
        });
    },
    /*选择默认*/
    currCategoryAuto(list){
      let arr=[];
      for(let i=0;i<list.length;i++){
        let item=list[i];
        if(item.category_id==this.curItem.params.auto.category){
          arr.push(item.category_id);
          break;
        }else{
          if(Object.prototype.toString.call(item.child)== '[object Array]'&&item.child.length>0){
            for(let j=0;j<item.child.length;j++){
              if(item.child[j].category_id==this.curItem.params.auto.category){
               arr.push(item.category_id);
               arr.push(item.child[j].category_id);
               break;
              }
            }
          }
        }
      }
      return arr;
    },
    /*检查*/
    check(checked, name) {
      let value = checked ? 1 : 0;
      this.curItem.style.show[name] = value;
    },
    /*选择类别*/
    changeCategory(e) {
      if(e.length > 0){
        let item = this.$refs['cascader'].getCheckedNodes();
        this.curItem.params.auto.category = item[0].data.category_id;
      }else{
        this.curItem.params.auto.category = 0;
      }
    }
  }
};
</script>
<style>
.choice-product-list {
  display: flex;
  justify-content: flex-start;
  flex-wrap: wrap;
}
.choice-product-list .item {
  position: relative;
  width: 80px;
  height: 80px;
  margin-right: 10px;
  margin-bottom: 10px;
  border: 1px solid #dddddd;
}
.choice-product-list .item .delete-box {
  position: absolute;
  width: 20px;
  height: 20px;
  top: -10px;
  right: -10px;
  font-size: 20px;
  cursor: pointer;
  color: #999999;
}
.choice-product-list .item .delete-box:hover {
  color: rgb(255, 51, 0);
}
.choice-product-list .item.plus-btn {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}
.choice-product-list .item.plus-btn > i {
  font-size: 30px;
  color: #cccccc;
}
.choice-product-list img {
  width: 100%;
  height: 100%;
}
</style>
supplier_vue/src/views/page/page/diy/params/RichText.vue
New file
@@ -0,0 +1,69 @@
<template>
  <!--
        作者:wangxw
        时间:2019-11-05
        描述:diy组件 富文本框
    -->
  <div>
    <div class="common-form">
      <span>{{ curItem.name }}</span>
    </div>
    <el-form size="small" :model="curItem" label-width="100px">
      <!--上下边距-->
      <el-form-item label="上下边距:"><el-slider v-model="curItem.style.paddingTop" show-input></el-slider></el-form-item>
      <!--左右边距-->
      <el-form-item label="左右边距:"><el-slider v-model="curItem.style.paddingLeft" show-input></el-slider></el-form-item>
      <!--背景颜色-->
      <el-form-item label="背景颜色:">
        <div class="d-s-c">
          <el-color-picker v-model="curItem.style.background"></el-color-picker>
          <el-button type="button" style="margin-left: 10px;" @click.stop="$parent.onEditorResetColor(curItem.style, 'background', '#ffffff')">重置</el-button>
        </div>
      </el-form-item>
      <!--内容-->
      <el-form-item label="内容:">
        <Uediter :text="content" :config="ueditor.config" @contentChange="contentChangeFunc" ref="ue"></Uediter>
      </el-form-item>
    </el-form>
  </div>
</template>
<script>
  import Uediter from '@/components/UE.vue';
  export default {
    components:{
      /*编辑器*/
      Uediter
    },
    data() {
      return {
        ueditor: {
          text: '',
          config: {
            initialFrameWidth: 400,
            initialFrameHeight: 500,
          }
        },
        content:''
      };
    },
    props: ['curItem', 'selectedIndex', 'opts'],
    watch:{
    },
    created() {
      this.curItem.style.paddingTop = parseInt(this.curItem.style.paddingTop);
      this.curItem.style.paddingLeft = parseInt(this.curItem.style.paddingLeft);
      this.content=this.curItem.params.content;
    },
    methods: {
      contentChangeFunc(e){
        this.content=e;
        this.curItem.params.content=e;
      }
    }
  };
</script>
<style>
</style>
supplier_vue/src/views/page/page/diy/params/Search.vue
New file
@@ -0,0 +1,47 @@
<template>
  <!--
        作者:luoyiming
        时间:2020-06-20
        描述:diy组件-参数设置-搜索栏
    -->
  <div>
    <div class="common-form"><span>{{ curItem.name }}</span></div>
     <el-form size="small" :model="curItem" label-width="100px">
       <el-form-item label="提示文字:">
         <el-input v-model="curItem.params.placeholder"></el-input>
       </el-form-item>
       <el-form-item label="搜索框样式:">
         <el-radio-group v-model="curItem.style.searchStyle">
             <el-radio label="3">方形</el-radio>
             <el-radio label="6">圆角</el-radio>
             <el-radio label="9">圆弧</el-radio>
           </el-radio-group>
       </el-form-item>
       <el-form-item label="文字对齐:">
         <el-radio-group v-model="curItem.style.textAlign">
             <el-radio label="3">居左</el-radio>
             <el-radio label="6">居中</el-radio>
             <el-radio label="9">居右</el-radio>
           </el-radio-group>
       </el-form-item>
    </el-form>
  </div>
</template>
<script>
  export default {
    data() {
      return {
      };
    },
    props: ['curItem'],
    methods: {
    }
  };
</script>
<style>
</style>
supplier_vue/src/views/page/page/diy/params/Seckill.vue
New file
@@ -0,0 +1,79 @@
<template>
<!--
        作者:luoyiming
        时间:2020-06-20
        描述:diy组件-参数设置-限时秒杀
    -->
    <div>
        <div class="common-form">
            <span>{{ curItem.name }}</span>
        </div>
        <el-form size="small" :model="curItem" label-width="100px">
            <!--显示数量-->
            <el-form-item label="显示数量:">
                <el-input v-model="curItem.params.showNum" class="w-auto"></el-input>
            </el-form-item>
            <!-- 文字颜色 -->
            <el-form-item label="时间颜色:">
                <div class="d-s-c">
                    <el-color-picker v-model="curItem.style.color"></el-color-picker>
                    <el-button type="button" style="margin-left: 10px;"
                        @click.stop="$parent.onEditorResetColor(curItem.style, 'color', '#ffffff')">重置
                    </el-button>
                </div>
            </el-form-item>
            <el-form-item label="日期文字:">
                <div class="d-s-c">
                    <el-color-picker v-model="curItem.style.countdown_color"></el-color-picker>
                    <el-button type="button" style="margin-left: 10px;"
                        @click.stop="$parent.onEditorResetColor(curItem.style, 'countdown_color', '#FF302F')">重置
                    </el-button>
                </div>
            </el-form-item>
            <el-form-item label="日期背景:">
                <div class="d-s-c">
                    <el-color-picker v-model="curItem.style.countdown_back_color"></el-color-picker>
                    <el-button type="button" style="margin-left: 10px;"
                        @click.stop="$parent.onEditorResetColor(curItem.style, 'countdown_back_color', '#FEE250')">重置
                    </el-button>
                </div>
            </el-form-item>
            <el-form-item label="背景图片:">
              <div class="diy-notice-icon">
                <img v-img-url="curItem.style.background_image" alt="" @click="$parent.onEditorSelectImage(curItem.style, 'background_image')">
              </div>
              <div>建议尺寸700×90</div>
            </el-form-item>
            <!--组件样式-->
            <div class="p-10-0 mb16 f14 border-b">
                <span class="gray6">组件样式</span>
            </div>
            <!-- 商品排序 -->
            <el-form-item label="显示内容:">
                <el-checkbox v-model="curItem.style.show.productName">商品名称</el-checkbox>
                <el-checkbox v-model="curItem.style.show.seckillPrice">秒杀价格</el-checkbox>
                <el-checkbox v-model="curItem.style.show.linePrice">划线价格</el-checkbox>
            </el-form-item>
        </el-form>
    </div>
</template>
<script>
    export default {
        data() {
            return {
            };
        },
        props: ['curItem', 'selectedIndex'],
        created() {
        },
        methods: {
        }
    };
</script>
<style>
</style>
supplier_vue/src/views/page/page/diy/params/Service.vue
New file
@@ -0,0 +1,60 @@
<template>
  <!--
        作者:wangxw
        时间:2019-11-05
        描述:diy组件 客服
    -->
  <div>
    <div class="common-form">
      <span>{{ curItem.name }}</span>
    </div>
    <el-form size="small" :model="curItem" label-width="100px">
      <!--底边距-->
      <el-form-item label="底边距:"><el-slider v-model="curItem.style.bottom" show-input></el-slider></el-form-item>
      <!--右边距-->
      <el-form-item label="右边距:"><el-slider v-model="curItem.style.right" show-input></el-slider></el-form-item>
      <!--不透明度-->
      <el-form-item label="不透明度:"><el-slider v-model="curItem.style.opacity" show-input></el-slider></el-form-item>
      <!--客服类型-->
      <el-form-item label="客服类型:">
        <el-radio-group v-model="curItem.params.type">
            <el-radio :label="'chat'">在线聊天</el-radio>
            <el-radio :label="'phone'">拨打电话</el-radio>
          </el-radio-group>
      </el-form-item>
      <el-form-item label="电话号码:" v-show="curItem.params.type == 'phone'">
        <el-input v-model="curItem.params.phone_num"></el-input>
      </el-form-item>
      <!--客服图标-->
      <el-form-item label="客服图标:">
        <div class="diy-service-icon">
          <img v-img-url="curItem.params.image" alt="" @click="$parent.onEditorSelectImage(curItem.params, 'image')">
        </div>
        <div>建议尺寸90×90</div>
      </el-form-item>
    </el-form>
  </div>
</template>
<script>
  export default {
    data() {
      return {
      };
    },
    props: ['curItem', 'selectedIndex', 'opts'],
    created() {
      this.curItem.style.bottom = parseInt(this.curItem.style.bottom);
      this.curItem.style.right = parseInt(this.curItem.style.right);
      this.curItem.style.opacity = parseInt(this.curItem.style.opacity);
    },
    methods: {
    }
  };
</script>
<style>
.diy-service-icon, .diy-service-icon img{ width: 40px; height: 40px;}
</style>
supplier_vue/src/views/page/page/diy/params/Setpages.vue
New file
@@ -0,0 +1,97 @@
<template>
  <!--
        作者:luoyiming
        时间:2020-06-20
        描述:diy组件-参数设置-顶部设置栏
    -->
  <div>
    <div class="common-form">
      <span>{{ curItem.name }}</span>
    </div>
    <el-form size="small" :model="curItem" label-width="100px">
      <!--页面标题-->
      <el-form-item label="标题类型:">
        <el-radio-group v-model="logo_type" @change="logechange">
          <el-radio :label="'image'">图片</el-radio>
        </el-radio-group>
      </el-form-item>
      <!--图片-->
      <el-form-item label="图片:">
        <div class="diy-setpages-cover">
          <img  v-if="curItem.style.toplogo" v-img-url="curItem.style.toplogo" alt="" @click="$parent.onEditorSelectImage(curItem.style, 'toplogo')" :style="'background-color:'+curItem.style.titleBackgroundColor+' ;'">
          <div>建议尺寸60×60</div>
        </div>
      </el-form-item>
      <!--页面名称-->
      <el-form-item label="页面名称:">
        <el-input v-model="curItem.params.name"></el-input>
        <p class="gray">页面名称仅用于后台查找</p>
      </el-form-item>
      <!--分享标题-->
      <el-form-item label="分享标题:">
        <el-input v-model="curItem.params.share_title"></el-input>
        <p class="gray">小程序端转发时显示的标题</p>
      </el-form-item>
      <!-- 背景颜色 -->
      <el-form-item label="背景颜色:">
        <div class="d-s-c">
          <el-color-picker v-model="curItem.style.titleBackgroundColor"></el-color-picker>
          <el-button type="button" style="margin-left: 10px;" @click.stop="$parent.onEditorResetColor(curItem.style, 'titleBackgroundColor', '#ffffff')">重置</el-button>
        </div>
      </el-form-item>
      <!--页面标题-->
      <el-form-item label="商品分类:">
        <div class="gray9">仅首页有效</div>
        <el-radio-group v-model="curItem.category.open">
           <el-radio :label="1">开启</el-radio>
          <el-radio :label="0">关闭</el-radio>
        </el-radio-group>
      </el-form-item>
      <!-- 背景颜色 -->
      <el-form-item label="分类颜色:">
        <div class="d-s-c">
          <el-color-picker v-model="curItem.category.color"></el-color-picker>
          <el-button type="button" style="margin-left: 10px;" @click.stop="$parent.onEditorResetColor(curItem.category, 'color', '#ffffff')">重置</el-button>
        </div>
      </el-form-item>
    </el-form>
  </div>
</template>
<script>
  export default {
    data() {
      return {
        logo_type: 'image'
      };
    },
    props: ['curItem', 'selectedIndex', 'opts'],
    created() {
      console.log(this.curItem.style.toplogo)
      if(this.curItem.style.toplogo=='text'){
        this.logo_type='image';
      }else{
         this.logo_type='image';
      }
    },
    methods: {
      logechange(e){
        console.log(e)
        if(e == 'text'){
         this.curItem.style.toplogo='text';
        }else{
         this.curItem.style.toplogo='';
        }
      }
    }
  };
</script>
<style>
  .diy-setpages-cover>img{
    width: 60px;
    height: 60px;
  }
</style>
supplier_vue/src/views/page/page/diy/params/Special.vue
New file
@@ -0,0 +1,87 @@
<template>
  <!--
        作者:wangxw
        时间:2019-11-05
        描述:diy组件 头条快报
    -->
  <div>
    <div class="common-form">
      <span>{{ curItem.name }}</span>
    </div>
    <el-form size="small" :model="curItem" label-width="100px">
      <!-- 文章分类 -->
      <el-form-item label="文章分类:">
        <el-select v-model="curItem.params.auto.category">
          <el-option label="全部分类" :value="0"></el-option>
            <el-option
              v-for="item in category"
              :key="item.category_id"
              :label="item.name"
              :value="item.category_id">
            </el-option>
        </el-select>
      </el-form-item>
      <!-- 显示数量 -->
      <el-form-item label="显示数量:">
        <el-input type="number" min="1" v-model="curItem.params.auto.showNum" style="width: auto;"></el-input>
        <div>
          文章数据请到
          <a href="#/plus/article/index" target="_blank">内容管理 - 文章列表</a>
          中管理
        </div>
      </el-form-item>
      <!--图片-->
      <el-form-item label="图片:">
        <div class="diy-special-cover">
          <img v-img-url="curItem.style.image" alt="" @click="$parent.onEditorSelectImage(curItem.style, 'image')">
          <div>建议尺寸136×33</div>
        </div>
      </el-form-item>
      <!--显示类型-->
      <el-form-item label="显示类型:">
        <el-radio-group v-model="curItem.style.display">
          <el-radio :label="1">单行</el-radio>
          <el-radio :label="2">两行</el-radio>
        </el-radio-group>
      </el-form-item>
    </el-form>
  </div>
</template>
<script>
  import ArticleApi from '@/api/article.js';
  export default {
    data() {
      return {
        category: [],
      };
    },
    props: ['curItem', 'selectedIndex', 'opts'],
    created() {
      /*获取文章栏目*/
      this.getData();
    },
    methods: {
      /*获取文章栏目*/
      getData() {
        let self = this;
        ArticleApi.getCategory({
            page_id: self.page_id
          }, true).then(res => {
            self.category = res.data.category;
          })
          .catch(error => {
            self.loading = false;
          });
      },
    }
  };
</script>
<style>
  .diy-special-cover img {
    width: 140px;
    height: 38px;
  }
</style>
supplier_vue/src/views/page/page/diy/params/Store.vue
New file
@@ -0,0 +1,102 @@
<template>
<!--
        作者:luoyiming
        时间:2020-06-20
        描述:diy组件-参数设置-下线门店
    -->
  <div>
    <div class="common-form">
      <span>{{ curItem.name }}</span>
    </div>
    <el-form size="small" :model="curItem" label-width="100px">
      <!-- 商品来源 -->
      <el-form-item label="商品来源:">
        <el-radio-group v-model="curItem.params.source">
          <el-radio :label="'auto'">自动获取</el-radio>
          <el-radio :label="'choice'">手动选择</el-radio>
        </el-radio-group>
      </el-form-item>
      <!--手动选择-->
      <template v-if="curItem.params.source == 'choice'">
        <el-form-item label="门店列表:">
          <div class="choice-shop-list">
            <div :key="index" v-for="(shop, index) in curItem.data" class="item">
              <div class="delete-box"><i class="el-icon-error" @click="$parent.onEditorDeleleData(index, selectedIndex)"></i></div>
              <img v-img-url="shop.image" alt="" />
            </div>
            <div class="item plus-btn" @click.stop="$parent.onSelectProduct(curItem)">
              <i class="el-icon-plus"></i>
              <p>选择门店</p>
            </div>
          </div>
        </el-form-item>
      </template>
      <!-- 自动获取 -->
      <template v-show="curItem.params.source == 'auto'">
        <!-- 展示数量 -->
        <el-form-item label="展示数量:"><el-input style="width: auto;" v-model="curItem.params.auto.showNum" class="w-auto"></el-input></el-form-item>
      </template>
      <!-- 背景颜色 -->
      <el-form-item label="背景颜色:">
          <div class="d-s-c">
              <el-color-picker v-model="curItem.style.background"></el-color-picker>
              <el-button type="button" style="margin-left: 10px;"
                  @click.stop="$parent.onEditorResetColor(curItem.style, 'background', '#ffffff')">重置
              </el-button>
          </div>
      </el-form-item>
    </el-form>
  </div>
</template>
<script>
export default {
  data() {
    return {};
  },
  props: ['curItem', 'selectedIndex', 'opts'],
  methods: {}
};
</script>
<style>
.choice-shop-list {
  display: flex;
  justify-content: flex-start;
  flex-wrap: wrap;
}
.choice-shop-list .item {
  position: relative;
  width: 80px;
  height: 80px;
  margin-right: 10px;
  border: 1px solid #dddddd;
}
.choice-shop-list .item .delete-box {
  position: absolute;
  width: 20px;
  height: 20px;
  top: -10px;
  right: -10px;
  font-size: 20px;
  cursor: pointer;
  color: #999999;
}
.choice-shop-list .item .delete-box:hover {
  color: rgb(255, 51, 0);
}
.choice-shop-list .item.plus-btn {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}
.choice-shop-list .item.plus-btn > i {
  font-size: 30px;
  color: #cccccc;
}
.choice-shop-list img {
  width: 100%;
  height: 100%;
}
</style>
supplier_vue/src/views/page/page/diy/params/Tab.vue
New file
@@ -0,0 +1,118 @@
<template>
  <!--
        作者:lyzflash
      时间:2023-08-10
      描述:diy组件-模拟显示-选项卡组
    -->
  <div>
    <div class="common-form"><span>{{ curItem.name }}</span></div>
    <el-form size="small" :model="curItem" label-width="100px">
      <!--显示模式-->
      <el-form-item label="显示模式:">
        <el-radio-group v-model="curItem.style.show_type">
          <el-radio label="1">平铺</el-radio>
          <el-radio label="2">横向滑动</el-radio>
        </el-radio-group>
        <div class="gray9">建议选项卡数量多于4个时使用滑动模式</div>
      </el-form-item>
        <!--背景颜色-->
      <el-form-item label="背景颜色:">
        <div class="d-s-c">
            <el-color-picker v-model="curItem.style.background"></el-color-picker>
            <el-button type="button" style="margin-left: 10px;" @click.stop="$parent.onEditorResetColor(curItem.style, 'background', '#ffffff')">
              重置
            </el-button>
        </div>
      </el-form-item>
      <!--激活的背景颜色-->
      <el-form-item label="激活背景颜色:">
        <div class="d-s-c">
            <el-color-picker v-model="curItem.style.background_active"></el-color-picker>
            <el-button type="button" style="margin-left: 10px;" @click.stop="$parent.onEditorResetColor(curItem.style, 'background_active', '#ffffff')">
              重置
            </el-button>
        </div>
      </el-form-item>
      <!--激活的文字颜色-->
      <el-form-item label="激活文字颜色:">
        <div class="d-s-c">
            <el-color-picker v-model="curItem.style.text_active"></el-color-picker>
            <el-button type="button" style="margin-left: 10px;" @click.stop="$parent.onEditorResetColor(curItem.style, 'text_active', '#333333')">
              重置
            </el-button>
        </div>
      </el-form-item>
      <el-form-item label="内容:">
        <div class="param-img-item" :key="index" v-for="(navBar, index) in curItem.data">
          <div class="delete-box">
            <i class="el-icon-delete-solid" @click="$parent.onEditorDeleleData(index, selectedIndex)"></i>
          </div>
          <div class="url-box">
            <span class="key-name">文字内容:</span>
            <el-input v-model="navBar.text" class="max-w460"></el-input>
          </div>
          <div class="url-box">
            <span class="key-name">颜色:</span>
            <div class="d-s-c">
                <el-color-picker v-model="navBar.color"></el-color-picker>
                <el-button type="button" style="margin-left: 10px;" @click.stop="$parent.onEditorResetColor(navBar, 'color', '#666666')">
                  重置
                </el-button>
            </div>
          </div>
          <div class="d-s-c">
            <div class="url-box flex-1">
            <span class="key-name">链接名称:</span>
            <el-input v-model="navBar.name"></el-input>
          </div>
          <div class="url-box ml10">
            <el-button type="primary" @click="changeLink(index)">选择链接</el-button>
          </div>
          </div>
        </div>
        <div class="d-c-c">
          <el-button @click="$parent.onEditorAddData">添加一个</el-button>
        </div>
      </el-form-item>
    </el-form>
    <Setlink v-if="is_linkset" :is_linkset="is_linkset" @closeDialog="closeLinkset">选择链接</Setlink>
  </div>
</template>
<script>
    import Setlink from '@/components/setlink/Setlink';
  export default {
      components: {
          Setlink,
      },
    data() {
      return {
        /*是否选择链接*/
          is_linkset: false,
          index: null,
      };
    },
    props: ['curItem', 'selectedIndex', 'opts'],
    methods: {
      /*选择链接*/
        changeLink(index) {
            this.is_linkset = true;
            this.index = index;
        },
      /*获取链接并关闭弹窗*/
        closeLinkset(e) {
            this.is_linkset = false;
            this.curItem.data[this.index].type=e.type;
            this.curItem.data[this.index].inputname=e.name;
            this.curItem.data[this.index].linkUrl=e.url;
            this.curItem.data[this.index].name = '链接到' + ' ' + e.type + ' ' + e.name;
        },
    }
  };
</script>
<style>
</style>
supplier_vue/src/views/page/page/diy/params/Title.vue
New file
@@ -0,0 +1,68 @@
<template>
  <!--
        作者:wangxw
        时间:2019-11-05
        描述:diy组件 搜索栏
    -->
  <div>
    <div class="common-form">
      <span>{{ curItem.name }}</span>
    </div>
    <el-form size="small" :model="curItem" label-width="100px">
      <!--上下边距-->
      <el-form-item label="上下边距:"><el-slider v-model="curItem.style.paddingTop" show-input></el-slider></el-form-item>
      <!--背景颜色-->
      <el-form-item label="背景颜色:">
        <div class="d-s-c">
          <el-color-picker v-model="curItem.style.background"></el-color-picker>
          <el-button type="button" style="margin-left: 10px;" @click.stop="$parent.onEditorResetColor(curItem.style, 'background', '#F5F5F5')">重置</el-button>
        </div>
      </el-form-item>
      <!--文字颜色-->
      <el-form-item label="文字颜色:">
        <div class="d-s-c">
          <el-color-picker v-model="curItem.style.textColor"></el-color-picker>
          <el-button type="button" style="margin-left: 10px;" @click.stop="$parent.onEditorResetColor(curItem.style, 'textColor', '#FF0000')">重置</el-button>
        </div>
      </el-form-item>
      <el-form-item label="图标显示:">
        <el-radio-group v-model="curItem.params.show_icon">
            <el-radio label="yes">显示</el-radio>
            <el-radio label="no">不显示</el-radio>
          </el-radio-group>
      </el-form-item>
      <!--标题图标-->
      <el-form-item label="标题图标:">
        <div class="diy-notice-icon">
          <img v-img-url="curItem.params.icon" alt="" @click="$parent.onEditorSelectImage(curItem.params, 'icon')">
        </div>
        <div>建议尺寸32×32</div>
      </el-form-item>
      <!-- 公告内容 -->
      <el-form-item label="标题文字:">
        <el-input v-model="curItem.params.title" class="w-auto"></el-input>
      </el-form-item>
    </el-form>
  </div>
</template>
<script>
  export default {
    data() {
      return {
      };
    },
    props: ['curItem', 'selectedIndex', 'opts'],
    created() {
      this.curItem.style.paddingTop = parseInt(this.curItem.style.paddingTop);
    },
    methods: {
    }
  };
</script>
<style>
.diy-notice-icon, .diy-notice-icon img{ width: 32px; height: 32px;}
</style>
supplier_vue/src/views/page/page/diy/params/Video.vue
New file
@@ -0,0 +1,72 @@
<template>
  <!--
        作者:wangxw
        时间:2019-11-05
        描述:diy组件 视频
    -->
  <div>
    <div class="common-form">
      <span>{{ curItem.name }}</span>
    </div>
    <el-form size="small" :model="curItem" label-width="100px">
      <!--上下边距-->
      <el-form-item label="上下边距:">
        <el-slider v-model.number="curItem.style.paddingTop" show-input></el-slider>
      </el-form-item>
      <!--视频高度-->
      <el-form-item label="视频高度:">
        <el-slider v-model.number="curItem.style.height" :min="50" :max="500" show-input></el-slider>
        <div>
          滑块可用左右方向键精确调整
        </div>
      </el-form-item>
      <!--视频封面-->
      <el-form-item label="视频封面:">
        <div class="diy-video-cover">
          <img v-img-url="curItem.params.poster" alt="" @click="$parent.onEditorSelectImage(curItem.params, 'poster')">
        </div>
      </el-form-item>
      <!--视频地址-->
      <el-form-item label="视频地址:">
        <div class="d-s-c">
          <el-input v-model="curItem.params.videoUrl"></el-input>
          <el-button type="button" style="margin-left: 10px;" @click.stop="$parent.onEditorSelectVideo(curItem.params, 'videoUrl')">选择视频</el-button>
       </div>
      </el-form-item>
      <!--自动播放-->
      <el-form-item label="自动播放:">
        <el-radio-group v-model="curItem.params.autoplay">
            <el-radio label="0">否</el-radio>
            <el-radio label="1">是</el-radio>
          </el-radio-group>
      </el-form-item>
    </el-form>
  </div>
</template>
<script>
  export default {
    data() {
      return {
        paddingTop:0,
        height:0
      };
    },
    props: ['curItem', 'selectedIndex'],
    created() {
      this.curItem.style.paddingTop = parseInt(this.curItem.style.paddingTop);
      this.curItem.style.height = parseInt(this.curItem.style.height);
    },
    watch:{
    },
    methods: {
    }
  };
</script>
<style>
.diy-video-cover{ width: 200px;}
.diy-video-cover img{ width: 100%;}
</style>
supplier_vue/src/views/page/page/diy/params/Window.vue
New file
@@ -0,0 +1,98 @@
<template>
  <!--
        作者:wangxw
        时间:2019-11-05
        描述:diy组件 图片橱窗
    -->
  <div>
    <div class="common-form">
      <span>{{ curItem.name }}</span>
    </div>
    <el-form size="small" :model="curItem" label-width="100px">
      <!--上下边距-->
      <el-form-item label="上下边距:"><el-slider v-model="curItem.style.paddingTop" show-input></el-slider></el-form-item>
      <!--左右边距-->
      <el-form-item label="左右边距:"><el-slider v-model="curItem.style.paddingLeft" :min="0" :max="50" show-input></el-slider></el-form-item>
      <!--背景颜色-->
      <el-form-item label="背景颜色:">
        <div class="d-s-c">
          <el-color-picker v-model="curItem.style.background"></el-color-picker>
          <el-button type="button" style="margin-left: 10px;" @click.stop="$parent.onEditorResetColor(curItem.style, 'background', '#ffffff')">重置</el-button>
        </div>
      </el-form-item>
      <!-- 布局方式 -->
      <el-form-item label="布局方式:">
        <el-radio-group v-model="curItem.style.layout">
          <el-radio label="2">堆积两列</el-radio>
          <el-radio label="3">堆积三列</el-radio>
          <el-radio label="4">堆积四列</el-radio>
          <el-radio label="5">堆积两列(长方形)</el-radio>
          <el-radio label="-1">橱窗样式</el-radio>
        </el-radio-group>
        <div v-if="curItem.style.layout==-1" class="red">橱窗样式最多显示四张图片,超出隐藏</div>
        <div class="gray9">请确保所有图片的尺寸/比例相同。</div>
      </el-form-item>
      <el-form-item label="图片:">
        <div class="param-img-item" :key="index" v-for="(imageSingle, index) in curItem.data">
          <div class="delete-box"><i class="el-icon-delete-solid" @click="$parent.onEditorDeleleData(index, selectedIndex)"></i></div>
          <div class="pic"><img v-img-url="imageSingle.imgUrl" alt="" @click="$parent.onEditorSelectImage(imageSingle, 'imgUrl')" /></div>
          <div class="d-s-c">
          <div class="url-box flex-1">
            <span class="key-name">链接地址:</span>
            <el-input v-model="imageSingle.name"></el-input>
          </div>
          <div class="url-box ml">
            <el-button type="primary" @click="changeLink(index)">选择链接</el-button>
          </div>
          </div>
        </div>
        <div class="d-c-c"><el-button @click="$parent.onEditorAddData">添加一个</el-button></div>
      </el-form-item>
    </el-form>
    <Setlink v-if="is_linkset" :is_linkset="is_linkset" @closeDialog="closeLinkset">选择链接</Setlink>
  </div>
</template>
<script>
    import Setlink from '@/components/setlink/Setlink';
  export default {
      components: {
          Setlink,
      },
    data() {
      return {
        /*是否选择链接*/
          is_linkset: false,
          index: null,
      };
    },
    props: ['curItem', 'selectedIndex'],
    created() {
      this.curItem.style.paddingTop = parseInt(this.curItem.style.paddingTop);
      this.curItem.style.paddingLeft = parseInt(this.curItem.style.paddingLeft);
    },
    methods: {
      /*选择链接*/
        changeLink(index) {
            this.is_linkset = true;
            this.index = index;
        },
      /*获取链接并关闭弹窗*/
        closeLinkset(e) {
            console.log(e);
            this.is_linkset = false;
            this.curItem.data[this.index].type=e.type;
            this.curItem.data[this.index].inputname=e.name;
            this.curItem.data[this.index].linkUrl=e.url;
//            this.curItem.data[this.index].name=e.name;
            this.curItem.data[this.index].name = '链接到' + ' ' + e.type + ' ' + e.name;
        },
    }
  };
</script>
<style>
</style>
supplier_vue/src/views/page/page/diy/params/assembleProduct.vue
New file
@@ -0,0 +1,58 @@
<template>
  <!--
        作者:luoyiming
        时间:2020-06-20
        描述:diy组件-参数设置-限时拼团
    -->
  <div>
    <div class="common-form">
      <span>{{ curItem.name }}</span>
    </div>
    <el-form size="small" :model="curItem" label-width="100px">
      <!--显示数量-->
      <el-form-item label="显示数量:">
        <el-input v-model="curItem.params.showNum" class="w-auto"></el-input>
      </el-form-item>
      <!-- 文字颜色 -->
      <el-form-item label="文字颜色:">
          <div class="d-s-c">
              <el-color-picker v-model="curItem.style.color"></el-color-picker>
              <el-button type="button" style="margin-left: 10px;"
                  @click.stop="$parent.onEditorResetColor(curItem.style, 'color', '#C9C9C9')">重置
              </el-button>
          </div>
      </el-form-item>
      <el-form-item label="背景图片:">
        <div class="diy-notice-icon">
          <img v-img-url="curItem.style.background_image" alt="" @click="$parent.onEditorSelectImage(curItem.style, 'background_image')">
        </div>
        <div>建议尺寸700×90</div>
      </el-form-item>
      <!--组件样式-->
      <div class="p-10-0 mb16 f14 border-b">
        <span class="gray6">组件样式</span>
      </div>
      <!-- 商品排序 -->
      <el-form-item label="显示内容:">
        <el-checkbox v-model="curItem.style.show.productName">商品名称</el-checkbox>
        <el-checkbox v-model="curItem.style.show.assemblePrice">拼团价格</el-checkbox>
        <el-checkbox v-model="curItem.style.show.linePrice">划线价格</el-checkbox>
      </el-form-item>
    </el-form>
  </div>
</template>
<script>
  export default {
    data() {
      return {};
    },
    props: ['curItem', 'selectedIndex', 'opts'],
    created() {},
    methods: {}
  };
</script>
<style>
</style>
supplier_vue/src/views/page/page/edit.vue
New file
@@ -0,0 +1,141 @@
<template>
  <!--
      作者:wangxw
      时间:2020-06-10
      描述:页面-页面列表-修改页面
  -->
  <div v-loading="loading" class="diy-container clearfix">
    <!--类别选择-->
    <div class="diy-menu"><Type v-if="!loading" :defaultData="defaultData"></Type></div>
    <!--手机diy容器-->
    <div class="diy-phone"><Model v-if="!loading" ref="model" :form="form" :defaultData="defaultData" :diyData="diyData"></Model></div>
    <!--参数设置-->
    <div class="diy-info"><Params v-if="!loading" :form="form" :defaultData="defaultData" :diyData="diyData"></Params></div>
    <!--提交-->
    <div class="common-button-wrapper">
      <el-button  size="small" type="info" @click="gotoBack">返回上一页</el-button>
      <el-button size="small" type="primary" @click="Submit()" :loading="loading">保存</el-button>
    </div>
  </div>
</template>
<script>
import {deepClone} from '@/utils/base.js'
import PageApi from '@/api/page.js';
import Type from './diy/Type.vue';
import Model from './diy/Model.vue';
import Params from './diy/Params.vue';
export default {
  components: {
    /*组件类别*/
    Type,
    /*组件信息*/
    Model,
    /*参数信息*/
    Params
  },
  data() {
    return {
      /*是否正在加载*/
      loading: true,
      /*默认数据*/
      defaultData: {},
      /*组件数据列表*/
      diyData: {
        items: []
      },
      opts: {},
      /*表单对象*/
      form: {
        umeditor: {},
        /*当前选中*/
        curItem: {},
        /*当前选中的元素(下标)*/
        selectedIndex: -1
      }
    };
  },
  created() {
    /*获取列表*/
    this.getData();
  },
  methods: {
    /*获取列表*/
    getData() {
      let self = this;
      self.page_id = self.$route.query.page_id;
      PageApi.editPage(
        {
          page_id: self.page_id
        },
        true
      )
        .then(res => {
          self.defaultData = res.data.defaultData;
          self.diyData = res.data.jsonData;
          self.form.curItem=self.diyData.page;
          self.opts = res.data.opts;
          self.loading = false;
        })
        .catch(error => {
          self.loading = false;
        });
    },
    /*新增Diy组件*/
    onAddItem: function(key) {
      // 复制默认diy组件数据
      let item = deepClone(this.defaultData[key]),cur_index=0;
      if(this.form.selectedIndex<0){
        cur_index=0;
        this.diyData.items.unshift(item);
      }else{
        cur_index=this.form.selectedIndex + 1;
         this.diyData.items.splice(cur_index,0,item);
      }
      // 编辑当前选中的元素
      this.$refs.model.onEditer(cur_index);
    },
    /*上架*/
    Submit() {
      let self = this;
      self.loading = true;
      let params = self.diyData;
      let page_id = self.page_id;
      PageApi.SavePage(
        {
          params: JSON.stringify(params),
          page_id: page_id
        },
        true
      )
        .then(data => {
          self.loading = false;
          self.$message({
            message: '恭喜你,修改成功',
            type: 'success'
          });
          self.getData();
        })
        .catch(error => {
          self.loading = false;
        });
    },
    /*返回上一页面*/
    gotoBack(){
      this.$router.back(-1);
    }
  }
};
</script>
<style lang="scss">
@import '@/styles/page/diy.scss';
</style>
supplier_vue/src/views/page/page/editpage.vue
New file
@@ -0,0 +1,138 @@
<template>
  <!--
      作者:wangxw
      时间:2020-06-10
      描述:页面-首页
  -->
  <div v-loading="loading" class="diy-container clearfix">
    <!--类别选择-->
    <div class="diy-menu"><Type v-if="!loading" :defaultData="defaultData"></Type></div>
    <!--手机diy容器-->
    <div class="diy-phone"><Model v-if="!loading" ref="model" :form="form" :defaultData="defaultData" :diyData="diyData"></Model></div>
    <!--参数设置-->
    <div class="diy-info"><Params v-if="!loading" :form="form" :defaultData="defaultData" :diyData="diyData"></Params></div>
    <!--提交-->
    <div class="common-button-wrapper">
      <el-button  size="small" type="info" @click="gotoBack">返回上一页</el-button>
      <el-button size="small" type="primary" @click="Submit()" :loading="loading">保存</el-button>
    </div>
  </div>
</template>
<script>
import {deepClone} from '@/utils/base.js'
import PageApi from '@/api/page.js';
import Type from './diy/Type.vue';
import Model from './diy/Model.vue';
import Params from './diy/Params.vue';
export default {
  components: {
    /*组件类别*/
    Type,
    /*组件信息*/
    Model,
    /*参数信息*/
    Params
  },
  data() {
    return {
      page_id:0,
      /*是否正在加载*/
      loading: true,
      /*默认数据*/
      defaultData: {},
      /*组件数据列表*/
      diyData: {
        items: []
      },
      opts: {},
      /*表单对象*/
      form: {
        umeditor: {},
        /*当前选中*/
        curItem: {},
        /*当前选中的元素(下标)*/
        selectedIndex: -1
      }
    };
  },
  created() {
    /*获取列表*/
    this.getData();
  },
  methods: {
    /*获取列表*/
    getData() {
      let self = this;
      self.page_id = self.$route.query.page_id;
      PageApi.getEdit({
        page_id:self.page_id
      }, true)
        .then(res => {
          self.defaultData = res.data.defaultData;
          self.diyData = res.data.jsonData;
          self.form.curItem=self.diyData.page;
          self.opts = res.data.opts;
          self.loading = false;
        })
        .catch(error => {
          self.loading = false;
        });
    },
   /*新增Diy组件*/
   onAddItem: function(key) {
     // 复制默认diy组件数据
     let item = deepClone(this.defaultData[key]),cur_index=0;
     if(this.form.selectedIndex<0){
       cur_index=0;
       this.diyData.items.unshift(item);
     }else{
       cur_index=this.form.selectedIndex + 1;
        this.diyData.items.splice(cur_index,0,item);
     }
     // 编辑当前选中的元素
     this.$refs.model.onEditer(cur_index);
   },
    /*上架*/
    Submit() {
      let self = this;
      self.loading = true;
      let params = self.diyData;
      let page_id = self.page_id;
      PageApi.editHome(
        {
          params: JSON.stringify(params),
          page_id: page_id
        },
        true
      )
        .then(data => {
          self.loading = false;
          self.$message({
            message: '恭喜你,修改成功',
            type: 'success'
          });
          self.getData();
          self.form.selectedIndex= -1;
        })
        .catch(error => {
          self.loading = false;
        });
    },
    /*返回上一页面*/
    gotoBack(){
      this.$router.back(-1);
    }
  }
};
</script>
<style lang="scss">
@import '@/styles/page/diy.scss';
</style>
supplier_vue/src/views/page/page/home.vue
New file
@@ -0,0 +1,129 @@
<template>
  <!--
      作者:wangxw
      时间:2020-06-10
      描述:页面-首页
  -->
  <div v-loading="loading" class="diy-container clearfix">
    <!--类别选择-->
    <div class="diy-menu"><Type v-if="!loading" :defaultData="defaultData"></Type></div>
    <!--手机diy容器-->
    <div class="diy-phone"><Model v-if="!loading" ref="model" :form="form" :defaultData="defaultData" :diyData="diyData"></Model></div>
    <!--参数设置-->
    <div class="diy-info"><Params v-if="!loading" :form="form" :defaultData="defaultData" :diyData="diyData"></Params></div>
    <!--提交-->
    <div class="common-button-wrapper">
      <el-button size="small" type="primary" @click="Submit()" :loading="loading">保存</el-button>
    </div>
  </div>
</template>
<script>
import {deepClone} from '@/utils/base.js'
import PageApi from '@/api/page.js';
import Type from './diy/Type.vue';
import Model from './diy/Model.vue';
import Params from './diy/Params.vue';
export default {
  components: {
    /*组件类别*/
    Type,
    /*组件信息*/
    Model,
    /*参数信息*/
    Params
  },
  data() {
    return {
      /*是否正在加载*/
      loading: true,
      /*默认数据*/
      defaultData: {},
      /*组件数据列表*/
      diyData: {
        items: []
      },
      opts: {},
      /*表单对象*/
      form: {
        umeditor: {},
        /*当前选中*/
        curItem: {},
        /*当前选中的元素(下标)*/
        selectedIndex: -1
      }
    };
  },
  created() {
    /*获取列表*/
    this.getData();
  },
  methods: {
    /*获取列表*/
    getData() {
      let self = this;
      PageApi.editHome({}, true)
        .then(res => {
          self.defaultData = res.data.defaultData;
          self.diyData = res.data.jsonData;
          self.form.curItem=self.diyData.page;
          self.opts = res.data.opts;
          self.loading = false;
        })
        .catch(error => {
          self.loading = false;
        });
    },
   /*新增Diy组件*/
   onAddItem: function(key) {
     // 复制默认diy组件数据
     let item = deepClone(this.defaultData[key]),cur_index=0;
     if(this.form.selectedIndex<0){
       cur_index=0;
       this.diyData.items.unshift(item);
     }else{
       cur_index=this.form.selectedIndex + 1;
        this.diyData.items.splice(cur_index,0,item);
     }
     // 编辑当前选中的元素
     this.$refs.model.onEditer(cur_index);
   },
    /*上架*/
    Submit() {
      let self = this;
      self.loading = true;
      let params = self.diyData;
      let page_id = self.page_id;
      PageApi.SavePage(
        {
          params: JSON.stringify(params),
          page_id: page_id
        },
        true
      )
        .then(data => {
          self.loading = false;
          self.$message({
            message: '恭喜你,修改成功',
            type: 'success'
          });
          self.getData();
          self.form.selectedIndex= -1;
        })
        .catch(error => {
          self.loading = false;
        });
    }
  }
};
</script>
<style lang="scss">
@import '@/styles/page/diy.scss';
</style>
supplier_vue/src/views/page/page/index.vue
New file
@@ -0,0 +1,190 @@
<template>
  <!--
      作者:wangxw
      时间:2020-06-10
      描述:页面-页面列表
  -->
  <div class="user">
    <!--添加页面-->
    <div class="common-level-rail">
      <el-button size="small" type="primary" icon="el-icon-plus" @click="addClick()" v-auth="'/page/page/add'">添加页面</el-button>
    </div>
    <!--内容-->
    <div class="product-content">
      <div class="table-wrap">
        <el-table size="small" :data="tableData" border style="width: 100%" v-loading="loading">
          <el-table-column prop="page_id" label="页面ID" width="80"></el-table-column>
          <el-table-column prop="page_name" label="页面名称">
            <template slot-scope="scope">
              <span>{{ scope.row.page_name }}</span>
              <!-- <span class="gray">(首页)</span> -->
            </template>
          </el-table-column>
          <el-table-column prop="page_type" label="页面类型">
            <template slot-scope="scope">
              <span v-if="scope.row.page_type==10">商城首页</span>
              <span v-if="scope.row.page_type==20">自定义页</span>
            </template>
          </el-table-column>
          <el-table-column prop="create_time" label="添加时间"></el-table-column>
          <el-table-column prop="update_time" label="更新时间"></el-table-column>
          <el-table-column fixed="right" label="操作" width="150">
            <template slot-scope="scope">
              <el-button @click="editClick(scope.row.page_id)" type="text" size="small" v-auth="'/page/page/edit'">编辑</el-button>
              <el-button v-if="scope.row.page_type==20" @click="setHomeClick(scope.row.page_id)" type="text" size="small" v-auth="'/page/page/set'">设为首页
              </el-button>
              <el-button v-if="scope.row.page_type==20" @click="deleteClick(scope.row.page_id)" type="text" size="small" v-auth="'/page/page/delete'">删除
              </el-button>
            </template>
          </el-table-column>
        </el-table>
      </div>
      <!--分页-->
      <div class="pagination">
        <el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange" background :current-page="curPage"
          :page-size="pageSize" layout="total, prev, pager, next, jumper"
          :total="totalDataNumber">
        </el-pagination>
      </div>
    </div>
  </div>
</template>
<script>
  import PageApi from '@/api/page.js';
  export default {
    data() {
      return {
        /*是否加载完成*/
        loading: true,
        /*列表数据*/
        tableData: [],
        /*一页多少条*/
        pageSize: 20,
        /*一共多少条数据*/
        totalDataNumber: 0,
        /*当前是第几页*/
        curPage: 1,
      };
    },
    created() {
      /*获取列表*/
      this.getTableList();
    },
    methods: {
      /*选择第几页*/
      handleCurrentChange(val) {
        let self = this;
        self.curPage = val;
        self.loading = true;
        self.getTableList();
      },
      /*每页多少条*/
      handleSizeChange(val) {
        this.curPage = 1;
        this.pageSize = val;
        this.getTableList();
      },
      /*获取列表*/
      getTableList() {
        let self = this;
        let Params = {};
        Params.page = self.curPage;
        Params.list_rows = self.pageSize;
        PageApi.PageList(Params, true).then(data => {
          self.loading = false;
          self.tableData = data.data.list.data;
          self.totalDataNumber = data.data.list.total;
        }).catch(error => {
        });
      },
      /*删除数据*/
      deleteClick(row) {
        let self = this;
        self.$confirm('此操作将永久删除该记录, 是否继续?', '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        }).then(() => {
          self.loading = true;
          PageApi.deletePage({
              page_id: row
            }, true).then(data => {
              if (data.code == 1) {
                self.loading = false;
                self.$message({
                  message: '恭喜你,删除成功',
                  type: 'success'
                });
                self.getTableList();
              } else {
                self.loading = false;
              }
            })
            .catch(error => {
              self.loading = false;
            });
        }).catch(() => {});
      },
      /*添加页面*/
      addClick() {
        this.$router.push('/page/page/add');
      },
      /*设为首页*/
      setHomeClick(page_id) {
        let self = this;
        self.$confirm('确定要将此页面设置为默认首页吗?', '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        }).then(() => {
          self.loading = true;
          PageApi.setHome({
              page_id: page_id
            }, true).then(data => {
              self.loading = false;
              if (data.code == 1) {
                self.$message({
                  message: '恭喜你,设置成功',
                  type: 'success'
                });
                self.getTableList();
              } else {
                self.$message.error('错了哦,这是一条错误消息');
              }
            })
            .catch(error => {
              self.loading = false;
            });
        }).catch(() => {
        });
      },
      /*编辑*/
      editClick(page_id) {
        let self = this;
        self.$router.push({
          path: '/page/page/edit',
          query: {
            page_id: page_id
          }
        })
      }
    }
  };
</script>
<style></style>
supplier_vue/src/views/page/page/list.vue
New file
@@ -0,0 +1,231 @@
<template>
  <!--
      作者:wangxw
      时间:2020-06-10
      描述:页面-页面列表
  -->
  <div class="d-b-s diy-preview">
    <!--手机diy容器-->
    <div class="diy-phone"><Model v-if="!loading" ref="model" :form="form" :defaultData="defaultData" :diyData="diyData"></Model></div>
    <div class="user flex-1">
      <!--添加页面-->
      <div class="common-level-rail">
        <el-button size="small" type="primary" icon="el-icon-plus" @click="addClick()" v-auth="'/page/page/addPage'">添加页面</el-button>
      </div>
      <!--内容-->
      <div class="product-content">
        <div class="table-wrap">
          <el-table size="small" :data="tableData" border style="width: 100%" v-loading="loading">
            <el-table-column prop="page_id" label="页面ID" width="80"></el-table-column>
            <el-table-column prop="page_name" label="页面名称">
              <template slot-scope="scope">
                <span>{{ scope.row.page_name }}</span>
                <span class="red" v-if="scope.row.is_default!=0">(默认)</span>
                <!-- <span class="gray">(首页)</span> -->
              </template>
            </el-table-column>
            <el-table-column prop="page_type" label="页面类型">
              <template slot-scope="scope">
                <span v-if="scope.row.page_type==10">商城首页</span>
                <span v-if="scope.row.page_type==20">自定义页</span>
              </template>
            </el-table-column>
            <el-table-column prop="create_time" label="添加时间"></el-table-column>
            <el-table-column prop="update_time" label="更新时间"></el-table-column>
            <el-table-column fixed="right" label="操作" width="90">
              <template slot-scope="scope">
                <el-button v-if="scope.row.is_default==0" @click="setHomeClick(scope.row.page_id)" type="text" size="small" v-auth="'/page/page/setPage'">设为默认</el-button>
                <el-button @click="editClick(scope.row.page_id)" type="text" size="small" v-auth="'/page/page/editPage'">编辑</el-button>
                <el-button v-if="scope.row.is_default==0" @click="deleteClick(scope.row.page_id)" type="text" size="small" v-auth="'/page/page/deletePage'">删除
                </el-button>
              </template>
            </el-table-column>
          </el-table>
        </div>
        <!--分页-->
        <div class="pagination">
          <el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange" background :current-page="curPage"
            :page-size="pageSize" layout="total, prev, pager, next, jumper"
            :total="totalDataNumber">
          </el-pagination>
        </div>
      </div>
    </div>
  </div>
</template>
<script>
  import PageApi from '@/api/page.js';
  import Model from './diy/Preview.vue';
  export default {
    components: {
      Model,
    },
    data() {
      return {
        /*是否加载完成*/
        loading: true,
        /*列表数据*/
        tableData: [],
        /*一页多少条*/
        pageSize: 20,
        /*一共多少条数据*/
        totalDataNumber: 0,
        /*当前是第几页*/
        curPage: 1,
        /*默认数据*/
        defaultData: {},
        /*组件数据列表*/
        diyData: {
          items: []
        },
        /*表单对象*/
        form: {
          umeditor: {},
          /*当前选中*/
          curItem: {},
          /*当前选中的元素(下标)*/
          selectedIndex: -1
        }
      };
    },
    created() {
      /*获取列表*/
      this.getTableList();
    },
    methods: {
      onEditer(){
        return
      },
      /*选择第几页*/
      handleCurrentChange(val) {
        let self = this;
        self.curPage = val;
        self.loading = true;
        self.getTableList();
      },
      /*每页多少条*/
      handleSizeChange(val) {
        this.curPage = 1;
        this.pageSize = val;
        this.getTableList();
      },
      /*获取列表*/
      getTableList() {
        let self = this;
        let Params = {};
        Params.page = self.curPage;
        Params.list_rows = self.pageSize;
        PageApi.HomeList(Params, true).then(data => {
          self.loading = false;
          self.tableData = data.data.list.data;
          self.diyData = data.data.default.page_data;
          console.log( self.diyData)
          self.totalDataNumber = data.data.list.total;
        }).catch(error => {
        });
      },
      /*删除数据*/
      deleteClick(row) {
        let self = this;
        self.$confirm('此操作将永久删除该记录, 是否继续?', '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        }).then(() => {
          self.loading = true;
          PageApi.deletePage({
              page_id: row
            }, true).then(data => {
              if (data.code == 1) {
                self.loading = false;
                self.$message({
                  message: '恭喜你,删除成功',
                  type: 'success'
                });
                self.getTableList();
              } else {
                self.loading = false;
              }
            })
            .catch(error => {
              self.loading = false;
            });
        }).catch(() => {});
      },
      /*添加页面*/
      addClick() {
        this.$router.push('/page/page/addpage');
      },
      /*设为首页*/
      setHomeClick(page_id) {
        let self = this;
        self.$confirm('确定要将此页面设置为默认首页吗?', '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        }).then(() => {
          self.loading = true;
          PageApi.setPage({
              page_id: page_id
            }, true).then(data => {
              self.loading = false;
              if (data.code == 1) {
                self.$message({
                  message: '恭喜你,设置成功',
                  type: 'success'
                });
                self.getTableList();
              } else {
                self.$message.error('错了哦,这是一条错误消息');
              }
            })
            .catch(error => {
              self.loading = false;
            });
        }).catch(() => {
        });
      },
      /*编辑*/
      editClick(page_id) {
        let self = this;
        self.$router.push({
          path: '/page/page/editpage',
          query: {
            page_id: page_id
          }
        })
      }
    }
  };
</script>
<style>
  .diy-preview .diy-phone{
    width: 375px;
    margin-right: 20px;
    flex-shrink: 0;
  }
  .diy-preview .diy-phone .btn-edit-del{
    display: none;
  }
  .diy-preview .diy-phone .diy-phone-container .diy-phone-item > div:hover, .diy-preview .diy-phone .diy-phone-container .diy-phone-item.active > div{
    border: 2px solid #f1f1f2;;
  }
</style>
supplier_vue/src/views/page/page/mymenu/add.vue
New file
@@ -0,0 +1,188 @@
<template>
  <!--
      作者:luoyiming
      时间:2020-06-01
      描述:广告-添加
    -->
  <div class="product-add pb50">
    <!--添加广告-->
    <el-form size="small" :model="form" ref="form" :rules="rules" label-width="100px">
      <div class="common-form">添加菜单</div>
      <el-form-item label="菜单名称" prop="title">
        <el-input v-model="form.title" placeholder="请输入菜单名称" class="max-w460"></el-input>
      </el-form-item>
      <el-form-item label="图标" prop="image_url">
        <div>
          <el-button type="primary" @click="openUpload">上传图片</el-button>
          <img :src="path" class="mt10" width="120px;" v-if="isImg" :isImg="isImg" />
          <div style="color: red;">图标大小为:25*25</div>
          <!--上传图片组件-->
          <Upload v-if="isupload" :isupload="isupload" @returnImgs="returnImgsFunc">上传图片</Upload>
        </div>
      </el-form-item>
      <el-form-item label="状态">
        <el-radio-group v-model="form.status">
          <el-radio :label="1">显示</el-radio>
          <el-radio :label="0">隐藏</el-radio>
        </el-radio-group>
      </el-form-item>
      <el-form-item label="排序">
        <el-input type="number" v-model="form.sort" placeholder="请输入数字" class="max-w460"></el-input>
      </el-form-item>
      <el-form-item label="链接" prop="link_url">
        <el-row>
          <div class="url-box flex-1">
            <el-input v-model="form.link_url" type="text" class="max-w460" style="width: 380px;"></el-input>
            <el-button type="primary" @click="changeLink()">选择链接</el-button>
            <div class="tips" id="tips" style="color: #000;">{{tips_Id}}</div>
            <el-input v-model="form.name" type="hidden" class="max-w460" style="width: 380px;"></el-input>
          </div>
          <div class="url-box ml10" style="float: right;">
          </div>
        </el-row>
      </el-form-item>
      <Setlink v-if="is_linkset" :is_linkset="is_linkset" @closeDialog="closeLinkset">选择链接</Setlink>
      <!--提交-->
      <div class="common-button-wrapper">
        <el-button size="small" type="info" @click="cancelFunc">取消</el-button>
        <el-button size="small" type="primary" @click="onSubmit" :loading="loading">提交</el-button>
      </div>
    </el-form>
  </div>
</template>
<script>
  import PageApi from '@/api/page.js';
  import Upload from '@/components/file/Upload';
  import Setlink from '@/components/setlink/Setlink';
  export default {
    components: {
      /*图片上传*/
      Upload: Upload,
      Setlink
    },
    data() {
      return {
        /*是否上传图片*/
        isupload: false,
        is_linkset: false,
        isImg: false,
        path: '',
        tips_Id: '',
        /*form表单数据*/
        form: {
          title: '',
          image_url: '',
          sort: 1,
          status: 1,
          link_url: '',
          name: '',
        },
        loading: false,
        /*验证规则*/
        rules: {
          title: [{
            required: true,
            message: '请输入菜单名称',
            trigger: 'blur'
          }],
          image_url: [{
            required: true,
            message: '请上传图标',
            trigger: 'blur'
          }],
          link_url: [{
            required: true,
            message: '请选择链接地址',
            trigger: 'blur'
          }],
        }
      };
    },
    created() {},
    methods: {
      /*选择链接*/
      changeLink() {
        this.is_linkset = true;
      },
      /*获取链接并关闭弹窗*/
      closeLinkset(e) {
        //console.log(e);
        this.is_linkset = false;
        if (e != null) {
          if(e.url.startsWith('/')){
            this.form.link_url = e.url;
          }else{
            this.form.link_url = '/' + e.url;
          }
          this.form.name = '链接到' + ' ' + e.type + ' ' + e.name;
          this.tips_Id = '链接到' + ' ' + e.type + ' ' + e.name;
        }
      },
      /*上传*/
      openUpload() {
        this.isupload = true;
      },
      /*获取图片*/
      returnImgsFunc(e) {
        let self = this;
        if (e != null) {
          this.form.image_url = e[0].file_path;
          this.path = e[0].file_path;
          this.isImg = true;
        }
        this.isupload = false;
      },
      /*添加广告*/
      onSubmit() {
        let self = this;
        let form = self.form;
        self.$refs.form.validate(valid => {
          if (valid) {
            self.loading = true;
            PageApi.addMenu(form, true)
              .then(data => {
                self.loading = false;
                self.$message({
                  message: data.msg,
                  type: 'success'
                });
                self.$router.push('/page/page/mymenu/index');
              })
              .catch(error => {
                self.loading = false;
              });
          }
        });
      },
      /*取消添加,返回广告列表*/
      cancelFunc() {
        this.$router.push({
          path: '/page/page/mymenu/index'
        });
      }
    }
  };
</script>
<style>
  .edit_container {
    font-family: 'Avenir', Helvetica, Arial, sans-serif;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    text-align: center;
    color: #2c3e50;
  }
  .ql-editor {
    height: 400px;
  }
</style>
supplier_vue/src/views/page/page/mymenu/edit.vue
New file
@@ -0,0 +1,197 @@
<template>
  <!--
      作者:luoyiming
      时间:2020-06-01
      描述:广告-编辑
    -->
  <div class="product-add pb50" v-loading="loading">
    <!--编辑广告-->
    <el-form size="small" :model="form" ref="form" :rules="rules" label-width="100px">
      <div class="common-form">编辑菜单</div>
      <el-form-item label="菜单名称" prop="title">
        <el-input v-model="form.title" placeholder="请输入广告标题" class="max-w460"></el-input>
      </el-form-item>
      <el-form-item label="图标">
        <div>
          <el-button type="primary" @click="openUpload">上传图片</el-button>
          <img class="mt10" v-img-url="'image_url',form" width="120px;" alt="" />
          <div style="color: red;">图标大小为:25*25</div>
          <!--上传图片组件-->
          <Upload v-if="isupload" :isupload="isupload" @returnImgs="returnImgsFunc">上传图片</Upload>
        </div>
      </el-form-item>
      <el-form-item label="状态">
        <el-radio-group v-model="form.status">
          <el-radio :label="1">显示</el-radio>
          <el-radio :label="0">隐藏</el-radio>
        </el-radio-group>
      </el-form-item>
      <el-form-item label="排序">
        <el-input type="number" v-model="form.sort" placeholder="请输入数字" class="max-w460"></el-input>
      </el-form-item>
      <el-form-item label="链接" prop="link_url">
        <el-row>
          <div class="url-box flex-1">
            <el-input :disabled="form.app_id==0" v-model="form.link_url" type="text" class="max-w460"
              style="width: 380px;"></el-input>
            <el-button :disabled="form.app_id==0" type="primary" @click="changeLink()">选择链接<span></span></el-button>
            <div class="tips" id="tips" style="color: #000;">{{tips_Id}}</div>
            <el-input v-model="form.name" type="hidden" class="max-w460"></el-input>
          </div>
          <div class="url-box ml10" style="float: right;">
          </div>
        </el-row>
      </el-form-item>
      <Setlink v-if="is_linkset" :is_linkset="is_linkset" @closeDialog="closeLinkset">选择链接</Setlink>
      <!--提交-->
      <div class="common-button-wrapper">
        <el-button size="small" type="info" @click="cancelFunc" :loading="loading">取消</el-button>
        <el-button size="small" type="primary" @click="onSubmit" :loading="loading">提交</el-button>
      </div>
    </el-form>
  </div>
</template>
<script>
  import PageApi from '@/api/page.js';
  import Upload from '@/components/file/Upload';
  import Setlink from '@/components/setlink/Setlink';
  export default {
    components: {
      /*图片上传*/
      Upload: Upload,
      Setlink
    },
    data() {
      return {
        /*是否加载完成*/
        loading: true,
        /*是否上传图片*/
        isupload: false,
        /*form表单数据*/
        is_linkset: false,
        tips_Id: '',
        form: {
          ad_id: '',
          title: '',
          category_id: '',
          image_url: '',
          image: {},
          sort: 1,
          status: '0',
        },
        /*验证规则*/
        rules: {
          title: [{
            required: true,
            message: '请输入菜单名称',
            trigger: 'blur'
          }],
          link_url: [{
            required: true,
            message: '请选择链接地址',
            trigger: 'blur'
          }],
        }
      };
    },
    created() {
      this.getDetail();
    },
    methods: {
      changeLink() {
        this.is_linkset = true;
      },
      /*获取链接并关闭弹窗*/
      closeLinkset(e) {
        this.is_linkset = false;
        if (e != null) {
          if(e.url.startsWith('/')){
            this.form.link_url = e.url;
          }else{
            this.form.link_url = '/' + e.url;
          }
          this.form.name = '链接到' + ' ' + e.type + ' ' + e.name;
          this.tips_Id = '链接到' + ' ' + e.type + ' ' + e.name;
        }
      },
      /*上传*/
      openUpload() {
        this.isupload = true;
      },
      /*获取图片*/
      returnImgsFunc(e) {
        let self = this;
        if (e != null) {
          this.form.image_url = e[0].file_path;
        }
        this.isupload = false;
      },
      getDetail() {
        let self = this;
        // 取到路由带过来的参数
        const params = self.$route.query.menu_id;
        PageApi.menuDetail({
            menu_id: params
          }, true).then(res => {
            self.form = res.data.detail;
            self.tips_Id = res.data.detail.name;
            if (!self.form.image) {
              self.form.image = {};
            }
            self.loading = false;
          })
          .catch(error => {});
      },
      /*修改*/
      onSubmit() {
        let self = this;
        let params = this.form;
        // // 取到路由带过来的参数
        self.$refs.form.validate(valid => {
          if (valid) {
            PageApi.editMenu(params, true)
              .then(data => {
                self.$message({
                  message: data.msg,
                  type: 'success'
                });
                self.$router.push('/page/page/mymenu/index');
              })
              .catch(error => {});
          }
        });
      },
      /*取消添加,返回文章列表*/
      cancelFunc() {
        this.$router.push({
          path: '/page/page/mymenu/index'
        });
      }
    }
  };
</script>
<style>
  .edit_container {
    font-family: 'Avenir', Helvetica, Arial, sans-serif;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    text-align: center;
    color: #2c3e50;
  }
  .ql-editor {
    height: 400px;
  }
</style>
supplier_vue/src/views/page/page/mymenu/index.vue
New file
@@ -0,0 +1,212 @@
<template>
  <div>
    <div class="common-level-rail"><el-button size="small" type="primary" icon="el-icon-plus" @click="addMenu">添加菜单</el-button></div>
    <div class="table-wrap">
      <el-table :data="tableData" style="width: 100%" v-loading="loading">
        <el-table-column prop="menu_id" label="ID" width="100"></el-table-column>
         <el-table-column prop="title" label="菜单名称">
          <template slot-scope="scope">
            <div class="text-ellipsis" :title="scope.row.title">{{scope.row.title}}</div>
          </template>
        </el-table-column>
        <el-table-column prop="address" label="图标" width="250">
          <template slot-scope="scope">
            <img v-img-url="'image_url',scope.row" width="50" height="50" />
          </template>
        </el-table-column>
        <el-table-column prop="sort" label="排序" width="100"></el-table-column>
        <el-table-column prop="status" label="是否显示" width="80">
          <template slot-scope="scope">
            <el-switch
              v-model="scope.row.status"
              :active-value="1"
              :inactive-value="0"
              @change="changeStatus(scope.row)"
              active-color="#13ce66"
              inactive-color="#cccccc"
            ></el-switch>
          </template>
        </el-table-column>
        <el-table-column prop="create_time" label="添加时间" width="140"></el-table-column>
        <el-table-column prop="update_time" label="更新时间" width="140"></el-table-column>
        <el-table-column prop="name" label="操作" width="90">
          <template slot-scope="scope">
            <el-button @click="editMenu(scope.row)" type="text" size="small">编辑</el-button>
            <el-button @click="deleteMenu(scope.row)" type="text" size="small" v-if="scope.row.app_id>0">删除</el-button>
          </template>
        </el-table-column>
      </el-table>
      <!--分页-->
      <div class="pagination">
        <el-pagination
          @size-change="handleSizeChange"
          @current-change="handleCurrentChange"
          background
          :current-page="curPage"
          :page-size="pageSize"
          layout="total, prev, pager, next, jumper"
          :total="totalDataNumber"
        ></el-pagination>
      </div>
    </div>
  </div>
</template>
<script>
import PageApi from '@/api/page.js';
export default {
  components: {},
  data() {
    return {
      /*表单数据*/
      tableData: [],
      /*是否打开添加弹窗*/
      open_add: false,
      /*是否打开编辑弹窗*/
      open_edit: false,
      /*当前编辑的对象*/
      userModel: {},
      commentData: [],
      loading: true,
      /*一页多少条*/
      pageSize: 10,
      /*一共多少条数据*/
      totalDataNumber: 0,
      /*当前是第几页*/
      curPage: 1
    };
  },
  created() {
    /*获取列表*/
    this.getTableList();
  },
  methods: {
    /*获取列表*/
    getTableList() {
      let self = this;
      let Params = {};
      Params.page = self.curPage;
      Params.list_rows = self.pageSize;
      PageApi.menuList(Params, true)
        .then(data => {
          self.loading = false;
          self.tableData = data.data.list.data;
          self.totalDataNumber = data.data.list.total;
        })
        .catch(error => {
          self.loading = false;
        });
    },
    /*添加*/
    addMenu() {
      this.$router.push({
        path: '/page/page/mymenu/add'
      });
    },
    /*编辑*/
    editMenu(row) {
      let params = row.menu_id;
      this.$router.push({
        path: '/page/page/mymenu/edit',
        query: {
          menu_id: params
        }
      });
    },
    /*修改状态*/
    changeStatus(item){
      let self = this;
      const loading = self.$loading({
        lock: true,
        text: '正在处理',
        spinner: 'el-icon-loading',
        background: 'rgba(0, 0, 0, 0.7)'
      });
      PageApi.editMenu({
        menu_id: item.menu_id,
        status: item.status
      })
        .then(data => {
          loading.close();
        })
        .catch(data => {
          loading.close();
          self.$message({
            message: '处理失败,请重试',
            type: 'warning'
          });
        });
    },
    /*选择第几页*/
    handleCurrentChange(val) {
      let self = this;
      self.curPage = val;
      self.loading = true;
      self.getTableList();
    },
    /*每页多少条*/
    handleSizeChange(val) {
      this.curPage = 1;
      this.getTableList();
    },
    /*删除*/
    deleteMenu(row) {
      let self = this;
      self
        .$confirm('此操作将永久删除该记录, 是否继续?', '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        })
        .then(() => {
          self.loading = true;
          PageApi.deleteMenu(
            {
              menu_id: row.menu_id
            },
            true
          )
            .then(data => {
              self.$message({
                message: data.msg,
                type: 'success'
              });
              self.loading = false;
              self.getTableList();
            })
            .catch(error => {});
        })
        .catch(() => {});
    },
    handleClick(tab, event) {},
    /*关闭弹窗*/
    closeDialogFunc(e, f) {
      if (f == 'add') {
        this.open_add = e.openDialog;
        if (e.type == 'success') {
          this.getTableList();
        }
      }
      if (f == 'edit') {
        this.open_edit = e.openDialog;
        if (e.type == 'success') {
          this.getTableList();
        }
      }
    }
  }
};
</script>
<style></style>
supplier_vue/src/views/page/page/nav.vue
New file
@@ -0,0 +1,267 @@
<template>
  <!--
        作者:wangxw
        时间:2019-05-05
        描述:分类模板
    -->
  <div class="d-s-s pb50">
    <!--分类不同样式展示-->
    <div class="model-container">
      <div class="img-box p10" :style="'backgroundColor:'+formData.backgroundColor+';'">
        <div class="d-a-c">
          <div v-for="(item,index) in formData.list" :key="index" class="d-c d-c-c" @mouseenter="mouseenter"
            @mouseleave="mouseleave" v-if="item.is_show">
            <div v-if="formData.type != 2">
              <img class="nav_img" :src="item.iconPath" alt="">
            </div>
            <div v-if="formData.type != 1" :style="'color:'+formData.textColor+' ;'">{{item.text}}</div>
          </div>
        </div>
      </div>
    </div>
    <!--图片展示参数-->
    <div class="param-container flex-1">
      <div class="common-form"><span>展示设置</span></div>
      <el-form size="small" :model="formData" label-width="100px">
        <div :key="index" v-for="(navBar, index) in formData.list">
          <el-form-item :label="navBar.text+':'">
            <div class="param-img-item">
              <div class="d-a-c">
                <div class="icon">未选中:
                  <img v-img-url="navBar.iconPath" alt="" @click="onEditorSelectImage(navBar, 'iconPath')">
                </div>
                <div class="icon"> 已选中:
                  <img v-img-url="navBar.selectedIconPath" alt="" @click="onEditorSelectImage(navBar, 'selectedIconPath')">
                </div>
              </div>
            </div>
          </el-form-item>
        </div>
      </el-form>
    </div>
    <!--提交-->
    <div class="common-button-wrapper">
      <el-button size="small" type="primary" @click="Submit()">保存</el-button>
    </div>
    <!--上传图片-->
    <Upload v-if="isupload" :isupload="isupload" :config="{ total: 3 }" @returnImgs="returnImgsFunc"></Upload>
  </div>
</template>
<script>
  import PageApi from '@/api/page.js';
  import Upload from '@/components/file/Upload';
  export default {
    data() {
      return {
        /*是否上传图片*/
        isupload: false,
        /*表单数据对象*/
        formData: {
          /* 导航类型*/
          type: 0,
          /* 背景颜色*/
          backgroundColor: "",
          textColor: '',
          textHoverColor: '',
          /* 悬浮 */
          bulge: false,
          list: [
            // {
            // text:'',
            // iconPath:'',
            // is_show:true,
            // selectedIconPath:'',
            // link:{
            // wap_url:''
            // }
            // }
          ]
        },
        is_linkset: false,
        index: 0,
      };
    },
    components: {
      Upload
    },
    created() {
      this.getData();
    },
    methods: {
      /*获取数据*/
      getData() {
        let self = this;
        PageApi.getNav({}, true).then(res => {
          // let data = JSON.parse(res.data.data.data);
          // console.log(data)
          self.formData = res.data.data.data;
        }).catch(error => {
          self.loading = false;
        });
      },
      /*提交*/
      Submit() {
        let self = this;
        self.loading = true;
        let Params = self.formData;
        if (Params.list.length <= 0 || !Params.list) {
          Params = {}
        }
        PageApi.postNav({
            data: Params
          }, true)
          .then(data => {
            self.loading = false;
            self.$message({
              message: '恭喜你,修改成功',
              type: 'success'
            });
            self.getData();
          })
          .catch(error => {
            self.loading = false;
          });
      },
      /*选择链接*/
      changeLink(index) {
        this.is_linkset = true;
        this.index = index;
      },
      /*获取链接并关闭弹窗*/
      closeLinkset(e) {
        this.is_linkset = false;
        this.formData.list[this.index].link.wap_url = '/' + e.url;
        this.formData.list[this.index].text = e.name;
      },
      onEditorDeleleData: function(index) {
        let self = this;
        // if (self.formData.list.length <= 1) {
        //   self.$message({
        //     message: '至少保留一个',
        //     type: 'error'
        //   });
        //   return false;
        // }
        self.formData.list.splice(index, 1);
      },
      onEditorSelectImage: function(index, imgUrl) {
        this.isupload = true;
        this.imgModel = {
          index: index,
          imgUrl: imgUrl
        };
      },
      /*上传图片*/
      returnImgsFunc(e) {
        if (e != null) {
          this.imgModel.index[this.imgModel.imgUrl] = e[0]['file_path'];
        }
        this.isupload = false;
      },
      onEditorResetColor: function(holder, attribute, color) {
        holder[attribute] = color;
      },
      onEditorAddData: function() {
        let self = this;
        // 新增data数据
        if (self.formData.list) {
          if (self.formData.list.length >= 5) {
            self.$message({
              message: '最多添加5个',
              type: 'error'
            });
            return false;
          } else {
            let newDataItem = {
              iconPath: '',
              text: '',
              is_show: true,
              selectedIconPath: '',
              link: {
                wap_url: ''
              }
            };
            self.formData.list.push(newDataItem);
          }
        } else {
          let newDataItem = {
            iconPath: '',
            text: '',
            is_show: true,
            selectedIconPath: '',
            link: {
              wap_url: ''
            }
          };
          let list = [{ ...newDataItem
          }];
          self.formData = {
            type: 0,
            backgroundColor: "",
            textColor: '',
            textHoverColor: '',
            bulge: false,
            list: []
          }
          self.formData.list = list;
        }
      },
      mouseenter(e) {
        e.target.childNodes[2].style.color = this.formData.textHoverColor;
      },
      mouseleave(e) {
        e.target.childNodes[2].style.color = this.formData.textColor;
      }
    }
  };
</script>
<style scoped="scoped">
  .model-container {
    width: 300px;
    height: calc(100vh - 150px);
    margin-right: 30px;
  }
  .model-container img {
    width: 100%;
  }
  .model-container .img-box {
    box-shadow: 0 0 16px 0 rgba(0, 0, 0, .1);
  }
  .param-container {
    padding: 20px;
    /* height: calc(100vh - 150px); */
    border: 1px solid #cccccc;
  }
  .icon img {
    width: 50px;
    height: 50px;
  }
  .nav_img {
    width: 30px !important;
    height: 30px;
  }
  .delete-box {
    z-index: 99;
  }
  .param-img-item {
    border: 1px solid #CCCCCC;
    margin-bottom: 10px;
    padding: 30px 15px;
  }
</style>
supplier_vue/src/views/page/theme/index.vue
New file
@@ -0,0 +1,146 @@
<template>
  <!--
      作者 luoyiming
      时间:2019-10-26
      描述:设置-商城设置
  -->
  <div class="product-add">
    <!--form表单-->
    <el-row :gutter="20">
      <el-col :span="12" class="d-c-s">
        <div class="phone-theme">
          <img v-if="form.theme=='0'" :src="theme1_url">
          <img v-if="form.theme=='1'" :src="theme2_url">
          <img v-if="form.theme=='2'" :src="theme3_url">
          <img v-if="form.theme=='3'" :src="theme4_url">
          <img v-if="form.theme=='4'" :src="theme5_url">
          <img v-if="form.theme=='5'" :src="theme6_url">
          <img v-if="form.theme=='6'" :src="theme7_url">
        </div>
      </el-col>
      <el-col :span="12" class="d-c-s">
        <el-form size="small" ref="form" :model="form" label-width="50px">
          <div class="common-form">主题选择</div>
          <el-form-item label="">
            <el-radio-group v-model="form.theme" class="d-a-c f-w">
              <el-radio class="mb10 mr10" :label="'0'">主题一</el-radio>
              <el-radio class="mb10 mr10" :label="'1'">主题二</el-radio>
              <el-radio class="mb10 mr10" :label="'2'">主题三</el-radio>
              <el-radio class="mb10 mr10" :label="'3'">主题四</el-radio>
              <el-radio class="mb10 mr10" :label="'4'">主题五</el-radio>
              <el-radio class="mb10 mr10" :label="'5'">主题六</el-radio>
              <el-radio class="mb10 mr10" :label="'6'">主题七</el-radio>
            </el-radio-group>
          </el-form-item>
          <!--提交-->
          <div class="common-button-wrapper">
            <el-button type="primary" @click="onSubmit" :loading="loading">保存</el-button>
          </div>
        </el-form>
      </el-col>
    </el-row>
  </div>
</template>
<script>
  import PageApi from '@/api/page.js';
  import Upload from '@/components/file/Upload';
  import {
    formatModel
  } from '@/utils/base.js';
  import theme1 from '@/assets/img/theme1.jpg';
  import theme2 from '@/assets/img/theme2.jpg';
  import theme3 from '@/assets/img/theme3.jpg';
  import theme4 from '@/assets/img/theme4.jpg';
  import theme5 from '@/assets/img/theme5.jpg';
  import theme6 from '@/assets/img/theme6.jpg';
  import theme7 from '@/assets/img/theme7.jpg';
  export default {
    data() {
      return {
        /*是否正在加载*/
        loading: false,
        /*form表单数据*/
        form: {
          theme: 'red',
        },
        all_type: [],
        type: [],
        /*是否打开图片选择*/
        isupload: false,
        theme7_url: theme7,
        theme6_url: theme6,
        theme5_url: theme5,
        theme4_url: theme4,
        theme3_url: theme3,
        theme2_url: theme2,
        theme1_url: theme1,
      };
    },
    created() {
      this.getParams()
    },
    methods: {
      /*获取配置数据*/
      getParams() {
        let self = this;
        PageApi.themeDetail({}, true).then(res => {
            self.form.theme = res.data.vars.values.theme;
            self.loading = false;
          })
          .catch(error => {
          });
      },
      /*提交*/
      onSubmit() {
        let self = this;
        let params = this.form;
        self.$refs.form.validate((valid) => {
          if (valid) {
            self.loading = true;
            PageApi.editTheme(params, true)
              .then(data => {
                self.loading = false;
                self.$message({
                  message: '恭喜你,设置成功',
                  type: 'success'
                });
                self.$router.push('/page/theme/index');
              })
              .catch(error => {
                self.loading = false;
              });
          }
        });
      },
    }
  };
</script>
<style>
  .mb10 {
    margin-bottom: 10px;
  }
  .mr10 {
    margin-right: 10px;
  }
  .phone-theme>img {
    width: 250px;
  }
  .d-c-s {
    display: flex;
    justify-content: center;
    align-items: flex-start;
  }
</style>
supplier_vue/src/views/product/product/add.vue
@@ -138,6 +138,14 @@
            // 见点奖
            viewpoint_money: 0,
            belonging_shop_supplier_id:0,
            /*服务商品内容*/
            service_content: '',
            /*是否开启消费券赠送,默认1为开启,0为关闭*/
            is_consumption_gift: 1,
            /*是否允许使用消费券抵扣,默认1为允许,0为不允许*/
            is_consumption_discount: 1,
            /*最大抵扣消费券数量*/
            max_consumption_discount: 0,
          },
          /*商品分类*/
          category: [],
supplier_vue/src/views/product/product/edit.vue
@@ -110,6 +110,7 @@
            /*商品编码*/
            product_no: '',
            product_sku_id: '',
            settlement_price: 0,
          },
          /*多规格类别*/
          spec_many: {
@@ -179,6 +180,14 @@
          viewpoint_money: 0,
          is_viewpoint_money: 0,
          belonging_shop_supplier_id:0,
          /*服务商品内容*/
          service_content: '',
          /*是否开启消费券赠送,默认1为开启,0为关闭*/
          is_consumption_gift: 1,
          /*是否允许使用消费券抵扣,默认1为允许,0为不允许*/
          is_consumption_discount: 1,
          /*最大抵扣消费券数量*/
          max_consumption_discount: 0,
        },
      };
    },
supplier_vue/src/views/product/product/part/Basic.vue
@@ -108,8 +108,9 @@
    <el-form-item label="商品属性:">
      <el-radio-group v-model="form.model.is_virtual">
        <el-radio :label="0">实物商品</el-radio>
        <el-radio :label="1">服务商品(无需发货)</el-radio>
        <el-radio :label="1">虚拟商品(无需发货)</el-radio>
        <el-radio :label="2">券商品</el-radio>
        <el-radio :label="3">服务商品(无需发货)</el-radio>
      </el-radio-group>
    </el-form-item>
    <el-form-item label="运费:" prop="model.delivery_id" v-if="form.model.is_virtual==0">
@@ -133,18 +134,22 @@
      <el-input type="number" min="0" v-model="form.model.limit_num" class="max-w460"></el-input>
      <div class="gray9">每个会员购买的最大数量,0为不限购</div>
    </el-form-item>
    <el-form-item label="发货类型:" v-if="form.model.is_virtual==1">
    <el-form-item label="发货类型:" v-if="form.model.is_virtual==1||form.model.is_virtual==3">
      <el-radio-group v-model="form.model.virtual_auto">
        <el-radio :label="1">自动</el-radio>
        <el-radio :label="0">手动</el-radio>
      </el-radio-group>
    </el-form-item>
    <el-form-item label="服务商品:" :rules="[{ required: true, message: '请填写服务商品' }]" prop="model.virtual_content" v-if="form.model.is_virtual==1">
    <el-form-item label="虚拟商品:" :rules="[{ required: true, message: '请填写虚拟商品' }]" prop="model.virtual_content" v-if="form.model.is_virtual==1">
      <el-input type="text" v-model="form.model.virtual_content" class="max-w460"></el-input>
      <div class="gray9">虚拟商品内容</div>
    </el-form-item>
    <el-form-item label="服务商品:" :rules="[{ required: true, message: '请填写服务商品' }]" prop="model.service_content" v-if="form.model.is_virtual==3">
      <el-input type="text" v-model="form.model.service_content" class="max-w460"></el-input>
      <div class="gray9">服务商品内容</div>
    </el-form-item>
    <template v-if="form.model.virtual_auto==0&&form.model.is_virtual==1">
    <template v-if="form.model.virtual_auto==0&&(form.model.is_virtual==1||form.model.is_virtual==3)">
      <el-form-item label="支持线下核销:">
        <el-radio-group v-model="form.model.is_verify">
          <el-radio :label="1">支持</el-radio>
supplier_vue/src/views/product/product/part/Buyset.vue
@@ -18,6 +18,24 @@
      <el-input type="number" v-model="form.model.max_points_discount" class="max-w460"></el-input>
      <div class="gray9">最大抵扣积分数量,-1为使用通用设置</div>
    </el-form-item>
    <!--积分设置-->
    <div class="common-form">消费券设置</div>
    <el-form-item label="是否开启消费券赠送:">
      <el-radio-group v-model="form.model.is_consumption_gift">
        <el-radio :label="1">开启</el-radio>
        <el-radio :label="0">关闭</el-radio>
      </el-radio-group>
    </el-form-item>
    <el-form-item label="是否允许使用消费券抵扣:">
      <el-radio-group v-model="form.model.is_consumption_discount">
        <el-radio :label="1">允许</el-radio>
        <el-radio :label="0">不允许</el-radio>
      </el-radio-group>
    </el-form-item>
    <el-form-item v-if="form.model.is_consumption_discount == 1" label="最大抵扣消费券数量:" :rules="[{ required: true, message: ' ' }]" prop="model.max_consumption_discount">
      <el-input type="number" v-model="form.model.max_consumption_discount" class="max-w460"></el-input>
      <div class="gray9">最大抵扣消费券数量,-1为使用通用设置</div>
    </el-form-item>
    <div v-if="form.is_repurchase" class="common-form">见点奖设置</div>
    <el-form-item v-if="form.is_repurchase" label="见点奖设置:">
      <el-radio-group v-model="form.model.is_viewpoint_money">
supplier_vue/src/views/product/product/part/spec/Single.vue
@@ -14,6 +14,9 @@
    <el-form-item label="产品划线价:" :rules="[{ required: true, message: '请填写产品划线价' }]" prop="model.sku.line_price">
      <el-input type="number" v-model="form.model.sku.line_price" class="max-w460"></el-input>
     </el-form-item>
    <el-form-item label="产品结算价:" :rules="[{ required: false, message: '请填写产品结算价' }]" prop="model.sku.settlement_price">
      <el-input type="number" v-model="form.model.sku.settlement_price" class="max-w460"></el-input>
    </el-form-item>
    <el-form-item label="库存数量:" :rules="[{ required: true, message: '请填写库存数量' }]" prop="model.sku.stock_num">
      <el-input type="number" v-model="form.model.sku.stock_num" class="max-w460"></el-input>
    </el-form-item>
supplier_vue/src/views/product/product/part/spec/many/Table.vue
@@ -10,6 +10,7 @@
          批量设置
          <el-input size="small" v-model="batchData.product_price" placeholder="销售价" style="width: 160px;padding-left: 4px;"></el-input>
          <el-input size="small" v-model="batchData.line_price" placeholder="划线价" style="width: 160px;padding-left: 4px;"></el-input>
          <el-input size="small" v-model="batchData.settlement_price" placeholder="结算价" style="width: 160px;padding-left: 4px;"></el-input>
          <el-input size="small" v-model="batchData.stock_num" placeholder="库存" style="width: 160px;padding-left: 4px;"></el-input>
          <el-input size="small" v-model="batchData.product_weight" placeholder="重量" style="width: 160px;padding-left: 4px;"></el-input>
          <el-button size="small" @click="onSubmitBatchData">应用</el-button>
@@ -47,6 +48,11 @@
            <el-table-column label="划线价">
              <template slot-scope="scope">
                <el-form-item label="" style="margin-bottom: 0;"><el-input size="small" prop="line_price" v-model="scope.row.spec_form.line_price"></el-input></el-form-item>
              </template>
            </el-table-column>
            <el-table-column label="结算价">
              <template slot-scope="scope">
                <el-form-item label="" style="margin-bottom: 0;"><el-input size="small" prop="settlement_price" v-model="scope.row.spec_form.settlement_price"></el-input></el-form-item>
              </template>
            </el-table-column>
            <el-table-column label="库存">
@@ -95,7 +101,8 @@
          product_price: '',
          line_price: '',
          stock_num: '',
          product_weight: ''
          product_weight: '',
          settlement_price: 0,
        },
        /*图片是否打开*/
        isupload: false,
supplier_vue/src/views/user/consumption/index.vue
New file
@@ -0,0 +1,42 @@
<template>
  <!--
      作者 luoyiming
      时间:2020-06-09
      描述:会员-消费券管理
  -->
  <div class="common-seach-wrap">
    <el-tabs v-model="activeName">
      <el-tab-pane label="消费券设置" name="first"></el-tab-pane>
      <el-tab-pane label="消费券明细" name="second"></el-tab-pane>
    </el-tabs>
    <!--消费券设置-->
    <Setting v-if="activeName == 'first'"></Setting>
    <!--消费券明细-->
    <Log v-if="activeName == 'second'"></Log>
  </div>
</template>
<script>
import Setting from './part/Setting';
import Log from './part/Log';
export default {
  components: {
    Setting,
    Log
  },
  data() {
    return {
      form: {
        status: 0
      },
      activeName: 'first'
    };
  },
  methods: {}
};
</script>
<style>
</style>
supplier_vue/src/views/user/consumption/part/Log.vue
New file
@@ -0,0 +1,134 @@
<template>
  <!--
      作者 luoyiming
      时间:2020-06-09
      描述:会员-消费券管理-消费券明细
  -->
  <div class="user">
    <!--搜索表单-->
    <div class="common-seach-wrap">
      <el-form size="small" :inline="true" :model="formInline" class="demo-form-inline">
        <el-form-item label="昵称">
          <el-input v-model="formInline.search" placeholder="请输入昵称"></el-input>
        </el-form-item>
        <el-form-item label="注册时间">
          <div class="block">
            <span class="demonstration"></span>
            <el-date-picker v-model="formInline.value1" type="daterange"  value-format="yyyy-MM-dd" range-separator="至" start-placeholder="开始日期"
              end-placeholder="结束日期">
            </el-date-picker>
          </div>
        </el-form-item>
        <el-form-item>
          <el-button type="primary" icon="el-icon-search" @click="onSubmit">查询</el-button>
        </el-form-item>
      </el-form>
    </div>
    <!--内容-->
    <div class="product-content">
      <div class="table-wrap">
        <el-table size="small" :data="tableData" border style="width: 100%" v-loading="loading">
          <el-table-column prop="log_id" label="ID" width="60"></el-table-column>
          <el-table-column prop="nickName" label="微信头像" width="70">
            <template slot-scope="scope">
              <img :src="scope.row.user.avatarUrl" width="30" height="30" />
            </template>
          </el-table-column>
          <el-table-column prop="" label="昵称">
            <template slot-scope="scope">
              <span>{{scope.row.user.nickName}}</span>
              <span class="gray9">(用户ID:{{scope.row.user.user_id}})</span>
            </template>
          </el-table-column>
          <el-table-column prop="value" label="变动数量"></el-table-column>
          <el-table-column prop="describe" label="描述/说明"></el-table-column>
          <el-table-column prop="remark" label="管理员备注">
            <template slot-scope="scope">
              <span v-if="scope.row.remark==''">--</span>
            </template>
          </el-table-column>
          <el-table-column prop="create_time" label="创建时间"></el-table-column>
        </el-table>
      </div>
      <!--分页-->
      <div class="pagination">
        <el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange" background :current-page="curPage"
          :page-size="pageSize" layout="total, prev, pager, next, jumper"
          :total="totalDataNumber">
        </el-pagination>
      </div>
    </div>
  </div>
</template>
<script>
  import PointsApi from '@/api/points.js';
  export default {
    components: {},
    data() {
      return {
        /*是否加载完成*/
        loading: true,
        /*列表数据*/
        tableData: [],
        /*一页多少条*/
        pageSize: 10,
        /*一共多少条数据*/
        totalDataNumber: 0,
        /*当前是第几页*/
        curPage: 1,
        /*横向表单数据模型*/
        formInline: {
          search: '',
          value1: ''
        },
      };
    },
    created() {
      /*获取列表*/
      this.getTableList();
    },
    methods: {
      /*选择第几页*/
      handleCurrentChange(val) {
        let self = this;
        self.curPage = val;
        self.loading = true;
        self.getTableList();
      },
      /*每页多少条*/
      handleSizeChange(val) {
        this.curPage = 1;
        this.pageSize = val;
        this.getTableList();
      },
      /*获取列表*/
      getTableList() {
        let self = this;
        let Params = self.formInline;
        Params.page = self.curPage;
        Params.list_rows = self.pageSize;
        PointsApi.GetUserList(Params, true).then(data => {
          self.loading = false;
          self.tableData = data.data.list.data;
          self.totalDataNumber = data.data.list.total;
        }).catch(error => {
        });
      },
      /*搜索查询*/
      onSubmit() {
        let self = this;
        self.loading = true;
        self.getTableList();
      },
    }
  };
</script>
<style></style>
supplier_vue/src/views/user/consumption/part/Setting.vue
New file
@@ -0,0 +1,172 @@
<template>
  <!--
      作者 luoyiming
      时间:2020-06-09
      描述:会员-消费券管理-消费券设置
  -->
  <div class="pb50">
    <el-form ref="form" size="small" :model="form" label-width="200px">
      <div class="common-form">消费券设置</div>
      <el-form-item label="消费券名称 " prop="points_name" :rules="[{required: true,message: ' '}]">
        <el-input v-model="form.points_name" autocomplete="off" class="max-w460"></el-input>
        <div class="lh18 mt10 gray9">
          <p>注:修改消费券名称后,在买家端的所有页面里,看到的都是自定义的名称</p>
          <p>例:商家使用自定义的消费券名称来做品牌运营。如京东把消费券称为“京豆”,淘宝把消费券称为“淘金币”</p>
        </div>
      </el-form-item>
      <el-form-item label="消费券说明" :rules="[{required: true,message: ' '}]">
        <el-input type="textarea" rows="5" v-model="form.describe" autocomplete="off"></el-input>
      </el-form-item>
      <div class="common-form">消费券赠送</div>
      <el-form-item label="是否开启购物送消费券">
        <el-radio-group v-model="form.is_shopping_gift">
          <el-radio :label="1">开启</el-radio>
          <el-radio :label="0">关闭</el-radio>
        </el-radio-group>
        <div class="lh18 mt10 gray9">
          <p>注:如开启则订单完成后赠送用户消费券</p>
          <p>消费券赠送规则:1.订单确认收货已完成;2.已完成订单超出后台设置的申请售后期限</p>
        </div>
      </el-form-item>
      <el-form-item label="消费券赠送比例 " prop="gift_ratio" :rules="[{required: true,message: ' '}]">
        <el-input placeholder="请输入内容" v-model="form.gift_ratio" class="max-w460">
          <template slot="append">%</template>
        </el-input>
        <div class="lh18 mt10 gray9">
          <p> 注:赠送比例请填写数字0~100;订单的运费不参与消费券赠送</p>
          <p> 例:订单付款金额(100.00元) * 消费券赠送比例(100%) = 实际赠送的消费券(100消费券)</p>
        </div>
      </el-form-item>
      <!-- <el-form-item label="生日消费赠送 " prop="birthday_ratio" :rules="[{required: true,message: ' '}]">
        <el-input placeholder="请输入内容" v-model="form.birthday_ratio" class="max-w460">
          <template slot="append">倍</template>
        </el-input>
        <div class="lh18 mt10 gray9">
          <p> 注:赠送倍数请填写数字0~100;该倍数目前仅对会员等级的兑换比例生效,一般用于生日那天消费可得双倍消费券</p>
          <p> 例:蹭送消费券(100消费券) * 消费券倍数(2) = 实际赠送的消费券(200消费券)</p>
        </div>
      </el-form-item> -->
      <div class="common-form">消费券抵扣</div>
      <el-form-item label=" 是否允许下单使用消费券抵扣 ">
        <el-radio-group v-model="form.is_shopping_discount" class="max-w460">
          <el-radio :label="1">允许</el-radio>
          <el-radio :label="0">不允许</el-radio>
        </el-radio-group>
        <div class="lh18 mt10 gray9">
          <p>注:如开启则用户下单时可选择使用消费券抵扣订单金额</p>
        </div>
      </el-form-item>
      <el-form-item label=" 是否允许消费券转换余额 ">
        <el-radio-group v-model="form.is_trans_balance" class="max-w460">
          <el-radio :label="1">允许</el-radio>
          <el-radio :label="0">不允许</el-radio>
        </el-radio-group>
        <div class="lh18 mt10 gray9">
          <p>注:如开启则用户可将消费券转换成余额</p>
        </div>
      </el-form-item>
      <el-form-item label=" 消费券抵扣比例">
        <el-input placeholder="请输入内容" v-model="form.discount.discount_ratio" class="max-w460">
          <template slot="prepend">1个消费券可抵扣</template>
          <template slot="append">元</template>
        </el-input>
        <div class="lh18 mt10 gray9">
          <p>例如:1消费券可抵扣0.01元,100消费券则可抵扣1元,1000消费券则可抵扣10元</p>
        </div>
      </el-form-item>
      <el-form-item label=" 抵扣条件">
        <el-input placeholder="请输入内容" v-model="form.discount.full_order_price" class="max-w460">
          <template slot="prepend">订单满</template>
          <template slot="append">元</template>
        </el-input>
      </el-form-item>
      <el-form-item label=" ">
        <el-input placeholder="请输入内容" v-model="form.discount.max_money_ratio" class="max-w460">
          <template slot="prepend">最高可抵扣金额</template>
          <template slot="append">%</template>
        </el-input>
        <div class="lh18 mt10 gray9">
          <p>温馨提示:例如订单金额100元,最高可抵扣10%,此时用户可抵扣10元</p>
        </div>
      </el-form-item>
      <!--提交-->
      <div class="common-button-wrapper">
        <el-button type="primary" size="small" @click="onSubmit" :loading="loading">提交</el-button>
      </div>
    </el-form>
  </div>
</template>
<script>
  import PointsApi from '@/api/points.js';
  export default {
    data() {
      return {
        form: {
          is_shopping_gift: 1,
          gift_ratio: 10,
          is_shopping_discount: 1,
          discount: {
            discount_ratio: 0,
            full_order_price: 0,
            max_money_ratio: 0,
          },
          is_trans_balance: 0,
         // birthday_ratio:0,
        },
        loading: false,
      };
    },
    created() {
      /*获取数据*/
      this.getData();
    },
    methods: {
      /*获取数据*/
      getData() {
        let self = this;
        let Params = {};
        PointsApi.getPoints(Params, true).then(data => {
          self.form = data.data.values;
          self.form.is_shopping_gift = parseInt(data.data.values.is_shopping_gift);
          self.form.is_shopping_discount = parseInt(data.data.values.is_shopping_discount);
          self.form.is_trans_balance = parseInt(data.data.values.is_trans_balance);
        }).catch(error => {
        });
      },
      /*保存*/
      onSubmit() {
        let self = this;
        let form = self.form;
        self.$refs.form.validate((valid) => {
          if (valid) {
            self.loading = true;
            PointsApi.setPoints(form, true)
              .then(data => {
                self.loading = false;
                if (data.code == 1) {
                  self.$message({
                    message: '恭喜你,保存成功',
                    type: 'success'
                  });
                } else {
                  self.loading = false;
                }
              })
              .catch(error => {
                self.loading = false;
              });
          }
        });
      },
    }
  };
</script>
<style>
</style>